:root {
  /* Die App ist bewusst nur hell. Ohne diese Zeile faerbt der Browser
     Formularfelder, Auswahllisten und Bildlaufleisten trotzdem dunkel,
     sobald das Geraet auf Dunkelmodus steht — und dann steht dunkle Schrift
     auf dunklem Grund. */
  color-scheme: light;

  --bg:        #f4f2ee;
  --surface:   #ffffff;
  --surface-2: #eceae5;
  --line:      #d9d5cd;
  --text:      #1c1a17;
  --muted:     #6d6862;
  --accent:    #b4451f;
  --accent-ink:#ffffff;
  --ok:        #1f7a4d;
  --ok-soft:   #e2f2e9;
  --warn:      #8a6d00;
  --warn-soft: #fbf1cd;
  --danger:    #b3261e;
  --radius:    14px;   /* HIG: 10–16 pt fuer Karten und Knoepfe */
  --tap:       48px;   /* HIG: mindestens 44 pt */

  /* Apples Vierer-/Achter-Raster. Abstaende sind Vielfache davon — nicht,
     weil es huebscher waere, sondern damit gleiche Dinge gleich weit
     auseinanderstehen und der Blick eine Ordnung findet. Frueher standen hier
     0,6rem neben 0,75rem neben 0,9rem, alles handgesetzt und leicht daneben. */
  --s1:  4px;
  --s2:  8px;
  --s3: 12px;
  --s4: 16px;
  --s6: 24px;
  --s8: 32px;

  /* Abstand zum Bildschirmrand. ACHTUNG: Apple nennt dafuer KEINE Zahl —
     nachgesehen in den Rohdaten der Layout-Seite der Vorgaben, dort stehen
     Punktwerte fuer Raender nur fuer tvOS. Die viel zitierten "16 pt" sind
     verbreitete Praxis, keine Vorgabe. 16 px ist also unsere Entscheidung,
     getroffen weil 10 px zu eng wirkten — nicht, weil Apple es verlangt. */
  --rand: var(--s4);
  /* Quer gehalten reicht der Bildschirm unter die runden Ecken und die
     Kamerainsel. Dann gilt der groessere der beiden Werte — die Vorgabe von
     16 pt oder das, was das Geraet meldet. */
  --rand-links:  max(var(--s4), env(safe-area-inset-left));
  --rand-rechts: max(var(--s4), env(safe-area-inset-right));

  /* Apples Textstile in Punkt. Auf iOS ist 1 pt ein CSS-Pixel, deshalb hier
     direkt in px: Es sind absolute Groessen aus der Vorgabe, keine
     Verhaeltnisse, die wir uns ausdenken. */
  --t-title1:  28px;
  --t-title2:  22px;
  --t-title3:  20px;
  --t-body:    17px;
  --t-callout: 16px;
  --t-subhead: 15px;
  --t-foot:    13px;
  --t-cap1:    12px;

  /* Zustandsfarbe der Menuekarten: gruen = das Kind bekommt dieses Essen.
     Nachgerechnet auf 4,5:1 fuer weisse Schrift (WCAG AA): #1a7d4d liefert
     5,14:1, der vorherige Ton #2f8f5b nur 4,04:1. */
  --gruen:     #1a7d4d;
  /* Hintergrund kleiner Etiketten: eine Spur dunkler als die Flaeche darunter. */
  --chip:      rgba(0, 0, 0, 0.07);
  --chip-dark: rgba(0, 0, 0, 0.22);

  /* Dreistufige Textfarbe nach Apple HIG:
     primary → secondary (--muted) → tertiary (--text-3).
     --text-3 ist warm-grau und haelt noch 4,5:1 auf weissem Grund. */
  --text-3: #7a7670;

  /* Waehlbare Karten sind ein AUFGEHELLTES GRUEN, kein gruenstichiges Weiss.
     Sie sollen erkennbar zur gruenen Familie gehoeren — nur heller als das
     gewaehlte Essen, nicht blass. #a3cbb8 ist das Grundgruen zu 40 % auf
     Weiss.
     Dass darauf Grau als Preisfarbe nicht mehr traegt, ist kein Einwand
     gegen die Farbe, sondern gegen das Grau: Es bekommt deshalb eine eigene,
     gruen abgetoente Nebenfarbe. */
  --karte-frei:         #a3cbb8;   /* dunkle Schrift 9,75:1 */
  --karte-frei-rand:    #8ab9a3;
  --karte-frei-schrift: #2f5142;   /* Preis darauf 4,96:1 */
  /* Die Linien-Plakette muss sich mit der Karte bewegen: Auf hellem Gruen
     wird sie heller, sonst verschwindet ihre Schrift (das normale Grau kam
     dort nur auf 2,68:1). */
  --karte-frei-chip:    rgba(255, 255, 255, 0.45);

  /* Rot fuer FLAECHEN, auf denen weisse Schrift steht. Apples Systemrot
     (#ff3b30) traegt sie nicht: nur 3,55:1. Dieser Ton ergibt 6,54:1. */
  --rot-flaeche: #b3261e;
  /* Rot fuer Striche und Schrift, getrennt vom Flaechenrot: Was als Flaeche
     unter weisser Schrift taugt, muss als Strich nicht lesbar sein — und
     umgekehrt. */
  --rot-strich:  #b3261e;   /* auf der Leiste 5,85:1 */

  /* Titelgroesse als ein Wert statt zweier Nachbarn: Der Zeitraum unter dem
     Titel SOLL genauso gross sein. Zwei handgesetzte Zahlen driften
     auseinander — hier waren es 1,4 gegen 1,35 rem, was niemandem auffiel,
     aber die Absicht verfehlte. */
  --t-titel: var(--t-title2);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 17px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  overscroll-behavior-y: none;
}

.app { max-width: 34rem; margin: 0 auto; padding-bottom: 7rem; }

/* ---------- Kopfbereich ---------- */

.top {
  position: sticky; top: 0; z-index: 20;
  /* Bezugspunkt für das aufklappende Menü */
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding: max(var(--s2), env(safe-area-inset-top)) var(--rand-rechts) var(--s3) var(--rand-links);
}

/* Titelzeile als Schalter für Kindauswahl — aktiv nur wenn mehrere Kinder. */
.kindtitel {
  display: flex; align-items: center; gap: var(--s1);
  flex: 1; min-width: 0;
  background: none; border: 0; padding: 0; cursor: default;
  font: inherit; color: inherit; text-align: left;
}
.kindtitel.mehrere { cursor: pointer; }
.kindtitel.mehrere:active h1 { opacity: 0.55; }
.kindtitel h1 { margin: 0; min-width: 0; font-size: var(--t-titel); font-weight: 700; letter-spacing: -0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kindpill {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  background: rgba(0, 0, 0, 0.07);
  display: flex; align-items: center; justify-content: center;
  margin-left: var(--s1);
}
.chevron { flex: none; color: var(--muted); transition: transform 0.2s ease; }
.kindtitel.open .chevron { transform: rotate(180deg); }

/* Dropdown-Auswahl Kind — linksbuendig unter dem Titel. */
.kindpanel {
  position: absolute; left: var(--rand-links); top: 100%;
  min-width: 160px; padding: 4px;
  display: grid; gap: 2px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.14);
  z-index: 40;
}
.kindpanel button {
  min-height: 44px; padding: 0 var(--s3); text-align: left;
  border: none; border-radius: 8px; background: transparent; color: var(--text);
  font: inherit; font-size: var(--t-subhead); cursor: pointer;
}
.kindpanel button.aktiv { color: var(--gruen); font-weight: 600; }
.kindpanel button:active { background: var(--surface-2); }
.top .who { color: var(--muted); font-size: var(--t-subhead); }

.balance {
  display: inline-flex; align-items: baseline; gap: 4px;
  margin-top: var(--s1); padding: var(--s1) var(--s2);
  border-radius: 999px; background: var(--surface-2);
  font-size: var(--t-subhead); font-variant-numeric: tabular-nums;
}
.balance b { font-size: var(--t-body); }
.balance.neg b { color: var(--danger); }

/* ---------- Wochennavigation ---------- */

/* Zeitraum und Seitenpunkte: zwei Zeilen. Oben der Zeitraum (volle Breite),
   darunter die Punkte zentriert — wie Apples UIPageControl unter dem Inhalt.
   margin-top 0: Apple haelt Titel und Datum direkt beieinander (kein Extra-Gap). */
.weeknav {
  display: flex; flex-wrap: wrap; align-items: center;
  row-gap: var(--s2);
  margin-top: 0;
}
.weeknav .range {
  flex: 0 0 100%; min-width: 0;
  font-size: var(--t-titel); font-weight: 700; line-height: 1.2;
  color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}

/* Seitenpunkte: eigene Zeile direkt unter dem Zeitraum, linksbündig.
   Die Kapsel zeigt, dass es sich um einen Schieber handelt.
   min-height reserviert den Platz auch wenn noch keine Punkte geladen sind —
   kein Layout-Sprung beim ersten Render. flex: none → Kapsel nur so breit
   wie ihr Inhalt, linker Rand fluchtet mit dem Zeitraum darüber. */
.weekdots {
  display: flex; align-items: center; gap: 0;
  flex: none; min-height: 28px;
  padding: 1px var(--s2);
  background: rgba(0, 0, 0, 0.06);
  border-radius: 9999px;
}
.weekdots button {
  width: 44px; height: 28px; padding: 0; flex: none;
  background: none; border: 0; cursor: pointer;
  display: grid; place-items: center;
}
.weekdots button::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%;
  background: var(--text); opacity: 0.22;
  transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.2s ease;
}
.weekdots button[aria-selected="true"]::before {
  background: var(--gruen); opacity: 1; transform: scale(1.15);
}

/* Sichtbar nur fuer Vorlesehilfen und die Tastatur. */
.nurvorlesen {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.nurvorlesen:focus {
  position: static; width: auto; height: auto; margin: 0; clip: auto;
  padding: 4px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface); color: var(--text); font: inherit;
}

/* Blaetterbuehne: #days schneidet ab, #daysInner faehrt zur Seite.
   Drei Panels nebeneinander: #daysPrev links, #daysCur Mitte (normal flow),
   #daysNext rechts — absolut positioniert, damit nur #daysCur die Hoehe
   von #days bestimmt. */
/* padding-bottom gibt der letzten Karte Raum, ueber die fixe Aktionsleiste
   zu scrollen — ohne es bleibt der letzte Eintrag dahinter verborgen. */
#days { overflow: hidden; position: relative; padding-bottom: calc(80px + env(safe-area-inset-bottom)); }
#daysInner { will-change: transform; display: flow-root; }
.week-panel { position: absolute; top: 0; width: 100%; }
#daysCur    { position: relative; }
#daysPrev   { left: -100%; }
#daysNext   { left: 100%; }

/* ---------- Tage und Angebote ---------- */

/* Mehr Luft ueber der Ueberschrift: Sie trennt zwei Tage, und diese Trennung
   braucht sichtbaren Abstand zur letzten Kachel des Tages davor. */
.day { margin: var(--s8) var(--rand-rechts) 0 var(--rand-links); }
.day > h2 {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 0 8px; font-size: var(--t-cap1); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
}
/* Der Wochentag ist die eigentliche Orientierung in der Liste — deshalb
   gross, dunkel und in normaler Schreibweise. Das Datum bleibt die leise
   Bestaetigung daneben und behaelt Grau und Versalien. */
.day > h2 .wann {
  display: flex; align-items: baseline; gap: 8px; min-width: 0;
}
.day > h2 .wd {
  font-size: var(--t-body); text-transform: none; letter-spacing: 0;
  color: var(--text); white-space: nowrap;
}
.day > h2 .dt {
  color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.day.today > h2 .wd { color: var(--accent); }

.day > h2 .daystate {
  text-transform: none; letter-spacing: 0; font-weight: 500;
  font-size: var(--t-cap1); text-align: right; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 55%;
}
.day.today > h2 { color: var(--accent); }

/* Bricht ein Gericht auf zwei Zeilen um, werden ALLE Karten des Tages so
   hoch. Sonst huepft die Liste beim Lesen, und der Blick verliert die Spur.
   "1fr" auf den Zeilen eines Rasters mit offener Hoehe heisst genau das:
   alle Zeilen bekommen die Hoehe der groessten. */
/* 12 px zwischen den Karten, nicht 8: "about 12 points of padding around
   elements that include a bezel" — und unsere Karten haben einen Rahmen.
   Zwei antippbare Flaechen dicht nebeneinander laden zum Fehlgriff ein. */
.offers { display: grid; gap: var(--s3); grid-auto-rows: 1fr; }

/* Die Farbe der Karte IST der Zustand: gruen heisst, das bekommt das Kind.
   Ob Standard oder eigene Wahl, ist beim Aussuchen einerlei — deshalb keine
   dritte Farbe und kein Hinweis auf Ungespeichertes. Wer aussucht, will das
   Essen sehen, nicht einen Abgleich. */
.offer {
  /* Zwei Zeilen: oben der Name, unten die Nebenzeile mit Linie und Preis.
     Die Namenszeile bekommt mit "1fr" den gesamten Restplatz der Karte. Weil
     alle Karten eines Tages gleich hoch sind, heisst das: Braucht ein Name
     zwei Zeilen, halten die einzeiligen Namen die zweite Zeile als leeren
     Platz frei — und die Preiszeilen stehen bei allen Karten auf derselben
     Hoehe. Ausdruecklich so gesetzt und nicht ueber verteilten Restplatz
     (align-content), damit es auch dann noch stimmt, wenn die Karte einmal
     eine dritte Zeile bekommt. */
  display: grid; grid-template-rows: 1fr auto; row-gap: 4px;
  width: 100%; min-height: var(--tap);
  padding: var(--s4); text-align: left;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; cursor: pointer;
  /* Der Weg von der hellen zur kraeftigen Tönung ist jetzt kurz — ihn weich
     zu gehen laesst die Auswahl aufscheinen, statt zu springen. */
  transition: transform 0.08s ease, background-color 0.16s ease,
              border-color 0.16s ease, color 0.16s ease;
}
.offer:active { transform: scale(0.985); }

/* Das Gericht ist die Hauptsache auf der Karte: so gross wie die
   Tagesueberschrift und fett. Umbrechen ist ausdruecklich erlaubt — vorher
   wurde die Schrift so lange verkleinert, bis der laengste Name der Woche in
   eine Zeile passte, was alle anderen Namen unnoetig klein machte. */
.offer .name {
  min-width: 0; font-size: var(--t-title3); line-height: 1.28; font-weight: 700;
  overflow-wrap: break-word;
  /* Immer zwei Zeilen Platz reservieren — alle Karten gleich hoch,
     auch wenn der Name in eine Zeile passt. */
  min-height: calc(var(--t-title3) * 1.28 * 2);
}

.offer .foot { display: flex; align-items: baseline; gap: 4px; min-width: 0; }
.offer .line {
  flex: none; padding: 0.1rem 8px; border-radius: 6px;
  background: var(--chip); color: var(--text-3);
  font-size: var(--t-cap1); white-space: nowrap;
}

/* Der Preis gehoert in die Nebenzeile: sichtbar, damit das Kind sieht, was
   ein Essen kostet — aber kleiner als das Gericht, denn danach wird nicht
   ausgesucht. */
.offer .price {
  flex: none; font-size: var(--t-cap1); font-variant-numeric: tabular-nums;
  color: var(--text-3);
}
.offer .hintline {
  flex: 1 1 auto; min-width: 0; font-size: var(--t-cap1); color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Waehlbar: leicht gruen getoent statt weiss. Die Karten gehoeren damit
   sichtbar zur selben Familie wie das gewaehlte Essen — Weiss liess sie wie
   Fremdkoerper auf der Seite stehen. Das Gewaehlte bleibt das kraeftige
   Gruen; hier geht es nur um Zugehoerigkeit, nicht um Betonung. */
.offer[data-state="free"] {
  background: var(--karte-frei); border-color: var(--karte-frei-rand);
}
.offer[data-state="free"] .price,
.offer[data-state="free"] .hintline { color: var(--karte-frei-schrift); }
.offer[data-state="free"] .line {
  background: var(--karte-frei-chip); color: var(--karte-frei-schrift);
}

/* Absage verschickt — grau, durchgestrichen, keine Interaktion.
   Schrift bewusst sehr hell: deaktivierte Elemente sind nach WCAG 1.4.3 kontrastfrei. */
.offer[data-state="cancelling"],
.offer[data-state="abgemeldet"] {
  background: rgba(0,0,0,0.08); border-color: rgba(0,0,0,0.11);
  color: rgba(0,0,0,0.28); cursor: default; pointer-events: none;
  text-decoration: line-through;
}
.offer[data-state="cancelling"] .line,
.offer[data-state="abgemeldet"] .line {
  background: rgba(0,0,0,0.14); color: rgba(0,0,0,0.28);
}
.offer[data-state="cancelling"] .price,
.offer[data-state="cancelling"] .hintline,
.offer[data-state="abgemeldet"] .price,
.offer[data-state="abgemeldet"] .hintline { color: rgba(0,0,0,0.28); }


/* Das Essen, das an diesem Tag kommt */
.offer[data-state="chosen"] {
  background: var(--gruen); border-color: var(--gruen); color: #fff;
}
/* Abdunkeln statt aufhellen: Weiss auf aufgehelltem Gruen kam nur auf
   2,86:1, so sind es 7,39:1. */
.offer[data-state="chosen"] .line { background: var(--chip-dark); color: #fff; }
.offer[data-state="chosen"] .price,
.offer[data-state="chosen"] .hintline { color: rgba(255, 255, 255, 0.9); }

/* Zum Abbestellen vorgemerkt. Dieselbe Sprache wie beim Gruen: satte Farbe
   heisst entschieden. Durchgestrichen, weil es ein Wegnehmen ist. */
.offer[data-state="weg"] {
  background: var(--rot-flaeche); border-color: var(--rot-flaeche); color: #fff;
}
.offer[data-state="weg"] .name {
  text-decoration: line-through; text-decoration-thickness: 2px;
}
.offer[data-state="weg"] .line { background: var(--chip-dark); color: #fff; }
.offer[data-state="weg"] .price,
.offer[data-state="weg"] .hintline { color: rgba(255, 255, 255, 0.9); }

/* Der Papierkorb sitzt IN der Karte. Der sichtbare Kreis ist klein, das
   Tippziel darunter volle 44 px — sichtbare und greifbare Groesse sind
   zweierlei. Durchscheinend statt gefuellt, damit er die Karte nicht
   zerschneidet. */
/* Der Papierkorb liegt NEBEN der Karte, nicht darin: ein Knopf im Knopf
   waere ungueltiges HTML und mit Vorlesehilfen nicht bedienbar. Die Huelle
   traegt beide und stapelt sie uebereinander. */
.offerwrap { position: relative; display: grid; }
.offerwrap > .offer { height: 100%; }
.offerwrap.stornierbar > .offer { padding-right: calc(var(--s4) + 40px); }
.offerwrap .storno {
  position: absolute; right: 0.4rem; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0; border: 0; cursor: pointer;
  background: none; color: inherit;
}
.offerwrap .storno::before {
  content: ''; position: absolute; width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  transition: background 0.16s ease;
}
.offerwrap .storno svg { position: relative; opacity: 0.92; }
.offerwrap .storno:active::before { background: rgba(255, 255, 255, 0.3); }
/* Auf hellen Karten braucht der Kreis den umgekehrten Weg. */
.offerwrap:has(.offer[data-state="free"]) .storno::before {
  background: rgba(0, 0, 0, 0.07);
}

.offer[data-locked="1"] { cursor: default; }
.offer[data-locked="1"]:active { transform: none; }

/* Zurueckgenommen ueber die Flaeche, nicht ueber die Deckkraft: Bei opacity
   0.55 sank der Sperrgrund auf 2,30:1 und war kaum noch zu lesen. */
.offer[data-state="locked"] {
  background: var(--surface-2); border-color: var(--surface-2); color: var(--muted);
}

.nothing {
  margin: 0; padding: var(--s2) var(--s3);
  border: 1px dashed var(--line); border-radius: var(--radius);
  color: var(--muted); font-size: var(--t-subhead);
}

/* ---------- Speichern-Leiste ---------- */

.savebar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  padding: var(--s4) var(--rand-rechts) calc(var(--s4) + env(safe-area-inset-bottom)) var(--rand-links);
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(14px); border-top: 1px solid var(--line);
  box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.08);
  transform: translateY(120%); transition: transform 0.22s ease;
}
.savebar[data-open="1"] { transform: none; }
/* Zwei Reihen: Der Hinweis bekommt die ganze Breite, die Knoepfe darunter.
   Nebeneinander wurde "1 Tag geaendert" beschnitten, sobald die Schrift
   groesser wurde. */
.savebar .inner {
  max-width: 34rem; margin: 0 auto;
  display: grid; gap: 8px;
}
.savebar .buttons { display: flex; gap: 8px; }
/* Auch der E-Mail-Knopf ist ein Link, kein <button> — sonst bleibt er
   als einziger schmal und wird zusammengequetscht. */
.savebar .buttons > * { flex: 1; }
.savebar .summary {
  min-width: 0; font-size: var(--t-subhead); color: var(--muted);
  font-variant-numeric: tabular-nums; line-height: 1.3;
}
.savebar .summary b { color: var(--text); font-weight: 700; }

/* Nach der Klasse gewaehlt, nicht nach dem Element: Der E-Mail-Knopf ist ein
   <a> (er traegt ein mailto:), und mit "button.primary" fielen ausgerechnet
   ihm Rundung und Groesse durch — er stand eckig neben runden Knoepfen. */
.primary, .ghost {
  min-height: var(--tap); padding: 0 16px; flex: none; white-space: nowrap;
  font-size: var(--t-body);
  border-radius: 12px; font: inherit; font-weight: 600; cursor: pointer;
}
/* Gruen heisst: deine Eingabe wird uebernommen. Rot heisst: sie wird
   verworfen. Diese Zuordnung gilt in der ganzen App — auch dort, wo die
   bejahende Antwort die zerstoererische ist (siehe askConfirm mit danger).
   Nach der Farbe zu urteilen, was ein Knopf tut, muss ueberall funktionieren
   oder nirgends. */
.primary { border: none; background: var(--gruen); color: #fff; }
.ghost   { border: 1px solid var(--line); background: transparent; color: var(--text); }
button:disabled { opacity: 0.5; cursor: default; }

/* ---------- Meldungen ---------- */

.note {
  margin: var(--s3) var(--rand); padding: var(--s3) var(--s4);
  border-radius: 10px; border: 1px solid var(--line);
  background: var(--surface); font-size: var(--t-subhead);
}
.note.err  { border-color: var(--danger); color: var(--danger); }
.note.good { border-color: var(--ok); color: var(--ok); }

/* ---------- Anmeldung ---------- */

.login { padding: 48px 20px; max-width: 24rem; margin: 0 auto; }
.login h1 { font-size: var(--t-title1); margin: 0 0 var(--s1); }
.login p  { color: var(--muted); margin: 0 0 var(--s6); }
.login label { display: block; margin-bottom: var(--s4); font-size: var(--t-subhead); color: var(--muted); }
/* Alle Texteingaben gleich behandeln — sonst faellt ein neuer Feldtyp
   (email, tel, …) aus dem Layout. */
.login input:not([type=checkbox]):not([type=radio]) {
  display: block; width: 100%; margin-top: 0.3rem; min-height: var(--tap);
  padding: 0 12px; border: 1px solid var(--line); border-radius: 11px;
  background: var(--surface); color: var(--text); font: inherit;
}
.login .remember { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: var(--t-subhead); }
.login .remember input { width: 22px; height: 22px; }
.login button { width: 100%; margin-top: var(--s2); }
.login .hint { margin-top: var(--s6); font-size: var(--t-cap1); color: var(--muted); line-height: 1.5; }

.spinner {
  width: 20px; height: 20px; border: 2px solid var(--line);
  border-top-color: var(--accent); border-radius: 50%;
  animation: spin 0.7s linear infinite; margin: 48px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

.hidden { display: none !important; }

/* ---------- Burger-Menü ---------- */

.burger {
  width: 44px; height: 44px; flex: none; padding: 0;
  display: grid; place-content: center; gap: 3px;
  background: none; border: 0; cursor: pointer;
}
.burger span {
  display: block; width: 18px; height: 2px; border-radius: 1px;
  background: var(--text); transition: transform 0.18s ease, opacity 0.15s ease;
}
.burger.open span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.burger.open span:nth-child(2) { opacity: 0; }
.burger.open span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

.menupanel {
  position: absolute; right: 1rem; top: calc(100% - 0.4rem); z-index: 40;
  min-width: 12rem; padding: 4px;
  display: grid; gap: 0.15rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.16);
}
.menupanel button {
  min-height: 44px; padding: 0 12px; text-align: left;
  border: none; border-radius: 8px; background: transparent; color: var(--text);
  font: inherit; font-size: var(--t-subhead); cursor: pointer;
}
.menupanel button:active { background: var(--surface-2); }
.menupanel button.danger { color: var(--danger); }

/* ---------- Stornieren: Knopf im Kopfbereich ---------- */

.cancelbar {
  display: block; width: 100%; margin-top: 0.6rem; min-height: 40px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface); color: var(--text);
  font: inherit; font-size: var(--t-subhead); font-weight: 600; cursor: pointer;
}
.cancelbar:active { background: var(--surface-2); }

/* ---------- Auswahlblatt ---------- */

.sheet {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0, 0, 0, 0.45);
}

/* Alle Blätter gleich: weiß, ringsum abgesetzt, deutlich abgehoben. Vorher
   klebten sie am unteren Rand und trugen die Hintergrundfarbe der Seite —
   das sah nach Fortsetzung aus, nicht nach eigener Ebene. */
.sheet-panel {
  width: 100%; max-width: 34rem;
  max-height: calc(88vh - env(safe-area-inset-bottom));
  margin: 0 12px calc(12px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line); border-radius: 20px;
  box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.10), 0 18px 48px rgba(0, 0, 0, 0.22);
  overflow: hidden;
}

.sheet-head {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s4) var(--s4) var(--s2);
}
.sheet-head h2 { margin: 0; flex: 1; font-size: var(--t-body); }

.sheet-close {
  width: 36px; height: 36px; flex: none;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--surface-2); color: var(--text); font-size: var(--t-subhead); cursor: pointer;
}

.sheet-hint {
  margin: 0; padding: 0 var(--s4) var(--s3);
  font-size: var(--t-cap1); line-height: 1.4; color: var(--muted);
}

.sheet-body {
  flex: 1 1 auto; min-height: 24vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0 var(--rand) var(--s2); display: grid; gap: var(--s2); align-content: start;
}
.sheet-body label { display: block; margin-bottom: 0.9rem; font-size: var(--t-subhead); color: var(--muted); }
.sheet-body input:not([type=checkbox]) {
  display: block; width: 100%; margin-top: 0.3rem; min-height: var(--tap);
  padding: 0 12px; border: 1px solid var(--line); border-radius: 11px;
  background: var(--surface-2); color: var(--text); font: inherit;
}
.sheet-body .seclead { margin: 0 0 16px; font-size: var(--t-foot); line-height: 1.45; color: var(--muted); }
.sheet-body .tabs { margin-top: 0; }
.sheet-body .ghost, .sheet-body .primary { width: 100%; }

/* Wie die Menuekarten aufgebaut, nur ohne Linie und Preis — die spielen beim
   Absagen keine Rolle. Der Tag steht vorn, das Gericht dient nur noch der
   Wiedererkennung. */
.pick {
  display: grid; row-gap: var(--s1); width: 100%;
  padding: var(--s3) var(--s4); text-align: left;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; cursor: pointer;
}
.pick-day  { font-size: var(--t-body); font-weight: 700; line-height: 1.25; }
.pick-dish { font-size: var(--t-foot); line-height: 1.3; color: var(--muted); }


/* Ausgewaehlt heisst: wird abgesagt. Kraeftig rot, ohne Groessensprung —
   ein huepfender Knopf lenkt beim Durchtippen nur ab. */
.pick[aria-pressed="true"] {
  background: var(--danger); border-color: var(--danger); color: #fff;
}
.pick[aria-pressed="true"] .pick-dish { color: rgba(255, 255, 255, 0.85); }


.sheet-foot {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4) calc(var(--s3) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
}
.sheet-count { flex: 1; min-width: 0; font-size: var(--t-cap1); color: var(--text-3); white-space: nowrap; }

.sheet-foot .act {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px;
  border-radius: 11px; background: var(--accent); color: var(--accent-ink);
  font-size: var(--t-subhead); font-weight: 600; text-decoration: none; white-space: nowrap;
}
.sheet-foot #cancelPhone { background: transparent; color: var(--text); border: 1px solid var(--line); }
.sheet-foot .act[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }

/* ---------- Kopfzeilen-Aktionen ---------- */

.headactions { display: flex; gap: var(--s2); margin-top: var(--s2); }
.headactions .cancelbar { margin-top: 0; }
.cancelbar.slim { width: auto; flex: none; padding: 0 16px; font-weight: 500; }

/* ---------- Nachrichtenvorschau ---------- */

.preview { flex: none; margin: 0 var(--s4) var(--s2); border-top: 1px solid var(--line); padding-top: var(--s2); }
.preview summary {
  cursor: pointer; font-size: var(--t-subhead); font-weight: 600;
  padding: 4px 0; list-style: revert;
}

/* Ohne Auswahl bleibt die Zeile stehen, nur abgeblendet — sonst rueckt die
   Liste darueber beim ersten Antippen nach oben. */
.preview.leer { opacity: 0.4; pointer-events: none; }
.preview pre {
  margin: var(--s1) 0; padding: var(--s2) var(--s3); max-height: 22vh; overflow: auto;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px;
  font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; word-break: break-word; color: var(--text);
}
.preview-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.preview-note { margin: 8px 0 0; font-size: var(--t-cap1); color: var(--muted); line-height: 1.4; }

.act.ghostact {
  background: transparent; color: var(--text); border: 1px solid var(--line);
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 12px;
  border-radius: 10px; font-size: var(--t-subhead); font-weight: 600;
  text-decoration: none; cursor: pointer; font-family: inherit;
}

/* ---------- Monatsabrechnung ---------- */

.monthnav { margin: 0 var(--s4) var(--s3); }
/* Diese beiden Pfeile hatten gar keine Groessenregel — ihre Trefferflaeche
   war so gross wie das Zeichen selbst, also weit unter jeder Untergrenze. */
.monthnav button {
  min-width: var(--tap); min-height: var(--tap);
  display: grid; place-items: center;
  appearance: none; background: none; border: 0; padding: 0;
  color: var(--text); font: inherit; font-size: var(--t-title2); line-height: 1;
  cursor: pointer;
}
.monthnav .range { font-size: var(--t-body); }

.billsum {
  display: grid; gap: var(--s1); margin-bottom: var(--s3);
  padding: var(--s2) var(--s3); border-radius: 12px; background: var(--surface-2);
  font-size: var(--t-subhead); font-variant-numeric: tabular-nums;
}
.billsum div { display: flex; justify-content: space-between; gap: 8px; }
.billsum .net { padding-top: var(--s1); border-top: 1px solid var(--line); }
.billsum .net b { color: var(--accent); }

.billhead {
  margin: var(--s4) 0 var(--s1); font-size: var(--t-cap1); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted);
}

.billrow {
  display: grid; grid-template-columns: auto 1fr auto; align-items: baseline; gap: var(--s2);
  padding: var(--s2) var(--s3); border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2); font-size: var(--t-subhead);
}
.billrow + .billrow { margin-top: var(--s2); }
.billday   { font-size: var(--t-cap1); color: var(--text-3); font-variant-numeric: tabular-nums; }
.billdish  { min-width: 0; line-height: 1.3; }
.billprice { font-variant-numeric: tabular-nums; color: var(--text-3); }

.billrow.cancelled { opacity: 0.7; border-style: dashed; }
.billrow.cancelled .billdish { text-decoration: line-through; text-decoration-thickness: 1px; }
.billrow.cancelled .tag { margin-left: 0.35rem; text-decoration: none; display: inline-block; }

/* ---------- Kopfzeilen-Aktionen ---------- */

/* ---------- Nachrichtenvorschau ---------- */

/* Ohne Auswahl bleibt die Zeile stehen, nur abgeblendet — sonst rueckt die
   Liste darueber beim ersten Antippen nach oben. */

/* ---------- Protokoll ---------- */

.logentry {
  padding: var(--s2) var(--s3); background: var(--surface);
  border: 1px solid var(--line); border-radius: 12px;
}
.logentry h3 { margin: 0 0 var(--s1); font-size: var(--t-cap1); color: var(--muted); font-weight: 600; }
.logentry ul { margin: 0; padding-left: 1.1rem; font-size: var(--t-subhead); }
.logentry li { margin: var(--s1) 0; }
.logentry .sum { display: block; margin-top: var(--s2); font-size: var(--t-cap1); color: var(--text-3); }

.logmonth {
  display: flex; justify-content: space-between; gap: var(--s2);
  padding: var(--s2) var(--s3); border-radius: 10px; background: var(--surface-2);
  font-size: var(--t-subhead); font-variant-numeric: tabular-nums;
}

/* ---------- Kopfzeile mit Kindwechsel ---------- */

.titlerow { display: flex; align-items: center; gap: 8px; min-height: 40px; }
.titlerow h1 { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Kind auswählen ---------- */

.picklist { display: grid; gap: var(--s2); margin-bottom: var(--s6); }

.pickkid {
  display: flex; align-items: center; gap: 8px; width: 100%;
  min-height: 60px; padding: 0 16px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; cursor: pointer; text-align: left;
}
.pickkid:active { transform: scale(0.99); }
.pickkid:disabled { opacity: 0.5; }
.pickkid-name { flex: 1; font-size: var(--t-body); font-weight: 600; }
.pickkid-go   { color: var(--muted); font-size: var(--t-title3); }

/* ---------- Ersteinrichtung ---------- */

.kid {
  margin: 0 0 var(--s4); padding: var(--s3) var(--s3) var(--s1);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.kid legend { padding: 0 4px; font-size: var(--t-cap1); font-weight: 700; color: var(--muted); }
.login .kid label { margin-bottom: var(--s3); }
.login form > button + button { margin-top: var(--s2); }
.login .ghost { width: 100%; }

/* ---------- Reiter ---------- */

.tabs {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 4px; margin: var(--s6) 0 var(--s4); padding: var(--s1);
  background: var(--surface-2); border-radius: 12px;
}
.tabs button {
  min-height: 44px; padding: 0 var(--s1);
  border: none; border-radius: 9px; background: transparent; color: var(--muted);
  font: inherit; font-size: var(--t-subhead); font-weight: 600; cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.tabs button[aria-selected="true"] {
  background: var(--surface); color: var(--text);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

/* Die Reiterinhalte tragen ihre Abstaende selbst. Vorher lagen die Kinder
   und "Kind hinzufügen" direkt aneinander: Der Abstand des Blattes greift nur
   zwischen SEINEN Kindern, und der Reiterinhalt ist davon eines. Innen war
   dann nichts. */
.tabpanel { animation: fadein 0.16s ease; display: grid; gap: 16px; }
/* Mehrere Kinder untereinander bleiben eng beisammen — sie gehoeren zusammen,
   im Gegensatz zum Knopf darunter. */
.tabpanel #settingsChildren { display: grid; gap: 4px; }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }

.footrow { display: flex; gap: var(--s2); margin-top: var(--s8); }

/* ---------- Konto und Einstellungen ---------- */

.login h2.sec {
  margin: var(--s8) 0 var(--s1); font-size: var(--t-cap1); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
}
.login .seclead { margin: 0 0 16px; font-size: var(--t-foot); line-height: 1.45; color: var(--muted); }
.login label small { font-weight: 400; opacity: 0.8; }
.login a { color: var(--accent); }
.login .picklist { margin-bottom: var(--s3); }
.login .ghost + .ghost { margin-top: var(--s2); }

/* In der Fusszeile stehen die Knoepfe nebeneinander, nicht untereinander.
   Muss nach der Regel darueber stehen, sonst gewinnt deren margin-top. */
.login .footrow .ghost,
.login .footrow .ghost + .ghost { flex: 1; margin-top: 0; }
.pickkid[data-edit] .pickkid-go { font-size: var(--t-cap1); }

.code {
  margin: 8px 0 20px; padding: 16px 12px;
  border: 2px dashed var(--accent); border-radius: var(--radius);
  background: var(--surface); text-align: center;
  font: 700 1.15rem/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.06em; word-break: break-all; user-select: all;
}

/* Die Speicherleiste ist die Stelle, an der die Auswahl verbindlich wird —
   sie darf etwas Gewicht haben. */
.savebar .inner button { min-height: 52px; border-radius: 13px; }

/* Absagen, die der Anbieter noch nicht bestätigt hat: Sie zählen bis dahin
   weiter mit, und das soll man sehen. */
.tag.ok   { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.tag.warn { background: color-mix(in srgb, var(--warn) 24%, transparent); color: var(--warn); }
.billsum .unsure { padding-top: 0.25rem; font-size: var(--t-cap1); color: var(--warn); }
.billsum .unsure b { font-variant-numeric: tabular-nums; }

/* ---------- Rückfrage ---------- */

/* Mittig statt am unteren Rand: Eine Rückfrage ist keine Liste, durch die man
   blättert, sondern eine Entscheidung, die den Blick verdient. */
.sheet-panel.ask {
  width: auto; max-width: 22rem; margin: auto 16px;
  border-radius: 18px; border: 1px solid var(--line);
  padding: 20px 16px 16px;
}
.sheet:has(.ask) { align-items: center; justify-content: center; }

.sheet-panel.ask h2 { margin: 0 0 8px; font-size: var(--t-body); }
.sheet-panel.ask p  { margin: 0 0 20px; font-size: var(--t-subhead); line-height: 1.45; color: var(--muted); }

.askrow { display: flex; gap: 8px; }
/* Umbruch erlauben: Eine laengere Beschriftung soll den Kasten sprengen
   koennen, nicht daraus herauslaufen. */
.askrow button {
  flex: 1 1 0; min-width: 0; min-height: 48px;
  white-space: normal; padding: 0 8px;
}
.askrow .primary.danger { background: var(--danger); color: #fff; }

/* Die Fußzeile des Storno-Blatts trägt drei Schaltflächen — nebeneinander
   wird das auf dem iPhone zu eng, also eine eigene Reihe darunter. */
.sheet-foot { flex-wrap: wrap; }
.sheet-actions { display: flex; gap: 8px; width: 100%; }
.sheet-actions .act { flex: 1; justify-content: center; }
.sheet-actions #cancelPhone { flex: 0 0 auto; padding: 0 16px; }
.sheet-foot .sheet-count { flex: 1 1 100%; margin-bottom: 0.55rem; }
.act:disabled { opacity: 0.45; pointer-events: none; }

/* Die Rueckfrage vor dem Bestellen listet die gewaehlten Essen zeilenweise
   auf. Der Text kommt bewusst ueber textContent in die Seite — damit kann
   ein Gerichtsname kein Markup einschleusen. Damit die Zeilenumbrueche darin
   trotzdem stehen bleiben, uebernimmt das hier das Stylesheet. */
#askText {
  white-space: pre-line;
}

/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt sie auch
   hier nicht: Der Farbwechsel geschieht dann sofort. */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* Das Aufheben gehoert nicht in die Knopfreihe: Drei gleich breite Knoepfe
   nebeneinander sind auf dem Telefon zu eng, und es ist die leiseste der drei
   Handlungen. Als Kreuz oben rechts sagt es dasselbe kuerzer — dieselbe Geste
   wie das Schliessen eines Blattes. */
.stornobar .kopfzeile { display: flex; align-items: center; gap: 8px; }
.stornobar .kopfzeile .summary { flex: 1; min-width: 0; }

/* Das Kreuz nimmt die Farbe der Handlung an, die es ausloest: Es verwirft
   die Vormerkungen. Rund, damit es sich von den eckigen Knoepfen darunter
   als eigene Art von Bedienelement abhebt — es ist keine der beiden
   Hauptaktionen, sondern der Rueckzug. */
.stornobar .sheet-close {
  width: 34px; height: 34px; flex: none; aspect-ratio: 1 / 1;
  border-radius: 50%;
  border: 1.5px solid var(--rot-strich);
  background: transparent; color: var(--rot-strich);
  font-size: var(--t-subhead); line-height: 1; cursor: pointer;
}

/* Fussleiste der Absage. Dieselbe Bauform wie die Speichern-Leiste — zwei
   verschiedene Leisten mit verschiedenem Aussehen waeren nur Verwirrung. */
.stornobar .summary b { color: var(--rot-flaeche); }
.primary.rot {
  background: var(--rot-flaeche); border-color: var(--rot-flaeche); color: #fff;
}
.primary.gruen {
  background: var(--gruen); border-color: var(--gruen); color: #fff;
}
a.primary,
a.ghost {
  display: grid; place-items: center; text-decoration: none;
}
