/*
 * Poppins, als Datei im Projekt und nicht von Google geladen.
 *
 * Die App muss ohne Netz starten, das ist der halbe Sinn einer installierten
 * Web App. Eine Schrift von einem fremden Server bricht dort weg, und die
 * Seite springt beim ersten Öffnen ohne Empfang in die Systemschrift. Ausserdem
 * verrät jeder Abruf an fonts.gstatic.com, wann jemand die App aufmacht, und
 * bei einer App, in der Notizen über Therapie und Familie liegen, ist das
 * nichts, was man nebenbei mitliefert.
 *
 * Nur die lateinische Teilmenge, zwei Schnitte, zusammen 16 Kilobyte. Der
 * Bereich U+0000 bis U+00FF deckt ä, ö, ü und ß ab.
 *
 * 500 und 600, weil die Wortmarke auf dem Sprung zwischen den Gewichten
 * beruht. 300 fehlt hier bewusst: das Light gibt es nur in der Wortmarke, und
 * die liegt als Pfad vor. Eine dritte Datei für zwei Buchstaben wäre
 * Ladezeit ohne Gegenwert.
 *
 * SIL Open Font License 1.1, der Text liegt in apps/pwa/schrift/OFL.txt.
 */
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./schrift/poppins-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("./schrift/poppins-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}

/*
  Markenfarben daevo.

  --brand ist das Logoblau aus dem Personal Coach Aaron Logo. Es hat auf Weiß
  nur einen Kontrast von 1.57 zu 1 und taugt dort nicht für Text oder Knopf
  Beschriftungen. Auf dunklem Grund liegt es bei 12.05 zu 1 und ist dort ideal.
  --brand-deep ist die abgedunkelte Variante für helle Oberflächen,
  Kontrast 4.51 zu 1 gegen Weiß, damit erfüllt sie WCAG AA.

  Deshalb zeigt --accent im dunklen Modus das Logoblau und im hellen Modus den
  dunklen Ton. --on-accent ist jeweils die Schriftfarbe darauf.
*/
:root {
  /* ---------- Marke ---------- */
  --brand: #96d8f0;
  --brand-deep: #1e7fa8;
  /* Für Text auf hellem Grund. --brand-deep erreicht auf #f6f8fa nur 4.24 zu 1
     und ist dort für Fliesstext zu schwach. Dieser Ton liegt bei 4.98. */
  --brand-text: #1b7399;

  /* ---------- Schrift ----------
   *
   * Zwei Rollen. Poppins trägt Überschriften und Zahlen, die Systemschrift
   * den Fliesstext. Eine geometrische Schrift wie Poppins ist auf 13 Pixeln
   * Lauftext schlechter lesbar als die Systemschrift, weil ihre runden
   * Formen eng laufen und die Unterschiede zwischen a, o und e kleiner
   * werden. In einer Zahl von 48 Pixeln ist genau diese Geometrie der Grund,
   * sie zu nehmen: die Null ist ein Kreis, wie der Ring, in dem sie steht.
   *
   * Der Rückfall ist nicht beliebig. Fehlt Poppins, soll etwas Geometrisches
   * kommen und keine Serifenschrift aus der Voreinstellung. */
  --schrift-display: "Poppins", ui-rounded, "Avenir Next", "Segoe UI Variable Display",
    system-ui, -apple-system, sans-serif;

  /* ---------- Flächen ----------
   *
   * Die Neutraltöne sind nicht neutral. Sie tragen einen leichten Blaustich in
   * Richtung des Logoblaus, rund vier Prozent Sättigung. Ein reines Grau neben
   * einer kühlen Markenfarbe wirkt schmutzig, und die Palette fällt in zwei
   * Hälften auseinander: hier die Marke, da der Rest. Der Stich ist zu gering,
   * um als Farbe gelesen zu werden, und genau darum geht es.
   */
  --bg: #0b0e14;
  --panel: #131822;
  --panel-2: #0f141c;
  /* Für Elemente, die auf einem Panel liegen und sich davon abheben müssen. */
  --erhoben: #1a2130;

  /* ---------- Die starke Fläche ----------
   *
   * Für den einen Knopf, der sich von allem abheben soll. Beide Modi tragen
   * Markenblau statt Weiss oder Schwarz: der Knopf hebt sich ab, ohne den
   * härtesten Kontrast der Palette zu verbrauchen. Im dunklen Modus das
   * Logoblau, im hellen ein abgedunkeltes Blau derselben Familie.
   *
   * Die Werte sind gerechnet. Dunkel: Text #0b0e14 auf #96d8f0 liegt bei
   * 12.31 zu 1, die Unterzeile bei Deckkraft 0.82 noch bei 5.84. Hell: Weiss
   * auf #186688 liegt bei 6.37 zu 1, die Unterzeile bei 0.82 noch bei 4.86.
   * Das dokumentierte #1e7fa8 reicht dort nicht: die Unterzeile käme auf 3.58
   * und läge unter 4.5.
   *
   * Der Kreis darauf trägt die jeweils andere Stufe derselben Farbe. */
  --stark: #96d8f0;
  --auf-stark: #0b0e14;
  --stark-marke: #1e7fa8;
  --auf-stark-marke: #ffffff;
  --border: #232b3a;
  /* Trennlinien innerhalb einer Fläche. Schwächer als ein Rahmen, weil sie
     gliedern und nicht abgrenzen. */
  --linie: rgba(255, 255, 255, 0.07);
  --text: #e8edf5;
  --muted: #8d97a8;
  --accent: var(--brand);
  --accent-text: var(--brand);
  --on-accent: #0b0d10;
  --good: #3fb950;
  --warn: #d29922;
  /* --alt und --water sind mit den Makrofarben weggefallen. Sie hatten keine
     Bedeutung ausser "die dritte Farbe" und "die vierte", und ein Token ohne
     Bedeutung wird beim nächsten Mal irgendwo eingesetzt, wo er nicht hingehört. */
  --bad: #f85149;

  /* ---------- Makrofarben ----------
   *
   * Vier Töne einer Familie, nicht vier Farben nebeneinander. Vorher trugen
   * die Balken die Zustandsfarben: Fett lief auf `--warn`, also auf der
   * Warnfarbe. Ein Makro ist keine Warnung, und das sieht man dem Balken an,
   * bevor man es benennen kann. Das Gelb stach heraus, weil es dafür gebaut
   * ist herauszustechen.
   *
   * Die vier Töne liegen auf einem Kreis um die Markenfarbe: Grün-Türkis,
   * Rose, Violett, Markenzyan. Ihre Helligkeit ist nicht geschätzt, sondern
   * gerechnet: jeder trifft auf der Spur genau 7.0 zu 1, im hellen Modus
   * genau 4.0 zu 1, bei überall derselben Sättigung von 0.62. Gleicher
   * Kontrast heisst gleiches Gewicht, gleiche Sättigung heisst gleiche
   * Farbkraft, und damit liest sich die Gruppe als System statt als vier
   * Einzelfarben. Ein Ton mit mehr Sättigung als die anderen springt heraus,
   * auch wenn die Helligkeit stimmt: genau das war beim ersten Versuch mit
   * dem Violett so.
   */
  /* ---------- Die fünf Bereiche des Balance Boards ----------
   *
   * Dieselbe Rechnung wie bei den Makros, und das ist der Punkt: eine App,
   * ein System. Fünf Farbtöne im Abstand von 40 Grad, überall dieselbe
   * Sättigung von 0.62, jeder auf der Spur genau 7.0 zu 1, im hellen Modus
   * genau 4.0 zu 1.
   *
   * Vorher standen fünf zufällige Farben in `rings.js`: Kontrast von 3.53 bis
   * 8.37, Sättigung von 0.56 bis 0.88, Farbtöne über den ganzen Kreis
   * verstreut. Das Gewicht stand damit verkehrt herum. Karriere ist bei
   * diesem Nutzer der grösste Bereich und trug den schwächsten Ton, Beziehung
   * der kleinste und den lautesten. Wer auf die Kacheln schaut, liest zuerst
   * die Farbe und erst danach die Zahl.
   *
   * Kein Gelb und kein Orange. Beides trägt in dieser App die Bedeutung
   * Warnung, und ein Lebensbereich ist keine Warnung.
   *
   * Sie stehen hier und nicht mehr in JavaScript, weil sie sonst in beiden
   * Farbmodi gleich bleiben. Ein Ton, der auf Schwarz stimmt, stimmt auf
   * Weiss nicht.
   */
  --bereich-karriere: #42bad3;
  --bereich-fitness: #2ec379;
  --bereich-wellbeing: #9ca9e8;
  --bereich-me_time: #c29ce8;
  --bereich-beziehung: #e591c9;

  --makro-protein: #2ec28c;
  --makro-fett: #e694ad;
  --makro-kohlenhydrate: #b6a0e9;
  --makro-wasser: #4cb9d5;
  /* Die Spur hinter dem Balken. Stand vorher als fester Wert in der Regel und
     war damit im hellen Modus nur über eine zweite Regel zu retten. */
  --spur: #1b2230;

  /* ---------- Typografie ----------
   *
   * Eine modulare Skala mit dem Verhältnis 1.2. Vorher standen elf Grössen
   * zwischen 12 und 20 Pixeln im Stylesheet, darunter 12.5, 13.5, 14.5, 15.5
   * und 16.5. Jede für sich plausibel, zusammen ohne System, und genau das
   * liest man einer Oberfläche an, ohne es benennen zu können.
   */
  --t-2xs: 11px;
  --t-xs: 12px;
  --t-sm: 13px;
  --t-md: 15px;
  --t-lg: 17px;
  --t-xl: 20px;
  --t-2xl: 24px;
  --t-3xl: 30px;
  --t-4xl: 40px;

  /* Grosse Schrift braucht engere Laufweite, kleine eine weitere. Ohne das
     wirken Überschriften auseinandergezogen und Kleinstschrift gedrängt. */
  --track-eng: -0.02em;
  --track-normal: 0;
  --track-weit: 0.02em;
  --track-versal: 0.08em;

  /* ---------- Abstände ----------
   *
   * Alles auf einem Vierer Raster. Ein Layout, in dem 13, 18 und 26 Pixel
   * nebeneinander stehen, hat keinen Rhythmus, und Rhythmus ist der halbe
   * Unterschied zwischen zusammengesetzt und entworfen.
   */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-8: 32px;
  --s-10: 40px;
  --s-12: 48px;

  /* ---------- Ecken ---------- */
  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;
  --radius: var(--r-md);

  /* ---------- Tiefe ----------
   *
   * Drei Stufen statt zufälliger Schatten. Im dunklen Modus kommt zu jedem
   * Schatten ein Lichtsaum an der Oberkante: dunkle Oberflächen erzeugen
   * Tiefe über Licht, nicht über Schatten, weil ein Schatten auf Schwarz
   * unsichtbar ist. Dieses Detail unterscheidet eine gebaute Oberfläche von
   * einer zusammengesetzten.
   */
  --schatten-1: 0 1px 2px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --schatten-2: 0 4px 16px -4px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  --schatten-3: 0 16px 40px -12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.06);

  /* ---------- Bewegung ----------
   *
   * Eine Kurve für alles. Sie startet schnell und läuft weich aus, wie eine
   * Bewegung mit Masse. Lineare Übergänge wirken maschinell.
   */
  --kurve: cubic-bezier(0.2, 0.8, 0.2, 1);
  /* Für den Startbildschirm. Zieht sanfter an als --kurve, die für Knöpfe
     gemacht ist und am Anfang zu schnell losläuft. */
  --kurve-start: cubic-bezier(0.22, 0.61, 0.25, 1);
  --schnell: 140ms;
  --normal: 220ms;

  --bar: 52px;
  --composer: 64px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/*
  Das Attribut hidden muss jede Anzeigeregel schlagen. Ohne diese Zeile
  gewinnt zum Beispiel .setup mit display flex gegen die Vorgabe des Browsers,
  weil Angaben aus dem eigenen Stylesheet immer vor denen des Browsers kommen.
  Folge wäre: das Onboarding bleibt nach dem Speichern sichtbar.
*/
[hidden] { display: none !important; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  overscroll-behavior-y: none;
}

body { padding-top: env(safe-area-inset-top); }

.screen { max-width: 620px; margin: 0 auto; }

/*
  Startbildschirm.

  Er liegt über allem und blendet sich selbst aus. Die Zeiten stehen auch in
  js/app.js, weil das Skript ihn aus dem Baum nimmt. Ändert man eine Zahl,
  gehört die andere mit geändert: 1300 ms stehen, 400 ms blenden.
*/
.splash {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
  overflow: hidden;
  animation: splash-auf 300ms ease-out both;
}
.splash.geht { opacity: 0; transition: opacity 400ms ease; }
.splash-inner { position: relative; z-index: 1; }
.splash-inner img { height: auto; max-width: 66vw; }

/*
  Der Start der App.

  Die Marke kommt nicht fertig ins Bild, sie entsteht: erst Licht aus der
  Mitte, dann wird die Wortmarke aus der Unschärfe heraus scharf und bekommt
  zuletzt ihre Farbe. Zwei Sekunden, weil ruhig nur wirkt, wenn man Zeit
  lässt. Wer es eilig hat, tippt einmal und ist sofort drin.

  Zwei Ebenen, weil sie sich verschieden bewegen müssen: der Schein wächst
  aus einem Punkt, die Marke bleibt an ihrem Platz und schärft sich nur.
  Beides in einer Animation ginge nicht.
*/
.splash-schein {
  position: absolute; left: 50%; top: 50%;
  width: 150vw; aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at 50% 50%,
    rgba(150, 216, 240, 0.30) 0%,
    rgba(30, 127, 168, 0.12) 40%,
    transparent 70%);
  animation: splash-schein 2000ms var(--kurve-start) both;
}
.splash-inner { animation: splash-marke 2000ms var(--kurve-start) both; }

/* Auf hellem Grund trägt das Logoblau nicht, es verschwindet im Weiss.
   Dort kommt der Schein aus dem dunklen Blau und bleibt deutlich schwächer:
   ein Lichtschein auf Weiss wird sonst zu einem grauen Fleck. */
:root[data-theme="light"] .splash-schein {
  background: radial-gradient(circle at 50% 50%,
    rgba(30, 127, 168, 0.16) 0%,
    rgba(30, 127, 168, 0.07) 40%,
    transparent 70%);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .splash-schein {
    background: radial-gradient(circle at 50% 50%,
      rgba(30, 127, 168, 0.16) 0%,
      rgba(30, 127, 168, 0.07) 40%,
      transparent 70%);
  }
}

@keyframes splash-auf { from { opacity: 0; } to { opacity: 1; } }
@keyframes splash-schein {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.35); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes splash-marke {
  0%   { opacity: 0; transform: scale(0.97); filter: blur(5px) brightness(0.4); }
  100% { opacity: 1; transform: none; filter: blur(0) brightness(1); }
}

@media (prefers-reduced-motion: reduce) {
  .splash, .splash-inner, .splash-schein { animation: none; }
  .splash-schein { opacity: 1; }
}

/* Einkaufsliste */
.ek-stand {
  display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; padding: 2px 8px; border-radius: var(--r-pill); margin-bottom: 4px;
  border: 1px solid var(--border); color: var(--muted);
}
.ek-stand.gekauft { border-color: var(--good); color: var(--good); }
.ek-stand.zuhause { border-color: var(--accent); color: var(--accent); }
.list li.erledigt .li-title { text-decoration: line-through; opacity: 0.55; }
.list li.erledigt .li-sub { opacity: 0.55; }
.ek-knoepfe { display: flex; gap: 6px; }
.ek-knoepfe button { padding: 6px 10px; font-size: 12.5px; font-weight: 500; }

/* Mindeststandards */
.std-quote {
  display: flex; align-items: center; gap: 8px; margin-top: 6px;
}
.std-bar { flex: 1; height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
.std-bar i { display: block; height: 100%; background: var(--accent); }
.std-bar i.schwach { background: var(--warn); }
.std-bar i.rot { background: var(--bad); }
.std-zahl { font-size: 12px; color: var(--muted); min-width: 42px; text-align: right; }

/* Onboarding */
/* Spalte, nicht Zeile. Der Einstieg über eine Sicherung steht unter dem
   Fragebogen, nicht daneben: als zweite Spalte ragte er aus dem Bild. */
.setup { min-height: 100dvh; display: flex; flex-direction: column; align-items: stretch; padding: 0; }
.setup-inner { width: 100%; }

/*
  Der Anamnesebogen fuellt den Bildschirm. Kopf und Fuss stehen fest, nur die
  Mitte scrollt. So bleibt der Weiter Knopf auf dem Handy immer erreichbar,
  auch wenn die Tastatur offen ist.
*/
.setup-flow {
  width: 100%; min-height: 100dvh;
  display: flex; flex-direction: column;
}
.setup-head { padding: 18px 18px 0; }
.setup-fortschritt {
  height: 4px; border-radius: 2px; background: var(--border); overflow: hidden;
}
.setup-fortschritt i { display: block; height: 100%; background: var(--accent); transition: width 0.35s ease; }
.setup-zaehler { font-size: 12.5px; color: var(--muted); margin-top: 8px; }
.setup-body { flex: 1; overflow-y: auto; padding: 18px 18px 8px; -webkit-overflow-scrolling: touch; }
.setup-body h1 { font-size: 25px; }
.setup-lockup { margin: 0 0 20px; }
.setup-lockup img { height: auto; max-width: 58vw; }
.setup-fuss {
  display: flex; gap: 10px; align-items: center;
  padding: 12px 18px calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border); background: var(--bg);
}
.setup-fuss .primary { margin-left: auto; min-width: 132px; }
.setup-hinweis { min-height: 20px; font-size: 13.5px; color: var(--warn); margin-top: 10px; }

/* Auswahlkarten, eine pro Zeile, damit der Text nie umbricht und ueberlappt. */
.opts { display: grid; gap: 9px; }
.opt {
  display: flex; flex-direction: column; gap: 3px; text-align: left;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  padding: 13px 15px; font-weight: 500;
}
.opt b { font-weight: 600; font-size: 15.5px; }
.opt span { font-size: 13.5px; color: var(--muted); line-height: 1.4; }
.opt.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.opt.on span { color: var(--text); opacity: 0.75; }
.opt-zaehler { font-size: 12.5px; color: var(--muted); margin-top: 8px; }

/* Freie Mehrfachauswahl, zum Beispiel Unvertraeglichkeiten. */
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-pill); padding: 8px 14px; font-size: 14px; font-weight: 500;
}
.pill.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* Körperfett schätzen. Vier Figuren, deshalb zwei mal zwei statt drei nebeneinander. */
.figuren { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.figur {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  padding: 12px 8px 10px;
}
/* Die Höhe führt, nicht die Breite. Sonst passt der Browser das Bild in eine
   Box, die breiter ist als nötig, und die Figur wird winzig in der Mitte. */
.figur-bild {
  height: 190px; width: auto; max-width: 100%; display: block; margin: 0 auto;
  opacity: 0.86; transition: opacity 160ms ease, transform 160ms ease;
}
.figur b { font-size: 15px; font-weight: 700; }
.figur span { font-size: 12px; color: var(--muted); line-height: 1.25; text-align: center; }
.figur.on { border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.figur.on .figur-bild, .figur:hover .figur-bild { opacity: 1; }
.figur.on .figur-bild { transform: scale(1.03); }
.figur.on span { color: var(--text); }
.figur-hinweis {
  margin-top: 12px; font-size: 13.5px; color: var(--muted); line-height: 1.45;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 11px 13px;
}

@media (min-width: 560px) {
  .figuren { grid-template-columns: repeat(4, 1fr); }
}
.brand-lockup { margin: 0 0 26px; }
.brand-lockup img { height: auto; max-width: 62vw; }
.head-mark { height: 17px; width: auto; margin-bottom: 9px; opacity: 0.95; }
h1 { font-size: 26px; margin: 0 0 6px; letter-spacing: -0.02em; }
.lead { color: var(--muted); margin: 0 0 22px; }

/* Formulare */
.field { margin-bottom: 14px; flex: 1; min-width: 0; }
.field-row { display: flex; gap: 12px; }
label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 5px; }
input, select, textarea {
  width: 100%;
  font: inherit;
  font-size: 16px;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 11px 12px;
  appearance: none;
}
/* Kein Ziehgriff. Er sitzt an der abgerundeten Ecke und sieht dort aus wie
   ein Fehler. Die Zeilenzahl steht ohnehin am Element. */
textarea { resize: none; line-height: 1.45; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }

button {
  font: inherit; font-weight: 600; font-size: 16px;
  border-radius: var(--r-sm); border: 1px solid transparent;
  padding: 12px 18px; cursor: pointer;
}
button.primary { background: var(--accent); color: var(--on-accent); }
button.ghost { background: transparent; border-color: var(--border); color: var(--text); }
button.danger { background: transparent; border-color: var(--bad); color: var(--bad); }
button.big { width: 100%; margin-bottom: 12px; }
button:active { transform: scale(0.985); }
button:disabled { opacity: 0.5; }

.fineprint { font-size: 12.5px; color: var(--muted); line-height: 1.5; margin: 10px 0 24px; }

/* App Layout */
.page-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin: 12px 0 18px; }
.page-head h1 { font-size: 24px; margin: 0; }
.sub { color: var(--muted); font-size: 14px; margin: 4px 0 0; }
.badge {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-pill);
  padding: 6px 13px; font-size: 13px; font-weight: 600; white-space: nowrap;
}
.section-title { font-size: 13px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); margin: 26px 0 10px; }

/* Ring */
/* ---------- Der Held ----------
 *
 * Eine Seite hat einen Helden oder keinen. Vorher standen auf Heute zwei
 * grosse Ringe übereinander, der obere mit einer abgeleiteten Punktzahl. Zwei
 * Helden sind keiner: das Auge sucht, statt zu lesen.
 *
 * Der Held trägt keinen Kasten. Ein Rahmen um das Wichtigste auf der Seite
 * macht es zu einem Objekt neben anderen Objekten. Was ihn zusammenhält, ist
 * der Abstand zu seinen Nachbarn.
 */
.held {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--s-2); padding: var(--s-1) 0 var(--s-4);
}
.held-ring { position: relative; width: 196px; height: 196px; }
.held-ring .ring { width: 196px; height: 196px; }
/* Dünner als der kleine Ring. Eine Spur, die mitwächst, wird zum Reifen: auf
   196 Pixeln trägt dieselbe Stärke von fünf optisch doppelt so viel wie auf
   132, und der Ring nimmt der Zahl in seiner Mitte das Gewicht. */
.held-ring .ring circle { stroke-width: 3.6; }
.held-zahl {
  font-size: var(--t-4xl); font-weight: 680; letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums; line-height: 1;
}
.held-label { font-size: var(--t-sm); color: var(--muted); margin-top: var(--s-2); }
/* Die Nebenzahlen stehen in einer Zeile und nicht in einer Tabelle daneben.
   Gegessen und Ziel erklären die grosse Zahl, sie konkurrieren nicht mit ihr. */
.held-satz {
  margin: 0; font-size: var(--t-sm); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.held-satz b, .held-satz span:not(.held-punkt) { color: var(--text); font-weight: 600; }
.held-punkt {
  display: inline-block; width: 3px; height: 3px; border-radius: 50%;
  background: currentColor; opacity: 0.5; margin: 0 var(--s-2) 3px;
}

.ring-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px; display: flex; gap: 18px; align-items: center;
}
.ring-wrap { position: relative; width: 132px; height: 132px; flex: 0 0 132px; }
.ring { width: 132px; height: 132px; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-width: 5; stroke-linecap: round; }
/* Die Spur nimmt dieselbe Farbe wie der Ring, nur gedimmt. So sieht der
   Kalorienring genauso aus wie der Ring im Logo. */
.ring-bg { stroke: var(--brand); stroke-opacity: 0.18; }
.ring-fg { stroke: var(--accent); stroke-dasharray: 326.7; stroke-dashoffset: 326.7; transition: stroke-dashoffset 0.5s ease; }
.ring-center {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
}
.ring-num { font-size: 28px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.ring-label { font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.ring-side { flex: 1; min-width: 0; }
.mini { display: flex; justify-content: space-between; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.mini:last-child { border-bottom: none; }
.mini-k { color: var(--muted); }
.mini-v { font-weight: 650; font-variant-numeric: tabular-nums; }

/* ---------- Messwerte ----------
 *
 * Ein Ring ist die falsche Form für einen kleinen Anteil. Drei Prozent auf
 * einem Ring sind ein Stummel von zehn Grad, und daneben steht eine Zahl, die
 * das Gleiche noch einmal sagt. Fünf davon nebeneinander ergeben ausserdem
 * eine Reihe zu drei und eine zu zwei, also eine Waise.
 *
 * Ein Balken trägt jeden Anteil von null bis über hundert, liest sich in
 * einer Spalte untereinander und lässt Name, Wert und Ziel auf einer Zeile
 * stehen. Dieselbe Form wie bei den Makros: eine App, ein System.
 */
.messwerte { display: flex; flex-direction: column; gap: var(--s-4); margin: var(--s-4) 0 var(--s-2); }
.messwert { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 0; color: inherit; }
button.messwert { cursor: pointer; }
button.messwert:active { opacity: 0.65; }
.messwert-kopf {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--s-3); margin-bottom: var(--s-2);
}
.messwert-name { font-size: var(--t-sm); font-weight: 600; letter-spacing: -0.005em; }
.messwert-wert { font-size: var(--t-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.messwert-wert b { color: var(--text); font-weight: 650; }
.messwert-zusatz { color: var(--muted); font-weight: 500; }
.messwert.gross .messwert-name { font-size: var(--t-md); }
.messwert.gross .messwert-wert b { font-size: var(--t-xl); letter-spacing: -0.02em; }
/* Die Farbe kommt je Zeile über eine Variable, nicht über eine Klasse je
   Bereich. Fünf Klassen für fünf Farben wären fünf Stellen, an denen eine
   Farbe später nicht mitgezogen wird. */
.messwert .balken > i { background: var(--ton, var(--brand)); }
/* Über dem Ziel. Nicht rot, denn über einem Fitnessziel zu liegen ist kein
   Fehler. Eine Schraffur sagt "voll und darüber hinaus", eine volle Spur
   allein sähe aus wie genau erreicht. */
.messwert .balken > i.drueber {
  background-image: repeating-linear-gradient(115deg,
    rgba(0, 0, 0, 0.2) 0 2px, transparent 2px 9px);
}

/* Balken */
/* Die Gruppe hiess ebenfalls `.bars`, genau wie das Menuesymbol in der
   Kopfzeile. Dasselbe Muster wie bei `.bar`: ein Name, zwei Bauteile. */
.balken-gruppe { margin-top: var(--s-4); }
/*
 * Die Makrobalken.
 *
 * Sie hiessen `.bar`, genau wie die Kopfzeile jeder Ansicht. Die Regel für die
 * Kopfzeile steht weiter unten im Stylesheet und hat gewonnen: die Balken
 * wurden 52 Pixel hoch statt acht, bekamen seitlichen Innenabstand und
 * `display: flex`. Deshalb der eigene Name. Zwei Bauteile mit einem
 * Klassennamen ist keine Frage der Ordnung, sondern ein Fehler, der irgendwann
 * eintritt.
 */
.balken-zeile { margin-bottom: var(--s-3); }
.balken-kopf {
  display: flex; justify-content: space-between;
  font-size: var(--t-sm); margin-bottom: var(--s-2);
}
.balken-kopf span:last-child { color: var(--muted); font-variant-numeric: tabular-nums; }

.balken { height: 8px; border-radius: var(--r-pill); background: var(--spur); overflow: hidden; }
.balken > i {
  display: block; height: 100%; width: 0;
  border-radius: var(--r-pill);
  transition: width 0.4s var(--kurve);
}
.balken > i.protein { background: var(--makro-protein); }
.balken > i.fett { background: var(--makro-fett); }
.balken > i.kohlenhydrate { background: var(--makro-kohlenhydrate); }
.balken > i.wasser { background: var(--makro-wasser); }
/* Über dem Ziel ist kein Makro mehr, sondern eine Aussage. Hier darf die
   Warnfarbe stehen, denn hier ist es eine Warnung. */
.balken > i.over { background: var(--bad); }

.quick { display: flex; gap: 9px; margin-top: 16px; }
.chip {
  flex: 1; background: var(--panel); border: 1px solid var(--border); color: var(--text);
  font-size: 14.5px; font-weight: 600; padding: 11px 6px;
}

/* Menuegruppen */
.menu-gruppe { margin-bottom: 9px; }
.menu-kopf {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 15px 16px; color: var(--text); text-align: left;
}
.menu-kopf b { font-size: 16px; font-weight: 650; }
.menu-kopf .chev-ab {
  display: block; width: 9px; height: 9px; margin-right: 4px;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.2s ease;
}
.menu-kopf[aria-expanded="true"] { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.menu-kopf[aria-expanded="true"] .chev-ab { transform: rotate(-135deg) translate(-3px, -3px); }
.menu-unter { padding: 8px 0 2px 12px; }
.menu-unter .menu-item { margin-bottom: 7px; }
.menu-item.gross b { font-size: 17px; }
.menu-item.leise { margin-top: 6px; opacity: 0.85; }

/* Ringe und das Balance Board */
.seg {
  display: flex; gap: 6px; background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 4px; margin-bottom: 16px;
}
.seg-btn {
  flex: 1; background: transparent; border: 0; color: var(--muted);
  font-size: 14px; font-weight: 600; padding: 9px 4px; border-radius: var(--r-sm);
}
.seg-btn.is-on { background: var(--panel-2); color: var(--text); }

.ring-buehne {
  display: flex; align-items: center; justify-content: center; gap: 18px;
  flex-wrap: wrap; margin-bottom: 6px;
}
/* Ein leerer Platzhalter darf den Ring nicht aus der Mitte schieben. */
.ring-buehne > div:empty { display: none; }
.ring-stapel svg, .ring-tag svg { display: block; color: var(--text); }

/* Flex statt Grid, damit die zweite Reihe mittig steht statt links zu kleben.
   Fünf Kacheln auf drei Spalten sehen sonst aus wie ein Fehler. */
.ring-kacheln {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 10px; margin: 14px 0 6px;
}
/*
 * Alle Kacheln gleich hoch, egal wie lang ihre Beschriftung ist.
 *
 * "Familie und Beziehung" bricht auf zwei Zeilen um, und ohne eine gemeinsame
 * Höhe steht die untere Reihe dann tiefer als die obere. Die Kommentarzeile
 * dafür stand schon hier, die Höhe fehlte: eine Absicht, die nur als Text
 * existiert, ist keine.
 *
 * Fünf Kacheln füllen keine Dreierreihe, die letzte Reihe bleibt also halb
 * leer. Das ist bewusst in Kauf genommen. Die Alternative wären fünf Zeilen
 * über die volle Breite, und die kosten auf Heute eine halbe Bildschirmhöhe
 * für eine Übersicht, die man im Vorbeigehen liest.
 */
.ring-kachel {
  flex: 0 1 calc(33.333% - 7px); min-width: 96px; min-height: 152px;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: var(--s-3) var(--s-2) var(--s-3); text-align: center; color: var(--text);
}
/* Nur wo eine Wertzeile steht, also auf dem Balance Board. Auf Heute gibt es
   keine, dort wuerde die feste Hoehe nur Leerraum erzeugen. */
.ring-kachel:has(.k-wert) { min-height: 158px; }
.ring-kachel svg { margin: 0 auto; }
.ring-kachel .k-name { font-size: 12.5px; font-weight: 600; margin-top: 7px; }
.ring-kachel .k-wert { font-size: 12px; color: var(--muted); margin-top: 2px; }

.ziel-zeile {
  display: flex; align-items: center; gap: 10px; margin-bottom: 9px;
}
.ziel-zeile span { flex: 1; font-size: 14.5px; }
.ziel-zeile input { width: 92px; }

/* Die Wertung, Kennzahlen oben, grosser Ring darunter */
.wertung {
  display: flex; flex-direction: column; align-items: center;
  padding: 4px 0 10px;
}
.metriken {
  display: flex; justify-content: center; gap: 26px; width: 100%;
  margin-bottom: 2px;
}
.metrik { text-align: center; color: var(--text); }
.metrik.klickbar { cursor: pointer; }
.metrik.klickbar:active { opacity: 0.6; }
.metrik-name { font-size: 13px; color: var(--muted); margin-bottom: 3px; }
.metrik-zeile { display: flex; align-items: center; justify-content: center; gap: 5px; }
.metrik-zeile svg { display: block; }
.metrik-wert { font-size: 17px; font-weight: 500; font-variant-numeric: tabular-nums; }
.metrik-pfeil {
  display: block; width: 9px; height: 9px;
  border-top: 1.6px solid var(--muted); border-right: 1.6px solid var(--muted);
}
.metrik-pfeil.hoch { transform: rotate(-45deg); border-color: var(--good); }
.metrik-pfeil.runter { transform: rotate(135deg); border-color: var(--warn); }
/*
 * Unverändert ist ein Strich, kein Pfeil.
 *
 * Um 45 Grad gedreht ergab die Pfeilform einen Winkel nach rechts, und der
 * liest sich als "hier tippen", nicht als "gleich geblieben". In einer Zeile
 * neben echten Richtungspfeilen sah das aus, als wären die Symbole zufällig
 * gewählt.
 */
.metrik-pfeil.gleich {
  width: 10px; height: 0; border-right: 0;
  border-top: 1.6px solid var(--muted); opacity: 0.55; transform: translateY(4px);
}
.wertung svg { color: var(--text); display: block; }
.wertung-satz {
  font-size: 13.5px; color: var(--muted); text-align: center;
  line-height: 1.5; margin: 2px 0 0; max-width: 34ch;
}

/* Listen */
/* Der Knopf fürs Kopf leeren. Text statt Symbol, weil ein Symbol dafür
   niemand versteht und die Funktion sonst unbenutzt bleibt. */
.icon-btn.dump {
  width: auto; flex: 0 0 auto; padding: 0 8px; font-size: 12px; font-weight: 700;
  letter-spacing: 0.02em; color: var(--muted);
}
.icon-btn.dump[aria-pressed="true"] { color: var(--accent); }

.list { list-style: none; padding: 0; margin: 0; }
.list li {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 13px 14px; margin-bottom: 9px;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
}
.li-main { min-width: 0; }
.li-title { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.li-sub { font-size: 13px; color: var(--muted); margin-top: 3px; overflow-wrap: anywhere; }
.li-side { text-align: right; font-size: 14px; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--muted); }
.li-side b { display: block; color: var(--text); font-size: 15px; }
/* Die Einstufung unter einer Aufgabe ist ein Knopf, kein Text: ein Tipp
   schaltet sie weiter. Sie sieht trotzdem nicht wie ein Knopf aus, sonst
   wirkt jede Zeile wie eine Aufforderung. */
.stufe {
  background: none; border: none; padding: 3px 0 0; margin: 0;
  font-size: 13px; font-weight: 400; color: var(--muted); text-align: left;
  border-bottom: 1px dashed color-mix(in srgb, var(--muted) 45%, transparent);
}
.stufe[data-stufe="3"] { color: var(--text); }

.empty { color: var(--muted); font-size: 14px; padding: 4px 2px 8px; }

/* Vorformatierter Text, etwa die Wochenuebersicht aus dem Kalender.
   Umbruch erlaubt, damit auf einem schmalen Telefon nichts seitlich rausläuft. */
.pre {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 13px 14px; margin: 0 0 9px;
  font-family: inherit; font-size: 14px; line-height: 1.6;
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* Composer */
.composer { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; }
.composer textarea { background: var(--panel-2); }
/* Vier Knoepfe passen auf einem Telefon nicht in eine Zeile. Ohne Umbruch
   schiebt der letzte die ganze Seite nach rechts, und dann scrollt die App
   seitlich. Die Grundbreite von 0 laesst die Knoepfe schrumpfen, statt die
   Zeile zu sprengen. */
.composer-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 11px; }
.composer-actions button { flex: 1 1 0; min-width: 84px; white-space: nowrap; }
.feedback {
  margin-top: 14px; padding: 13px 14px; border-radius: var(--r-md);
  background: rgba(76, 141, 255, 0.1); border: 1px solid rgba(76, 141, 255, 0.35);
  font-size: 14.5px; line-height: 1.55;
}
.feedback.err { background: rgba(248, 81, 73, 0.1); border-color: rgba(248, 81, 73, 0.4); }
.feedback.ok { background: rgba(63, 185, 80, 0.1); border-color: rgba(63, 185, 80, 0.4); }

.feelings { display: flex; gap: 9px; flex-wrap: wrap; }
.feelings button {
  flex: 1 1 auto; background: var(--panel); border: 1px solid var(--border);
  color: var(--text); font-size: 14px; font-weight: 500; padding: 10px 12px;
}
.feelings button.on { border-color: var(--accent); color: var(--accent); }

.card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 16px; margin-bottom: 14px;
}
.card h3 { margin: 0 0 10px; font-size: 17px; }
.card ol, .card ul { margin: 10px 0 0; padding-left: 20px; }
.card li { margin-bottom: 6px; font-size: 14.5px; }
.kv { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 14.5px; }
.kv:last-child { border-bottom: none; }
.kv span { color: var(--muted); }
.kv b { font-variant-numeric: tabular-nums; }

/*
 * Der Hinweis sitzt am unteren Rand, nicht darüber.
 *
 * Der Abstand war fest auf die Höhe der Chateingabe gesetzt. Auf jeder anderen
 * Ansicht gibt es die nicht, und der Hinweis schwebte dort achtzig Pixel über
 * dem Rand, also mitten im Inhalt. Nur wenn der Assistent offen ist, weicht er
 * der Eingabe aus.
 */
.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom) + 20px);
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  padding: 11px 18px; border-radius: var(--r-pill); font-size: 14px; font-weight: 500;
  z-index: 40; max-width: 90vw; text-align: center;
  box-shadow: var(--schatten-3);
}
body:has([data-view="assistant"]:not([hidden])) .toast {
  bottom: calc(var(--composer) + env(safe-area-inset-bottom) + 18px);
}

/*
  Die App ist dunkel gedacht. :root trägt deshalb die dunkle Palette.
  Der helle Satz gilt in zwei Fällen: wenn das System hell steht und keine
  ausdrückliche Wahl getroffen wurde, oder wenn data-theme auf light steht.
  Der letzte Fall ist nötig, weil manche Umgebungen das Thema am Wurzelelement
  stempeln statt über prefers-color-scheme zu melden.
*/
:root[data-theme="light"] {
    --bg: #f5f7fb; --panel: #ffffff; --panel-2: #edf1f7; --erhoben: #ffffff;
    --border: #dce3ed; --linie: rgba(20, 26, 36, 0.08);
    --text: #141a24; --muted: #5b6675;
    --makro-protein: #1e7f5c; --makro-fett: #cf3161;
    --makro-kohlenhydrate: #7e58d8; --makro-wasser: #227a91;
    --bereich-karriere: #217b8c; --bereich-fitness: #1e804f;
    --bereich-wellbeing: #5167d6; --bereich-me_time: #924ed5;
    --bereich-beziehung: #c72f94;
    --spur: #e4e8ec;
    --accent: var(--brand-deep);
    --accent-text: var(--brand-text);
    --on-accent: #ffffff;
    --schatten-1: 0 1px 2px rgba(20, 26, 36, 0.06);
    --schatten-2: 0 4px 16px -6px rgba(20, 26, 36, 0.14);
    --schatten-3: 0 16px 40px -14px rgba(20, 26, 36, 0.2);
    --stark: #186688;
    --auf-stark: #ffffff;
    --stark-marke: #96d8f0;
    --auf-stark-marke: #0b0e14;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #f5f7fb; --panel: #ffffff; --panel-2: #edf1f7; --erhoben: #ffffff;
    --border: #dce3ed; --linie: rgba(20, 26, 36, 0.08);
    --text: #141a24; --muted: #5b6675;
    --makro-protein: #1e7f5c; --makro-fett: #cf3161;
    --makro-kohlenhydrate: #7e58d8; --makro-wasser: #227a91;
    --bereich-karriere: #217b8c; --bereich-fitness: #1e804f;
    --bereich-wellbeing: #5167d6; --bereich-me_time: #924ed5;
    --bereich-beziehung: #c72f94;
    --spur: #e4e8ec;
    --accent: var(--brand-deep);
    --accent-text: var(--brand-text);
    --on-accent: #ffffff;
    /* Auf hellem Grund trägt der Schatten die Tiefe, nicht das Licht. */
    --schatten-1: 0 1px 2px rgba(20, 26, 36, 0.06);
    --schatten-2: 0 4px 16px -6px rgba(20, 26, 36, 0.14);
    --schatten-3: 0 16px 40px -14px rgba(20, 26, 36, 0.2);
    --stark: #186688;
    --auf-stark: #ffffff;
    --stark-marke: #96d8f0;
    --auf-stark-marke: #0b0e14;
  }
}

:root[data-theme="light"] .ring-bg { stroke: var(--brand-deep); stroke-opacity: 0.25; }
:root[data-theme="light"] .toast { box-shadow: 0 8px 26px rgba(0, 0, 0, 0.14); }

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .ring-bg { stroke: var(--brand-deep); stroke-opacity: 0.25; }
  :root:not([data-theme="dark"]) .toast { box-shadow: 0 8px 26px rgba(0, 0, 0, 0.14); }
}

/* Logo Umschaltung, dieselbe Logik wie bei den Farben. */
img.only-dark { display: block; }
img.only-light { display: none; }
:root[data-theme="light"] img.only-dark { display: none; }
:root[data-theme="light"] img.only-light { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) img.only-dark { display: none; }
  :root:not([data-theme="dark"]) img.only-light { display: block; }
}

.li-side button { padding: 7px 13px; font-size: 13.5px; font-weight: 500; }


/* ==========================================================================
   Assistent
   Der Kreis ist das Erste, was man sieht. Alles andere ordnet sich unter.
   ========================================================================== */

#app { position: fixed; inset: 0; display: flex; flex-direction: column; }

.view {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top);
}

/*
 * Die App steht auf einem Verlauf statt auf einer Fläche.
 *
 * Oben der dunkle Grundton der Marke, unten das Logoblau, stark abgedunkelt.
 * Der Verlauf endet nicht in einer fremden Farbe, sondern in der eigenen:
 * derselbe Ton, aus dem auch der Kreis leuchtet.
 *
 * Auf allen Ansichten derselbe Verlauf, damit die App nicht in eine schöne
 * Seite und mehrere graue zerfällt. Auf dem Assistenten liegt er kräftiger,
 * weil dort nichts anderes um Aufmerksamkeit konkurriert.
 */
.view {
  background:
    radial-gradient(115% 55% at 50% 112%, color-mix(in srgb, var(--brand) 12%, transparent) 0%, transparent 70%),
    linear-gradient(180deg, var(--panel-2) 0%, var(--bg) 42%, color-mix(in srgb, var(--brand-deep) 11%, var(--bg)) 100%);
}
#assistant {
  background:
    radial-gradient(120% 62% at 50% 108%, color-mix(in srgb, var(--brand) 26%, transparent) 0%, transparent 72%),
    linear-gradient(180deg, var(--panel-2) 0%, var(--bg) 48%, color-mix(in srgb, var(--brand-deep) 22%, var(--bg)) 100%);
}

/* Der Verlauf gehört unter den ganzen Inhalt, nicht hinter jede Karte. */
.view > .scroll { background: none; }

.bar {
  flex: 0 0 auto; height: var(--bar);
  display: flex; align-items: center; gap: 10px;
  padding: 0 10px;
}
.bar h1 { font-size: 17px; margin: 0; font-weight: 650; }
.bar-spacer { width: 40px; }
.bar-status {
  flex: 1; text-align: center; font-size: 12.5px; color: var(--muted);
  letter-spacing: 0.05em; text-transform: lowercase;
}

.icon-btn {
  width: 40px; height: 40px; flex: 0 0 40px;
  display: grid; place-items: center;
  background: none; border: none; padding: 0; color: var(--text);
}
.icon-btn .bars, .icon-btn .bars::before, .icon-btn .bars::after {
  display: block; width: 18px; height: 2px; border-radius: 2px; background: currentColor;
}
.icon-btn .bars { position: relative; }
.icon-btn .bars::before, .icon-btn .bars::after { content: ""; position: absolute; left: 0; }
.icon-btn .bars::before { top: -6px; }
.icon-btn .bars::after { top: 6px; }
.icon-btn .close, .icon-btn .close::before {
  display: block; width: 18px; height: 2px; border-radius: 2px; background: currentColor;
  transform: rotate(45deg);
}
.icon-btn .close::before { content: ""; transform: rotate(-90deg); }
.icon-btn .chev {
  display: block; width: 11px; height: 11px;
  border-left: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); margin-left: 4px;
}
/*
 * Sprachausgabe.
 *
 * Vorher ein leerer Kreis mit gestricheltem Rand im Aus-Zustand. Ein Kreis
 * ist kein Lautsprecher, und gestrichelt gegen durchgezogen ist als einziger
 * Unterschied zwischen an und aus zu leise.
 *
 * Als SVG und nicht aus Rahmen zusammengesetzt. Ein Trichter aus
 * `border-left` mit durchsichtigem Rand oben und unten ergibt ein Dreieck,
 * das je nach Zeilenhöhe zwei Pixel neben dem Korpus sitzt, und die Welle als
 * halber Kreisrand wurde zur einzelnen Klammer. Für eine Form mit Schrägen
 * ist ein Pfad das richtige Mittel.
 */
.icon-btn .speaker { display: block; width: 22px; height: 22px; }
.speaker-korpus { fill: currentColor; }
.speaker-welle, .speaker-strich { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; }
/* An zeigt die Welle, aus zeigt das Kreuz. Eine Form, die sich ändert, liest
   sich schneller als eine Linienart, die sich ändert. */
.icon-btn[aria-pressed="true"] .speaker-strich,
.icon-btn[aria-pressed="false"] .speaker-welle { display: none; }
}

/* Bühne mit dem Kreis */
.stage {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 4px 20px 0;
  transition: flex-basis 0.35s ease;
}
#assistant.has-chat .stage { flex: 0 0 auto; padding: 8px 20px 2px; }

.orb {
  position: relative;
  width: min(68vw, 290px); aspect-ratio: 1;
  background: none; border: none; padding: 0;
  transition: width 0.35s ease;
  --glow: 0.25; --level: 0; --orb-scale: 1;
}
.orb-canvas { transform: scale(var(--orb-scale)); transform-origin: center; }
#assistant.has-chat .orb { width: min(34vw, 140px); }
.orb::after {
  content: ""; position: absolute; inset: -22%;
  transform: scale(var(--orb-scale));
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--brand) 45%, transparent) 0%, transparent 66%);
  opacity: calc(var(--glow) * 0.5);
  filter: blur(26px);
  transition: opacity 0.12s linear;
  pointer-events: none;
}
.orb-canvas {
  position: relative; display: block; width: 100%; height: 100%;
  filter:
    drop-shadow(0 0 calc(3px + var(--glow) * 7px) color-mix(in srgb, var(--brand) 85%, transparent))
    drop-shadow(0 0 calc(10px + var(--glow) * 22px) color-mix(in srgb, var(--brand) 45%, transparent));
}

.orb-hint { color: var(--muted); font-size: 13.5px; margin: 0; text-align: center; }
#assistant.has-chat .orb-hint { display: none; }

/*
 * Der Verlauf.
 *
 * Die Antwort steht ohne Blase da, als Text auf dem Grund. Eine Sprechblase um
 * zehn Zeilen Coaching macht daraus eine Chatnachricht, und eine Chatnachricht
 * liest man quer. Die eigene Nachricht behält eine Blase, damit man beim
 * Scrollen sofort sieht, wo man selbst gesprochen hat.
 */
.transcript {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 8px 16px 2px;
  display: flex; flex-direction: column; gap: 12px;
  -webkit-overflow-scrolling: touch;
}
#assistant:not(.has-chat) .transcript { flex: 0 0 auto; max-height: 34vh; }
.msg { overflow-wrap: anywhere; }
.msg.user { white-space: pre-wrap; }
.msg.user {
  align-self: flex-end; max-width: 84%;
  padding: 12px 16px; border-radius: var(--r-lg);
  font-size: 15.5px; line-height: 1.5;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 42%, transparent);
  color: var(--text);
}
.msg.assistant {
  align-self: stretch; max-width: 100%;
  padding: 2px 2px 10px;
  display: flex; flex-direction: column; gap: 9px;
  color: var(--text);
}
.msg-text {
  font-size: 16.5px; line-height: 1.62;
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/*
 * Die Marke über der Antwort.
 *
 * Klein, in der Markenfarbe, mit demselben Schimmer wie der Kreis. Sie steht
 * auch über der Antwort, die noch entsteht, und pulsiert dann ruhig. Ein
 * Absender ohne Marke sieht aus wie ein Systemhinweis.
 */
.marke {
  width: 22px; height: auto; display: block; flex: 0 0 auto;
  color: var(--accent);
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--brand) 55%, transparent));
}
.msg.pending .marke { animation: markePuls 1.6s ease-in-out infinite; }
@keyframes markePuls {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .msg.pending .marke { animation: none; opacity: 0.7; }
}
.msg.assistant + .msg.user { margin-top: 8px; }
.msg.pending .msg-text { color: var(--muted); font-style: italic; font-size: 15px; }
.msg-done { display: block; margin-top: 9px; font-size: 12px; color: var(--muted); }

.chips {
  flex: 0 0 auto; display: flex; gap: 8px; overflow-x: auto;
  padding: 8px 16px; scrollbar-width: none;
}
.chips::-webkit-scrollbar { display: none; }
.chips button {
  flex: 0 0 auto; background: var(--panel); border: 1px solid var(--border);
  color: var(--text); font-size: 13.5px; font-weight: 500; padding: 8px 14px; border-radius: var(--r-pill);
}
#assistant.has-chat .chips { display: none; }

/* Anhänge */
.anhang-leiste {
  flex: 0 0 auto; display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
  padding: 8px 12px 0;
}
.anhang-leiste::-webkit-scrollbar { display: none; }
.anhang {
  position: relative; flex: 0 0 auto; width: 64px; height: 64px;
  border-radius: var(--r-sm); overflow: hidden;
  background: var(--panel); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
}
.anhang img { width: 100%; height: 100%; object-fit: cover; display: block; }
.anhang .anhang-typ {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em; color: var(--muted); text-align: center;
  padding: 0 4px; line-height: 1.2; overflow-wrap: anywhere;
}
.anhang.laedt::after {
  content: ""; position: absolute; inset: 0; background: rgba(0,0,0,0.45);
  backdrop-filter: blur(1px);
}
.anhang.fehler { border-color: var(--bad); }
.anhang-weg {
  position: absolute; top: 2px; right: 2px; width: 20px; height: 20px; padding: 0;
  border-radius: 50%; border: none; background: rgba(0,0,0,0.62); color: #fff;
  font-size: 14px; line-height: 20px; font-weight: 700;
}

.icon-btn.clip { border-radius: 50%; background: none; border: none; }
/* Büroklammer aus zwei Bögen. Eine Grafik dafür zu laden wäre Verschwendung. */
.icon-btn.clip .clip-icon {
  display: block; width: 9px; height: 17px;
  border: 2px solid currentColor; border-radius: 9px;
  transform: rotate(35deg);
}
.icon-btn.clip .clip-icon::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 2px; height: 8px; background: currentColor; border-radius: 1px;
  transform: translate(-1px, -8px);
}
.icon-btn.clip[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }

.anhang-menue {
  position: absolute; left: 12px; right: 12px;
  bottom: calc(var(--composer) + env(safe-area-inset-bottom) + 10px);
  z-index: 30; display: flex; flex-direction: column; gap: 8px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}
.anhang-menue button { width: 100%; background: var(--panel-2); border: 1px solid var(--border); color: var(--text); }

/* Bilder in einer Nachricht */
.msg-bilder { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.msg-bilder img {
  width: 108px; height: 108px; object-fit: cover; border-radius: var(--r-sm); display: block;
  border: 1px solid var(--border);
}
.msg-dateien { font-size: 12.5px; opacity: 0.75; margin-bottom: 4px; }

/*
 * Die Eingabe ist eine Pille, keine Zeile mit Knöpfen daneben.
 *
 * Alles sitzt in einem Element: Mikrofon, Klammer, Kopf, Feld und Pfeil. Das
 * spart eine Trennlinie über die ganze Breite und lässt den Verlauf bis nach
 * unten durchlaufen, statt ihn abzuschneiden.
 */
.composer-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 2px;
  margin: 6px 12px calc(10px + env(safe-area-inset-bottom));
  padding: 5px 6px 5px 8px;
  border-radius: 26px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel) 82%, transparent);
  backdrop-filter: blur(14px);
}
.composer-bar input {
  flex: 1; min-width: 0;
  border: none; background: none; border-radius: 0;
  padding: 11px 8px; font-size: 15.5px;
}
.composer-bar input:focus { outline: none; box-shadow: none; }
.icon-btn.mic, .icon-btn.send { border-radius: 50%; background: none; border: none; }
.icon-btn.send { width: 34px; height: 34px; }
.icon-btn.clip .clip-icon { position: relative; }
.icon-btn.mic .mic-dot {
  display: block; position: relative;
  width: 11px; height: 15px; border-radius: 6px; background: currentColor;
}
.icon-btn.mic .mic-dot::after {
  content: ""; position: absolute; left: 50%; bottom: -8px; transform: translateX(-50%);
  width: 17px; height: 8px;
  border: 2px solid currentColor; border-top: none;
  border-radius: 0 0 10px 10px;
}
.icon-btn.mic[aria-pressed="true"] { background: var(--accent); border-color: transparent; color: var(--on-accent); }
.icon-btn.send { background: var(--accent); border-color: transparent; color: var(--on-accent); }
.icon-btn.send .arrow {
  display: block; width: 10px; height: 10px;
  border-top: 2px solid currentColor; border-right: 2px solid currentColor;
  transform: rotate(-45deg); margin-left: -3px;
}

/* Bereiche mit eigenem Scrollbereich */
.scroll > .sub:first-child { margin: 4px 0 18px; }
/* Ein Absatz direkt vor einem Feld braucht Luft, sonst klebt die Beschriftung
   des Feldes am letzten Satz und liest sich wie seine Fortsetzung. */
.sub + .field, .sub + .field-row { margin-top: 14px; }
.scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 16px calc(28px + env(safe-area-inset-bottom)); -webkit-overflow-scrolling: touch; }

/* Menue */
.menu {
  position: absolute; inset: 0; z-index: 30;
  background: var(--bg);
  padding: env(safe-area-inset-top) 16px calc(24px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 9px;
  overflow-y: auto;
}
.menu-head { display: flex; align-items: center; justify-content: space-between; height: var(--bar); margin-bottom: 8px; }
.menu-head img { height: 17px; width: auto; }
.menu-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-md); padding: 15px 16px; text-align: left; width: 100%;
}
.menu-item b { font-size: 16.5px; font-weight: 650; }
.menu-item span { font-size: 13px; color: var(--muted); font-weight: 400; }

.switch { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; font-size: 15px; }
.switch input { width: 20px; height: 20px; flex: 0 0 20px; accent-color: var(--accent); }

.reco { background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md); padding: 16px; margin-bottom: 11px; }
.reco h3 { margin: 0 0 6px; font-size: 16px; }
.reco p { margin: 0 0 8px; font-size: 14.5px; line-height: 1.5; }
.reco .grund { font-size: 12.5px; color: var(--muted); }

.mem-kind {
  display: inline-block; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); border: 1px solid var(--border); border-radius: var(--r-pill); padding: 2px 8px; margin-bottom: 5px;
}

@media (prefers-reduced-motion: reduce) {
  .orb, .stage, .orb::after { transition: none; }
}

/* Barcode. Das Videobild bleibt flach, damit die Seite nicht springt, wenn die
   Kamera erst nach einer halben Sekunde ein Bild liefert. */
.scan {
  margin: 10px 0 4px; padding: 12px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-lg);
  display: flex; flex-direction: column; gap: 10px;
}
.scan video {
  width: 100%; height: 190px; object-fit: cover;
  background: #000; border-radius: var(--r-md);
}
.scan-hinweis { font-size: 13.5px; color: var(--muted); }
.scan-eingabe { display: flex; gap: 8px; }
.scan-eingabe input { flex: 1; min-width: 0; }

/* Zeiten je Wochentag. Drei Spalten mit fester Tagesspalte, damit die
   Zeitfelder untereinander stehen und die Zeile nicht springt, sobald ein
   Wochentagskürzel zwei statt drei Zeichen hat. */
.wochenkopf, .wochenzeile {
  display: grid; grid-template-columns: 34px 1fr 1fr; gap: 8px; align-items: center;
}
.wochenkopf { margin-bottom: 6px; }
.wochenkopf span { font-size: 12px; color: var(--muted); text-align: center; }
.wochenzeiten { display: flex; flex-direction: column; gap: 7px; }
.wochenzeile .wt-tag { font-size: 13.5px; font-weight: 600; color: var(--text); }
.wochenzeile input { width: 100%; min-width: 0; }
.feld-hilfe { font-size: 12.5px; color: var(--muted); line-height: 1.5; margin: 9px 0 0; }

.tempo-marken {
  display: flex; justify-content: space-between;
  font-size: 12px; color: var(--muted); margin-top: 3px;
}

/* Die Schritte für den Siri Kurzbefehl. Eine nummerierte Liste, weil die
   Reihenfolge hier wirklich zählt: wer die Variable vor der Adresse einsetzt,
   bekommt einen Kurzbefehl, der nichts tut. */
/* Das Angebot aus der Zwischenablage. Es sitzt über der Eingabe und sieht
   bewusst nach Angebot aus, nicht nach Bedienelement: es ist nur nach einem
   Kurzbefehl sinnvoll und verschwindet nach zwei Minuten von selbst. */
.zwischenablage {
  display: block; width: calc(100% - var(--s-8)); margin: 0 var(--s-4) var(--s-2);
  padding: var(--s-3) var(--s-4); border-radius: var(--r-pill);
  border: 1px solid var(--brand); background: color-mix(in srgb, var(--brand) 14%, transparent);
  color: var(--text); font-size: var(--t-sm); font-weight: 600; text-align: center;
  transition: transform var(--schnell) var(--kurve);
}
.zwischenablage:active { transform: scale(0.98); }

/* Die Rohliste der Stimmen. Monospace, weil Name, Kürzel und Herkunft
   untereinander stehen sollen, und scrollbar, weil manche Geräte über
   sechzig Stimmen melden. */
.stimmen-roh {
  margin: var(--s-3) 0 0; padding: var(--s-3);
  border-radius: var(--r-md); border: 1px solid var(--border);
  background: var(--panel-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--t-xs); line-height: 1.6; color: var(--muted);
  white-space: pre; overflow-x: auto; max-height: 40vh; overflow-y: auto;
}

.siri-schritte {
  margin: var(--s-3) 0 0; padding-left: var(--s-5);
  color: var(--muted); font-size: var(--t-sm); line-height: 1.6;
}
.siri-schritte li { margin-bottom: var(--s-1); }
.siri-schritte b { color: var(--text); font-weight: 600; }
/* Die Adresse ist lang. Ohne den kleineren Schnitt steht sie halb im Feld. */
#e-siriUrl { font-size: var(--t-xs); }

/* Wochen Check-in. Die Fragen stehen einzeln, mit Luft dazwischen: ein Bogen
   aus achtzehn eng gesetzten Fragen wird durchgeklickt, nicht beantwortet. */
.wc-wahl { display: flex; gap: 8px; margin-bottom: 14px; }
.wc-wahl button { flex: 1; }
.wc-frage {
  padding: 15px 14px; margin-bottom: 11px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-lg);
}
.wc-frage > label, .wc-frage > .wc-text {
  display: block; font-size: 15.5px; font-weight: 600; line-height: 1.4; margin-bottom: 3px;
}
.wc-frage .wc-hinweis { font-size: 12.5px; color: var(--muted); margin-bottom: 10px; line-height: 1.45; }
.wc-frage.pflicht > .wc-text::after { content: " *"; color: var(--accent); }
.wc-frage input[type="text"], .wc-frage textarea, .wc-frage select { width: 100%; margin-top: 8px; }
.wc-skala { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.wc-skala input[type="range"] { flex: 1; min-width: 0; }
.wc-skala .wc-wert {
  min-width: 46px; text-align: center; font-size: 16px; font-weight: 700;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.wc-enden { display: flex; justify-content: space-between; font-size: 12px; color: var(--muted); margin-top: 2px; }
.wc-dauer { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.wc-dauer input { width: 74px; }
.wc-dauer span { font-size: 13.5px; color: var(--muted); }
.wc-aktionen { margin: 6px 0 18px; }
.wc-aktionen button { width: 100%; }

/* Schieberegler. Ohne eigene Formatierung zeichnen die Browser eine Spur in
   Systemfarbe, die auf dem dunklen Panel praktisch verschwindet: sichtbar
   bleibt nur der Punkt, und ein Punkt ohne Schiene sieht nicht aus, als
   liesse er sich ziehen. */
input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 30px; background: transparent; margin: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: var(--r-pill);
  background: linear-gradient(to right, var(--accent) 0%, var(--accent) var(--fuellung, 50%),
    rgba(255, 255, 255, 0.14) var(--fuellung, 50%), rgba(255, 255, 255, 0.14) 100%);
}
input[type="range"]::-moz-range-track {
  height: 6px; border-radius: var(--r-pill); background: rgba(255, 255, 255, 0.14);
}
input[type="range"]::-moz-range-progress {
  height: 6px; border-radius: var(--r-pill); background: var(--accent);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 24px; height: 24px; margin-top: -9px;
  border-radius: 50%; background: #fff; border: 2px solid var(--accent);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
}
input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%;
  background: #fff; border: 2px solid var(--accent);
}
/* Solange nichts gewaehlt wurde, ist die Spur durchgehend grau und der Griff
   ohne Farbe. Sonst sieht ein Regler in der Mitte aus wie eine Antwort. */
.wc-skala.offen input[type="range"]::-webkit-slider-runnable-track {
  background: rgba(255, 255, 255, 0.14);
}
.wc-skala.offen input[type="range"]::-webkit-slider-thumb { border-color: rgba(255, 255, 255, 0.3); }
.wc-skala.offen .wc-wert { color: var(--muted); }

/* Gespräche. Die Liste ist nach Ordnern gruppiert, aber flach gehalten: eine
   zweite Klickebene für sechs Ordner mit je zwei Gesprächen kostet mehr Wege,
   als sie spart. */
.suchzeile { margin-bottom: 12px; }
.suchzeile input { width: 100%; }
.gs-ordner { margin: 18px 0 9px; display: flex; align-items: center; gap: 8px; }
.gs-ordner .punkt { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.gs-ordner b { font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.gs-ordner .anzahl { font-size: 12.5px; color: var(--muted); margin-left: auto; }
.gs-eintrag {
  display: flex; align-items: flex-start; gap: 11px;
  width: 100%; text-align: left; padding: 13px 14px; margin-bottom: 8px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-lg);
  color: var(--text);
}
.gs-eintrag.on { border-color: var(--accent); }
.gs-eintrag .gs-text { flex: 1; min-width: 0; }
.gs-eintrag b { display: block; font-size: 15px; font-weight: 600; line-height: 1.35; }
.gs-eintrag .gs-meta { display: block; font-size: 12.5px; color: var(--muted); margin-top: 3px; }
.gs-eintrag .gs-stelle {
  display: block; font-size: 13px; color: var(--muted); margin-top: 5px; line-height: 1.45;
}
.gs-eintrag .gs-weg {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: transparent; border: 0; color: var(--muted); font-size: 17px; line-height: 1;
}
.gs-leer { color: var(--muted); font-size: 14.5px; line-height: 1.6; padding: 22px 2px; }
.icon-btn .plus { display: block; width: 20px; height: 20px; position: relative; }
/*
 * Gespräche.
 *
 * Vorher waren das drei gleich lange Striche, also genau das Menüsymbol
 * daneben. Zwei verschiedene Handlungen mit demselben Bild nimmt niemand als
 * zwei wahr: der Nutzer drückt eines von beiden und lernt nichts dazu.
 * Jetzt eine Liste mit Punkten davor.
 */
.icon-btn .stapel { display: block; width: 18px; height: 14px; position: relative; }
.icon-btn .stapel::before, .icon-btn .stapel::after { content: ""; position: absolute; background: currentColor; }
.icon-btn .stapel::before {
  left: 0; top: 0; width: 4px; height: 4px; border-radius: 50%;
  box-shadow: 0 5px 0 currentColor, 0 10px 0 currentColor;
}
.icon-btn .stapel::after {
  left: 7px; top: 1px; width: 11px; height: 2px; border-radius: 2px;
  box-shadow: 0 5px 0 currentColor, 0 10px 0 currentColor;
}
.icon-btn .plus::before, .icon-btn .plus::after {
  content: ""; position: absolute; background: currentColor; border-radius: 2px;
}
.icon-btn .plus::before { left: 9px; top: 2px; width: 2px; height: 16px; }
.icon-btn .plus::after { top: 9px; left: 2px; height: 2px; width: 16px; }

/* ---------- Struktur in langen Ansichten ---------- */

/*
 * Zwei Ebenen von Überschriften, die man auf einen Blick auseinanderhält.
 *
 * `.section-title` war beides zugleich: klein, grau, versal. In einer Ansicht
 * mit acht davon sieht jede aus wie die nächste, und der Nutzer muss lesen,
 * statt zu sehen. `.abschnitt` ist jetzt die obere Ebene: gross, in Textfarbe,
 * mit einer Linie darüber. Die Linie trennt stärker als jeder Abstand.
 */
.abschnitt {
  font-size: 20px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25;
  color: var(--text); margin: 34px 0 14px; padding-top: 22px;
  border-top: 1px solid var(--border);
}
/* Die erste Überschrift einer Ansicht braucht keine Trennlinie nach oben. */
.scroll > .abschnitt:first-child { margin-top: 6px; padding-top: 0; border-top: 0; }

/* Ein Knopf, der einen Abschnitt abschliesst, steht auf voller Breite. Ein
   halbbreiter Knopf mitten im Formular sieht aus, als gehörte er zum Feld
   daneben. */
.breit { width: 100%; margin-bottom: 4px; }

/* Feldzeilen brechen um. Ohne das quetscht ein drittes Feld die beiden anderen
   zusammen, statt in die nächste Zeile zu rutschen. */
.field-row { flex-wrap: wrap; }
.field-row > .field { flex: 1 1 140px; }

/* Mehr Luft zwischen den Feldern. Ein Formular mit vierzehn Zeilen auf einem
   Telefon liest sich nur mit Abstand. */
.field { margin-bottom: 18px; }
label { font-size: 13.5px; margin-bottom: 7px; }

/* ============================================================
   Feinschliff. Steht am Ende, damit es die gewachsenen Regeln
   darüber überschreibt, ohne dass jede einzelne angefasst wird.
   ============================================================ */

/*
 * Zahlen laufen tabellarisch.
 *
 * In der Standardeinstellung ist eine 1 schmaler als eine 8. Eine Liste mit
 * 1900, 2884 und 138 zappelt dadurch, und ein Zähler, der von 9 auf 10
 * springt, verschiebt alles daneben. Tabellarische Ziffern sind gleich breit.
 * Das ist die unauffälligste Verbesserung mit der grössten Wirkung.
 */
body { font-variant-numeric: tabular-nums; }

/*
 * Überschriften.
 *
 * Grosse Schrift bekommt engere Laufweite und mehr Fettung, kleine bleibt
 * offen. Ohne das wirkt eine 30 Pixel Zeile auseinandergezogen und eine 12
 * Pixel Zeile gedrängt, egal wie gut die Schrift ist.
 */
h1 { font-size: var(--t-lg); font-weight: 650; letter-spacing: var(--track-eng); }
.abschnitt {
  font-size: var(--t-xl); font-weight: 680; letter-spacing: var(--track-eng);
  line-height: 1.2; color: var(--text);
  margin: var(--s-10) 0 var(--s-4); padding-top: var(--s-6);
  border-top: 1px solid var(--linie);
}
.scroll > .abschnitt:first-child { margin-top: var(--s-2); padding-top: 0; border-top: 0; }
.section-title {
  font-size: var(--t-xs); font-weight: 620; text-transform: uppercase;
  letter-spacing: var(--track-versal); color: var(--muted);
  margin: var(--s-6) 0 var(--s-3);
}
.sub { font-size: var(--t-md); line-height: 1.6; color: var(--muted); }

/*
 * Eingaben.
 *
 * Sechzehn Pixel sind Pflicht, darunter zoomt iOS beim Antippen in das Feld
 * hinein. Der Rahmen ist eine Linie und kein Kasten: eine Fläche mit eigenem
 * Hintergrund neben einer Fläche mit eigenem Hintergrund erzeugt genau den
 * Baukasteneindruck, den niemand will.
 */
input, select, textarea {
  font-size: var(--t-lg);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 13px 14px;
  transition: border-color var(--schnell) var(--kurve), box-shadow var(--schnell) var(--kurve);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
label { font-size: var(--t-sm); font-weight: 550; color: var(--muted); letter-spacing: var(--track-weit); }

/*
 * Knöpfe.
 *
 * Ein Knopf, der beim Tippen nichts tut, fühlt sich tot an. Achtundneunzig
 * Prozent Grösse für hundertvierzig Millisekunden ist zu wenig, um es bewusst
 * zu sehen, und genug, um es zu spüren.
 */
button {
  font-size: var(--t-md); font-weight: 620; letter-spacing: var(--track-weit);
  border-radius: var(--r-sm);
  transition: transform var(--schnell) var(--kurve), background var(--schnell) var(--kurve),
              border-color var(--schnell) var(--kurve), opacity var(--schnell) var(--kurve);
}
button:active { transform: scale(0.98); }
button:disabled { opacity: 0.45; transform: none; }
.primary { box-shadow: var(--schatten-1); }

/*
 * Karten und Listen.
 *
 * Vorher hatte fast jedes Element seinen eigenen Kasten mit Rahmen. Zwanzig
 * gerahmte Flächen untereinander lesen sich als Liste von Behältern, nicht als
 * Inhalt. Die Karte bleibt, wird aber ruhiger: weicher Rahmen, eine Stufe
 * Tiefe, mehr Innenabstand.
 */
.card, .list > li, .ring-card {
  border-color: var(--linie);
  box-shadow: var(--schatten-1);
}
.card { padding: var(--s-5); border-radius: var(--r-lg); }

/* Die Kennzahl Zeilen in einer Karte werden durch Linien gegliedert, nicht
   durch Abstand. Das ist dichter und ruhiger zugleich. */
.kv { border-color: var(--linie); }

/* Pillen und Kacheln bekommen dieselbe Reaktion wie Knöpfe. */
.pill, .opt, .menu-item, .gs-eintrag, .wc-frage { transition: all var(--schnell) var(--kurve); }
.pill:active, .opt:active, .menu-item:active { transform: scale(0.98); }

/*
 * Der Rahmen um ein aktives Element ist zwei Pixel breit und liegt innen.
 * Ein einzelner Pixel verschwindet auf einem Telefon, und ein Rahmen, der die
 * Grösse des Elements ändert, lässt das Layout springen.
 */
.pill.on, .opt.on, .gs-eintrag.on {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Bereichsüberschrift in der Kopfzeile: dieselbe Behandlung wie eine
   Überschrift, nur kleiner. Vorher war sie fett und eng wie ein Titel. */
.bar h1 { font-size: var(--t-lg); }

/* Kleinstschrift bleibt lesbar. 11 Pixel ohne weitere Laufweite verschmiert
   auf einem hochauflösenden Display zu einer grauen Linie. */
.fineprint, .meta, .feld-hilfe, .gs-meta {
  font-size: var(--t-xs); letter-spacing: var(--track-weit); line-height: 1.55;
}

/*
 * Die Ringkacheln stehen ohne Kasten.
 *
 * Fünf gerahmte Flächen mit je einem Kreis darin lesen sich als Tabelle von
 * Behältern. Der Ring ist die Form, er braucht keinen zweiten Rahmen um sich.
 * Was die Kachel zusammenhält, ist der Abstand zu ihren Nachbarn, nicht eine
 * Linie.
 */
.ring-kachel {
  background: transparent; border: 0; box-shadow: none;
  padding: var(--s-3) var(--s-1) var(--s-2);
}
.ring-kachel:has(.k-wert) { min-height: 150px; }
/* Hierarchie in der Kachel: der Name führt, der Wert stützt. Vorher waren
   beide fett, dadurch trug keiner. */
.ring-kachel .k-name {
  font-size: var(--t-sm); font-weight: 600; color: var(--text);
  margin-top: var(--s-2); letter-spacing: var(--track-normal);
}
.ring-kachel .k-wert {
  font-size: var(--t-xs); font-weight: 500; color: var(--muted); margin-top: 2px;
}
.ring-kacheln { gap: var(--s-2) var(--s-1); margin: var(--s-4) 0 var(--s-2); }

/* Die Kennzahlzeile über dem grossen Ring bekommt Luft und eine ruhige
   Beschriftung. Vorher standen vier fette Wörter dicht an dicht. */
#tagMetriken { gap: var(--s-2); }
#tagMetriken .m-name {
  font-size: var(--t-xs); font-weight: 550; color: var(--muted);
  letter-spacing: var(--track-weit);
}

/*
 * Eine gewählte Pille wird getönt, nicht gefüllt.
 *
 * Vollflächig in der Akzentfarbe hat sie dasselbe Gewicht wie der Knopf, der
 * die Aktion auslöst. Wenn vier Pillen und ein Knopf gleich laut sind, führt
 * keiner. Die Tönung reicht völlig, um "ausgewählt" zu zeigen, und lässt die
 * Hauptaktion die Hauptaktion sein.
 */
.pill.on {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-color: var(--accent);
  color: var(--accent-text);
  font-weight: 620;
}

/* Eine Beschriftung über einer Gruppe von Pillen. Sie gehört zur Gruppe wie
   ein Label zu einem Eingabefeld, ist aber keins, deshalb eine eigene Klasse. */
.feld-label {
  display: block; font-size: var(--t-sm); font-weight: 550;
  color: var(--muted); letter-spacing: var(--track-weit); margin-bottom: var(--s-2);
}

/*
 * Antworten mit Zeilenumbrüchen behalten sie.
 *
 * Der Coach liefert Aufzählungen mit echten Zeilenumbrüchen. Ohne diese Regel
 * fasst HTML alles zu einem Absatz zusammen, und aus einer Aufteilung auf drei
 * Mahlzeiten wird eine Textwand, die niemand liest. Der Umbruch ist hier die
 * Information.
 */
.feedback { white-space: pre-line; }

/* Luft zwischen den Gruppen im Bereich "Rest des Tages". Eine Beschriftung,
   die am Element darüber klebt, wirkt wie dessen Fussnote statt wie die
   Überschrift dessen, was folgt. */
#restSatz { margin-bottom: var(--s-5); }
.feld-label { margin-top: var(--s-5); }
.feld-label:first-of-type { margin-top: 0; }
#restMahlzeiten { margin-bottom: var(--s-5); }
#btnRestPlanen { margin-top: var(--s-2); }

/*
 * Das Coaching Angebot.
 *
 * Es steht am Ende einer Ansicht, nicht darüber, und sieht bewusst anders aus
 * als der Rest: ein Angebot, das wie ein Bedienelement aussieht, wird
 * versehentlich angetippt, und ein versehentlicher Klick auf einen
 * Buchungslink ärgert beide Seiten.
 */
.angebot {
  margin: var(--s-8) 0 var(--s-4);
  padding-top: var(--s-6);
  border-top: 1px solid var(--linie);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.angebot-teil {
  padding: var(--s-5);
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--accent) 7%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.angebot-teil b { display: block; font-size: var(--t-lg); font-weight: 650; letter-spacing: var(--track-eng); }
.angebot-teil span {
  display: block; font-size: var(--t-md); color: var(--muted);
  line-height: 1.55; margin: var(--s-2) 0 var(--s-4);
}
.angebot-knopf {
  display: block; text-align: center; text-decoration: none;
  padding: 13px 16px; border-radius: var(--r-sm);
  font-size: var(--t-md); font-weight: 620;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
}
.angebot-knopf.primary {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}

/* Eine Vorlage in der Verwaltung. Drei Felder, die zusammengehören, deshalb
   ein gemeinsamer Rahmen statt drei einzelner Zeilen. */
.plan-zeile {
  padding: var(--s-4); margin-bottom: var(--s-3);
  background: var(--panel); border: 1px solid var(--linie); border-radius: var(--r-md);
  display: flex; flex-direction: column; gap: var(--s-2);
}
.plan-zeile-unten { display: flex; align-items: center; gap: var(--s-2); }
.plan-zeile-unten input { width: 72px; }
.plan-zeile-unten span { font-size: var(--t-sm); color: var(--muted); flex: 1; }

.angebot-grund {
  display: block; font-size: var(--t-sm); color: var(--accent-text);
  line-height: 1.5; margin-bottom: var(--s-4);
}
.angebot-mail {
  display: block; text-align: center; margin-top: var(--s-3);
  font-size: var(--t-sm); color: var(--muted); text-decoration: none;
}
.plan-zeile .switch { margin: var(--s-1) 0 0; font-size: var(--t-sm); }
.plan-zeile-unten select { flex: 1; min-width: 0; }

/* Der Einstieg über eine Sicherung, unter dem Fragebogen.
   Bewusst zurückhaltend: wer zum ersten Mal hier ist, soll den Fragebogen
   ausfüllen und nicht nach einer Datei suchen, die es bei ihm nicht gibt. */
.setup-sicherung {
  margin: var(--s-8) auto 0;
  max-width: 30rem;
  padding: 0 var(--s-4) var(--s-8);
  border-top: 1px solid var(--linie);
  padding-top: var(--s-6);
}
.setup-sicherung textarea {
  width: 100%;
  margin-bottom: var(--s-3);
}

/* Der Weckwortknopf neben dem Mikrofon. Beschriftet statt bebildert: ein
   Symbol für "hört auf ein Wort" gibt es nicht, und ein erfundenes muss man
   erklären. Im eingeschalteten Zustand trägt er die Markenfarbe, damit auf
   einen Blick klar ist, dass das Mikrofon läuft. */
.icon-btn.weckwort {
  width: auto;
  padding: 0 var(--s-3);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--muted);
}
.icon-btn.weckwort[aria-pressed="true"] {
  color: var(--bg);
  background: var(--accent);
}

/* ---------- Der Mahlzeit Editor ---------- */

/*
  Ein Blatt, das von unten kommt, keine eigene Ansicht.

  Der Nutzer korrigiert eine Menge und will danach wieder da sein, wo er war.
  Eine eigene Ansicht hiesse zweimal navigieren für einen Handgriff, den man
  fünfmal am Tag macht. Das Blatt endet bewusst vor der Oberkante: was
  darunter liegt, bleibt sichtbar, und damit bleibt klar, dass man nur kurz
  woanders ist.
*/
.blatt {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
/* Solange das Blatt offen ist, scrollt nur das Blatt. Ohne das scrollt die
   Seite darunter mit, und der Nutzer verliert beim Schliessen seine Stelle. */
body.blatt-offen { overflow: hidden; }

.blatt-innen {
  width: 100%; max-width: 560px; max-height: 92vh;
  display: flex; flex-direction: column;
  background: var(--panel-2);
  border: 1px solid var(--border); border-bottom: none;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: var(--schatten-3);
  animation: blatt-hoch 260ms var(--kurve-start) both;
}
@keyframes blatt-hoch {
  from { transform: translateY(14px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .blatt-innen { animation: none; } }

.blatt-kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); padding: var(--s-4) var(--s-4) var(--s-2);
}
.blatt-kopf h2 { margin: 0; font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.01em; }

.blatt-scroll {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0 var(--s-4) var(--s-4);
}

/* Der Fuss bleibt stehen. Speichern ist die eine Sache, die immer erreichbar
   sein muss, auch bei zwölf Posten in der Liste. */
.blatt-fuss {
  display: flex; gap: var(--s-2); align-items: center;
  padding: var(--s-3) var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--linie);
}
.blatt-fuss .primary { margin-left: auto; }
.ghost.gefahr { color: var(--bad); border-color: var(--bad); }

/* Das Kreuz als Form, nicht als Zeichen. Ein Mal aus der Schrift sitzt je
   nach Gerät zwei Pixel daneben. */
.kreuz { display: block; width: 15px; height: 15px; position: relative; }
.kreuz::before, .kreuz::after {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 15px; height: 1.6px; background: currentColor; border-radius: 2px;
}
.kreuz::before { transform: rotate(45deg); }
.kreuz::after { transform: rotate(-45deg); }

.me-kopf { display: flex; gap: var(--s-3); align-items: flex-start; flex-wrap: wrap; }
.me-kopf .pills { flex: 1; min-width: 200px; }
.me-kopf .pills button {
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-pill); padding: 7px 13px; font-size: var(--t-sm); font-weight: 500;
}
.me-kopf .pills button.an { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
#meZeit {
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-md); padding: 7px 10px; font-size: var(--t-sm);
}

/* Die Summe oben, weil sie der Grund ist, warum jemand hier etwas ändert. */
.me-summe {
  display: flex; align-items: center; gap: var(--s-4);
  margin: var(--s-4) 0 var(--s-3); padding: var(--s-3) 0;
  border-top: 1px solid var(--linie); border-bottom: 1px solid var(--linie);
}
.me-kcal { display: flex; align-items: baseline; gap: 5px; }
.me-kcal b { font-size: var(--t-2xl); font-weight: 600; letter-spacing: -0.02em; }
.me-kcal span { font-size: var(--t-xs); color: var(--muted); }
.me-makros { display: flex; gap: var(--s-4); margin-left: auto; }
.me-makros div { display: flex; flex-direction: column; align-items: flex-end; }
.me-makros b { font-size: var(--t-sm); font-weight: 600; }
.me-makros span { font-size: var(--t-2xs); color: var(--muted); }

.me-posten { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.me-posten > li { border-bottom: 1px solid var(--linie); padding-bottom: var(--s-3); }
.me-posten > li:last-child { border-bottom: none; }
.me-leer { color: var(--muted); font-size: var(--t-sm); }

.me-zeile { display: flex; align-items: center; gap: var(--s-2); }
.me-name { flex: 1; font-size: var(--t-md); font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.me-mengefeld { display: flex; align-items: center; gap: 5px; flex: none; }
/* Breit genug für vier Ziffern. Ein Feld, das bei 1000 umbricht, sieht nach
   Fehler aus. */
.me-menge {
  width: 72px; text-align: right;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-md); padding: 7px 8px; font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
}
.me-einheit, .me-fest { font-size: var(--t-sm); color: var(--muted); }
.me-weg {
  flex: none; width: 32px; height: 32px; display: grid; place-items: center;
  background: transparent; border: none; color: var(--muted); border-radius: var(--r-pill);
}
.me-weg:active { color: var(--bad); }
.me-werte { margin-top: 4px; font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; }

.me-suche { display: flex; gap: var(--s-2); margin-bottom: var(--s-2); }
.me-suche input {
  flex: 1; min-width: 0;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-md); padding: 9px 11px; font-size: var(--t-sm);
}
.me-suche .ghost { flex: none; padding: 9px 12px; font-size: var(--t-sm); }

.me-treffer { list-style: none; margin: var(--s-2) 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.me-treffer-knopf {
  width: 100%; text-align: left; display: block;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-md); padding: var(--s-3);
  transition: transform var(--schnell) var(--kurve), border-color var(--schnell) var(--kurve);
}
.me-treffer-knopf:active { transform: scale(0.98); border-color: var(--accent); }
.me-warnung { margin-top: 4px; font-size: var(--t-2xs); color: var(--warn); }

.me-video {
  display: block; width: 100%; max-width: 100%; aspect-ratio: 4 / 3;
  object-fit: cover; border-radius: var(--r-md); margin: var(--s-2) 0;
  background: #000;
}

.me-hand { margin-top: var(--s-5); }
.me-hand summary {
  font-size: var(--t-sm); font-weight: 600; color: var(--muted);
  padding: var(--s-2) 0; cursor: pointer;
}
.me-hand summary::marker { color: var(--accent); }

/* Eine Zeile, die sich antippen lässt, muss danach aussehen. */
.list li.tippbar:active { background: var(--erhoben); }

/*
 * Der Weg ins Erfassen
 *
 * Ein Knopf statt vier. Vorher standen Diktieren, Foto, Barcode und Erfassen
 * als gleich aussehende Knöpfe nebeneinander. Vier gleichwertige Knöpfe sind
 * keine Wahl, sondern eine Aufgabe: man muss jedes Mal alle vier lesen.
 *
 * Das Plus ist gebaut, kein Schriftzeichen. Zwei Balken mit runden Enden,
 * dieselbe Rundung wie am d der Wortmarke. Ein Plus aus dem Zeichensatz sitzt
 * je nach Schrift anders in der Zeile und ist nie genau mittig.
 */
/*
 * Der Knopf sah aus wie die Wasserchips darüber: gerahmtes Rechteck mit
 * runden Ecken. Zwei Dinge mit demselben Aussehen und sehr verschiedenem
 * Gewicht, und der wichtigere verliert, weil er weiter unten steht.
 *
 * Der Unterschied liegt jetzt in der Art der Fläche und nicht in der Farbe.
 * Ein Chip ist umrandet und flach, dieser Knopf ist gefüllt und erhoben. Eine
 * Füllung in der Markenfarbe wäre die naheliegende Lösung und die falsche:
 * ein voll eingefärbter Knopf zieht mehr Aufmerksamkeit als die Zahlen
 * darüber, und die sind der Inhalt der Seite.
 */
.erfassen-knopf {
  width: 100%; display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-5) var(--s-5) var(--s-5) var(--s-4);
  /* Luft nach oben, nicht nur nach unten. Vorher klebte der Knopf an den
     Wasserchips darüber, und zwei Bedienelemente ohne Abstand lesen sich als
     eine Gruppe, obwohl das eine ein Nebenweg und das andere die
     Haupthandlung der Seite ist. */
  margin: var(--s-6) 0 var(--s-5);
  background: var(--stark); border: 0;
  border-radius: var(--r-lg); box-shadow: var(--schatten-2);
  color: var(--auf-stark); text-align: left; cursor: pointer;
  transition: transform var(--schnell) var(--kurve), box-shadow var(--schnell) var(--kurve);
}
/* Beim Drücken sinkt er ein: kleiner und flacher zugleich. Nur kleiner
   werden liest sich als Wackeln, der wegfallende Schatten macht daraus
   eine Bewegung nach unten. */
.erfassen-knopf:active { transform: scale(0.985); box-shadow: var(--schatten-1); }
.erfassen-knopf:hover { box-shadow: var(--schatten-3); }

/* Ein Winkel am rechten Rand. Ohne ihn sieht die Kachel aus, als stünde dort
   etwas, statt als ginge dort etwas auf. */
.erfassen-chev {
  margin-left: auto; flex: 0 0 auto;
  width: 10px; height: 10px; border-top: 2px solid currentColor; border-right: 2px solid currentColor;
  opacity: 0.45;
  border-radius: 1px; transform: rotate(45deg);
  transition: transform var(--normal) var(--kurve);
}
/* Solange das Blatt offen ist, zeigt der Winkel nach unten und das Plus steht
   auf der Diagonale. Ein Knopf, der geöffnet hat, soll das sagen. */
.erfassen-knopf[aria-expanded="true"] .erfassen-chev { transform: rotate(135deg); }
.erfassen-knopf[aria-expanded="true"] .erfassen-plus { transform: rotate(45deg); }

/* Der Kreis trägt die Markenfarbe, der Rest der Kachel nicht. Ein voll
   eingefärbter Knopf in der Markenfarbe zieht mehr Aufmerksamkeit als die
   Zahlen darüber, und die sind der Inhalt der Seite. */
.erfassen-plus {
  position: relative; flex: 0 0 auto;
  width: 50px; height: 50px; border-radius: var(--r-pill);
  background: var(--stark-marke); box-shadow: none;
  transition: transform var(--normal) var(--kurve);
}
.erfassen-plus::before,
.erfassen-plus::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  background: var(--auf-stark-marke); border-radius: var(--r-pill);
  transform: translate(-50%, -50%);
}
.erfassen-plus::before { width: 19px; height: 2.8px; }
.erfassen-plus::after { width: 2.8px; height: 19px; }

.erfassen-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
@media (prefers-reduced-motion: reduce) {
  .erfassen-knopf, .erfassen-plus, .erfassen-chev { transition: none; }
}
.erfassen-titel {
  font-family: var(--schrift-display); font-size: var(--t-lg); font-weight: 600;
  letter-spacing: -0.02em;
}
/* Nicht --muted. Der Ton ist für Text auf dem Grundton gerechnet und liegt auf
   der starken Fläche daneben. Die eigene Farbe mit Deckkraft bleibt in beiden
   Modi im Verhältnis: 0.82 ergibt dunkel 5.84 zu 1 und hell 4.86 zu 1. */
.erfassen-sub { font-size: var(--t-sm); font-weight: 500; color: currentColor; opacity: 0.82; }

/*
 * Die vier Wege im Blatt.
 *
 * Keine Kacheln mit Rahmen, sondern Zeilen mit Trennlinien. Vier gerahmte
 * Flächen untereinander lesen sich als Liste von Behältern, nicht als Wahl.
 * Was die Zeilen zusammenhält, ist die Linie, nicht der Kasten.
 */
.wege {
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-md); overflow: hidden; margin-bottom: var(--s-4);
}
.weg {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4); background: none; border: none;
  border-bottom: 1px solid var(--linie);
  color: var(--text); text-align: left; cursor: pointer; width: 100%;
  transition: background var(--schnell) var(--kurve);
}
.weg:last-child { border-bottom: none; }
.weg:active { background: var(--erhoben); }
.weg:hover { background: var(--erhoben); }

.weg-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.weg-titel { font-size: var(--t-md); font-weight: 600; letter-spacing: -0.01em; }
/* Die Zeile darf umbrechen. Auf 390 Pixeln passt "Mengen werden an
   Bezugsgrössen geschätzt" nicht in eine Zeile, und abgeschnittener Text
   erklärt nichts. */
.weg-sub { font-size: var(--t-xs); color: var(--muted); line-height: 1.4; }

/* Die Zeichen sind gezeichnet, nicht getippt. Emoji sehen auf jedem Gerät
   anders aus und tragen eine fremde Farbigkeit in die Palette. */
.weg-zeichen {
  position: relative; flex: 0 0 auto;
  width: 36px; height: 36px; border-radius: var(--r-sm);
  background: var(--erhoben); border: 1px solid var(--border);
}
.weg-zeichen::before, .weg-zeichen::after { content: ""; position: absolute; }

/* Foto: Gehäuse mit Linse. */
.weg-foto::before {
  left: 8px; top: 12px; width: 20px; height: 14px;
  border: 1.6px solid var(--accent); border-radius: 3px;
}
.weg-foto::after {
  left: 15px; top: 16px; width: 6px; height: 6px;
  border: 1.6px solid var(--accent); border-radius: var(--r-pill);
}

/* Sprache: Kapsel mit Fuss. */
.weg-sprache::before {
  left: 15px; top: 9px; width: 6px; height: 11px;
  background: var(--accent); border-radius: var(--r-pill);
}
.weg-sprache::after {
  left: 11px; top: 19px; width: 14px; height: 8px;
  border: 1.6px solid var(--accent); border-top: none;
  border-radius: 0 0 8px 8px;
}

/* Barcode: Striche in ungleichen Abständen, wie auf einer Packung. */
.weg-barcode::before {
  left: 9px; top: 10px; width: 18px; height: 16px;
  background:
    linear-gradient(var(--accent), var(--accent)) 0 0 / 2px 100% no-repeat,
    linear-gradient(var(--accent), var(--accent)) 4px 0 / 1px 100% no-repeat,
    linear-gradient(var(--accent), var(--accent)) 8px 0 / 2px 100% no-repeat,
    linear-gradient(var(--accent), var(--accent)) 13px 0 / 1px 100% no-repeat,
    linear-gradient(var(--accent), var(--accent)) 16px 0 / 2px 100% no-repeat;
}

/* Suche: Lupe. */
.weg-suche::before {
  left: 9px; top: 9px; width: 13px; height: 13px;
  border: 1.6px solid var(--accent); border-radius: var(--r-pill);
}
.weg-suche::after {
  left: 21px; top: 21px; width: 7px; height: 1.8px;
  background: var(--accent); border-radius: var(--r-pill);
  transform: rotate(45deg); transform-origin: left center;
}

/* Der Pfeil rechts sagt, dass es weitergeht und nicht sofort passiert. */
.weg-chev {
  flex: 0 0 auto; width: 7px; height: 7px;
  border-right: 1.6px solid var(--muted); border-top: 1.6px solid var(--muted);
  transform: rotate(45deg);
}

/* ---------- Das Foto, bevor es rausgeht ----------
 *
 * Die Bühne trägt drei Ebenen übereinander: das Bild, eine Zeile, die darüber
 * läuft, und ein paar Punkte, die aufleuchten. Alle drei laufen nur, solange
 * wirklich gerechnet wird, gesteuert über `.laeuft` am Element. Eine
 * Animation, die immer läuft, heisst nichts mehr: der Nutzer kann dann nicht
 * mehr sehen, ob die App arbeitet oder wartet.
 *
 * 4 zu 3 als festes Seitenverhältnis. Ein Bild vom Handy kommt hoch oder quer,
 * und ohne feste Höhe springt der Knopf darunter beim Laden an eine andere
 * Stelle. `object-fit: cover` schneidet lieber ab, als zu verzerren: ein
 * verzerrter Teller sieht aus wie ein Fehler der App.
 */
.foto-buehne {
  position: relative;
  aspect-ratio: 4 / 3;
  margin: var(--s-2) 0 var(--s-5);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--erhoben);
  border: 1px solid var(--border);
}
.foto-bild { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Die Zeile läuft von oben nach unten und wieder zurück. Ein Sprung zurück an
   den Anfang wirkt wie ein Ruckler, deshalb `alternate`. */
.foto-scan {
  position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: var(--brand);
  box-shadow: 0 0 14px 2px color-mix(in srgb, var(--brand) 60%, transparent);
  opacity: 0;
}
.foto-buehne.laeuft .foto-scan {
  opacity: 1;
  animation: foto-scan 2.2s var(--kurve) infinite alternate;
}
/* Bewegt wird `top` und nicht `transform`. Die Zeile ist zwei Pixel hoch, und
   translateY(100%) sind damit zwei Pixel statt der ganzen Bühne. */
@keyframes foto-scan {
  from { top: 0; }
  to { top: calc(100% - 2px); }
}

/* Die Punkte. Sie sitzen auf festen Stellen statt zufällig: derselbe Ablauf
   bei jedem Bild ist ruhiger als ein Feld, das jedes Mal anders flackert. */
.foto-funken { position: absolute; inset: 0; pointer-events: none; }
.foto-funken i {
  position: absolute; left: var(--x); top: var(--y);
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--brand);
  opacity: 0;
}
.foto-buehne.laeuft .foto-funken i {
  animation: foto-funke 3.5s var(--kurve) var(--v) infinite;
}
@keyframes foto-funke {
  0%, 100% { opacity: 0; transform: scale(0.4); }
  12% { opacity: 0.9; transform: scale(1); }
  30% { opacity: 0; transform: scale(0.4); }
}

@media (prefers-reduced-motion: reduce) {
  .foto-buehne.laeuft .foto-scan,
  .foto-buehne.laeuft .foto-funken i { animation: none; }
  .foto-buehne.laeuft .foto-scan { opacity: 0.5; }
}

.foto-details {
  width: 100%;
  padding: var(--s-3);
  background: var(--erhoben);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--text);
  font: inherit;
}
.foto-details:focus-visible { outline: 2px solid var(--brand-deep); outline-offset: 1px; }

/* Ein Knopf über die ganze Breite, ohne die Randausrichtung des sonstigen
   Fusses. Er ist hier die einzige Handlung, und ein einzelner Knopf, der
   rechts klebt, sieht aus, als fehle links noch einer. */
.foto-fuss { display: block; }
.foto-fuss .primary { margin: 0; border-radius: var(--r-pill); padding: var(--s-4); }

/* Während gerechnet wird, bleibt der Knopf gesperrt, aber nicht blass. Der
   allgemeine Wert von 0.45 ist für einen Knopf gedacht, den man gerade nicht
   benutzen darf. Hier ist es der einzige Ort, an dem der Fortschritt steht,
   und ein Fortschritt, den man kaum lesen kann, ist keiner. */
.foto-fuss .primary:disabled { opacity: 0.88; }


/* ---------- Betriebsarten ----------
 *
 * Kopf leeren und das Weckwort sind Zustände, keine Eingabehilfen. Sie
 * standen in der Pille als zwei Wörter zwischen vier Symbolen und haben den
 * Platzhalter im Feld abgeschnitten. Jetzt stehen sie darüber, beschriftet,
 * mit einem Punkt, der den Zustand trägt.
 */
.modi {
  display: flex; gap: var(--s-2);
  padding: 0 var(--s-4) var(--s-2);
}
.modus {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 7px var(--s-3); border-radius: var(--r-pill);
  border: 1px solid var(--border); background: var(--panel-2);
  color: var(--muted); font: inherit; font-size: var(--t-xs); font-weight: 600;
  transition: color var(--schnell) var(--kurve), border-color var(--schnell) var(--kurve);
}
.modus:active { transform: scale(0.98); }
.modus-punkt {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: 0.45;
  transition: opacity var(--schnell) var(--kurve), box-shadow var(--schnell) var(--kurve);
}
/* An heisst: Farbe, voller Punkt und ein Schimmer darum. Drei Signale, weil
   ein offenes Mikrofon Akku zieht und niemand es übersehen darf. */
.modus[aria-pressed="true"] { color: var(--accent-text); border-color: var(--accent); }
.modus[aria-pressed="true"] .modus-punkt {
  opacity: 1; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
@media (prefers-reduced-motion: reduce) { .modus, .modus-punkt { transition: none; } }

/* ---------- Karten zum Durchwischen ----------
 *
 * Eine Zahl je Karte. Sieben Zeilen untereinander werden überflogen, eine
 * Zahl, die allein steht, wird gelesen.
 *
 * Das Wischen macht der Browser über scroll-snap. Eine Bibliothek wäre die
 * erste Laufzeitabhängigkeit der App und das Verhalten wäre schlechter: ein
 * nachgebauter Wisch kennt weder den Schwung des Fingers noch die
 * Systemeinstellung für weniger Bewegung.
 */
.karten {
  display: flex; gap: var(--s-3);
  overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  /* Der Innenabstand liegt auf dem Streifen und nicht auf der Seite, damit
     die erste Karte am Rand einrastet und die letzte nicht klebt. */
  padding: var(--s-2) var(--s-4) var(--s-4);
  margin: 0 calc(var(--s-4) * -1);
  scrollbar-width: none;
}
.karten::-webkit-scrollbar { display: none; }
.karten:focus-visible { outline: 2px solid var(--brand-deep); outline-offset: -2px; border-radius: var(--r-lg); }

.karte {
  scroll-snap-align: center;
  flex: 0 0 min(272px, 76vw);
  display: flex; flex-direction: column;
  padding: var(--s-5);
  border-radius: var(--r-lg);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--schatten-1);
}
.karte-kopf { display: flex; align-items: center; gap: var(--s-3); }
/* Das Zeichen trägt die Farbe des Werts, der Rest der Karte nicht. Eine
   eingefärbte Karte je Wert ergäbe sieben bunte Flächen nebeneinander, und
   die Farbe hätte danach keine Bedeutung mehr. */
.karte-zeichen {
  width: 34px; height: 34px; flex: 0 0 34px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--ton, var(--brand)) 16%, transparent);
  color: var(--ton, var(--brand));
}
.karte-zeichen svg { width: 20px; height: 20px; display: block; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.karte-name { font-size: var(--t-sm); font-weight: 600; letter-spacing: -0.005em; }

/* Die Zahl trägt die Karte. Alles darum bleibt klein, sonst ist es wieder
   eine Liste, nur mit mehr Abstand. */
.karte-zahl {
  margin-top: auto; padding-top: var(--s-5);
  font-size: var(--t-4xl); font-weight: 680; letter-spacing: -0.035em;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.karte-einheit { font-size: var(--t-md); color: var(--muted); font-weight: 500; margin-left: 6px; letter-spacing: 0; }
.karte-zusatz { font-size: var(--t-sm); color: var(--muted); margin-top: var(--s-2); }
.karte-fuss {
  margin-top: var(--s-4); padding-top: var(--s-3);
  border-top: 1px solid var(--linie);
  font-size: var(--t-xs); color: var(--muted);
  display: flex; justify-content: space-between; gap: var(--s-2);
}
.karte-trend { color: var(--text); font-weight: 600; }
/* Kein Vergleich ist das Unwichtigste auf der Karte und stand fett neben der
   Zahl der Tage. Eine Abwesenheit braucht kein Gewicht. */
.karte-trend.leise { color: var(--muted); font-weight: 500; }

/* Die Punkte sagen, wie viele es sind und wo man steht. Ohne sie wischt
   niemand weiter, weil nichts darauf hinweist, dass da noch etwas kommt. */
.punkte { display: flex; justify-content: center; gap: 6px; margin: 0 0 var(--s-4); }
.punkte i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text); opacity: 0.22;
  transition: opacity var(--schnell) var(--kurve), width var(--schnell) var(--kurve);
}
.punkte i.an { opacity: 1; width: 18px; border-radius: var(--r-pill); }
@media (prefers-reduced-motion: reduce) { .punkte i { transition: none; } }

/* ---------- Wo Poppins steht ----------
 *
 * Überschriften und Zahlen, nichts sonst. Eine Schrift überall einzusetzen
 * macht sie unsichtbar: sie fällt nur auf, wenn daneben etwas anderes steht.
 *
 * Die Laufweite geht enger, als die Systemschrift sie brauchte. Poppins läuft
 * von sich aus weiter, und bei gleicher Einstellung wirkt eine Überschrift
 * auseinandergezogen.
 */
h1,
.bar h1,
.abschnitt,
.menu-item b,
.karte-name,
.messwert-name {
  font-family: var(--schrift-display);
  letter-spacing: -0.015em;
}

/* Zahlen, die die Seite tragen. Tabellarisch bleibt es überall: eine 1 ist
   sonst schmaler als eine 8, und eine Zahl, die beim Hochzählen wackelt,
   sieht nach Fehler aus. */
.held-zahl,
.karte-zahl,
.ring-num,
.messwert.gross .messwert-wert b,
.wertung-zahl {
  font-family: var(--schrift-display);
  font-variant-numeric: tabular-nums;
}

/* Die Zahl im Wertungsring wird als SVG Text gesetzt und erbt die Schrift
   nicht über die üblichen Regeln. */
.wertung svg text, .ring-svg text { font-family: var(--schrift-display); }

/* ---------- Der Wechsel zwischen Ansichten ----------
 *
 * Vorher schnitt die App hart um. Ein Schnitt ohne Übergang nimmt dem Nutzer
 * die Auskunft, ob er tiefer hinein oder wieder heraus gegangen ist, und
 * genau daran erkennt man billige Apps.
 *
 * Die neue Ansicht kommt herein, die alte wird nicht animiert. Zwei Ebenen
 * gleichzeitig zu bewegen braucht beide gleichzeitig im Baum, also ein
 * Umbauen von `hidden` auf Überlagerung, und das kostet an jeder Stelle, an
 * der eine Ansicht ihre Höhe misst. Der Gewinn wäre eine Nuance.
 *
 * 190 Millisekunden. Darunter sieht man nur ein Zucken, darüber wartet man.
 */
@keyframes ansicht-rein {
  from { opacity: 0; transform: translate3d(14px, 0, 0); }
  to { opacity: 1; transform: none; }
}
@keyframes ansicht-zurueck {
  from { opacity: 0; transform: translate3d(-14px, 0, 0); }
  to { opacity: 1; transform: none; }
}
.view.kommt-rein { animation: ansicht-rein 190ms var(--kurve) both; }
.view.kommt-zurueck { animation: ansicht-zurueck 190ms var(--kurve) both; }

/*
 * Der Assistent wird nicht geschoben.
 *
 * Auf ihm läuft der Kreis auf einem Canvas. Eine Transformation auf dem
 * Vorfahren zwingt den Browser, das Canvas in eine eigene Ebene zu legen und
 * pro Bild neu zusammenzusetzen, und die Bildrate bricht für die Dauer der
 * Animation ein. Ein Aufblenden reicht dort.
 */
.view[data-view="assistant"].kommt-rein,
.view[data-view="assistant"].kommt-zurueck {
  animation-name: ansicht-auf;
}
@keyframes ansicht-auf { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .view.kommt-rein, .view.kommt-zurueck { animation: none; }
}

/* ---------- Das Netz ----------
 *
 * Es steht ohne Kasten, wie der Held auf Heute. Was es zusammenhält, ist der
 * Abstand zu seinen Nachbarn. Ein Rahmen darum machte aus der
 * Zusammenfassung ein Objekt neben anderen Objekten.
 */
.netz-buehne {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--s-2); padding: var(--s-2) 0 var(--s-3);
  color: var(--text);
}
.netz-buehne svg { display: block; max-width: 100%; height: auto; }

.legende { display: flex; gap: var(--s-5); align-items: center; font-size: var(--t-xs); color: var(--muted); }
.legende span { display: inline-flex; align-items: center; gap: 7px; }
.legende-umriss {
  width: 13px; height: 13px; border-radius: 4px;
  border: 1.6px dashed currentColor; opacity: 0.8;
}
.legende-flaeche {
  width: 13px; height: 13px; border-radius: 4px;
  background: var(--brand); opacity: 0.85;
}

/* Der Hinweis auf eine Schieflage. Er steht in der Ansicht und nicht nur in
   der Mitteilung: wer die weggewischt hat und später selbst nachsieht, soll
   dasselbe lesen. Warnfarbe wäre falsch, eine Schieflage ist kein Fehler,
   sondern ein Unterschied zu dem, was sich der Nutzer vorgenommen hat. */
.hinweis {
  margin: var(--s-3) 0 var(--s-2);
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: var(--erhoben);
  border-left: 3px solid var(--accent);
}
.hinweis .li-title { font-family: var(--schrift-display); font-weight: 600; font-size: var(--t-sm); }
.hinweis .li-sub { color: var(--muted); font-size: var(--t-sm); margin-top: 3px; }

/* Die Linie auf der Berichtskarte. Sie trägt die Farbe ihres Werts, aber
   gedämpft: die Zahl darüber ist die Aussage, die Linie nur ihre Form. */
.funke {
  display: block; width: 100%; height: 34px;
  margin-top: var(--s-3);
  overflow: visible;
}
.funke path {
  fill: none; stroke: var(--ton, var(--brand)); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  /* preserveAspectRatio none verzerrt die Linie in der Breite. Ohne das
     bliebe die Strichstärke ungleichmässig, sobald die Karte skaliert. */
  vector-effect: non-scaling-stroke;
  opacity: 0.85;
}
.funke circle { fill: var(--ton, var(--brand)); }
