/* Oberflächengestaltung von KMS.
 *
 * Übernommen aus TMS (Tattoo-Studio-Manager), damit beide Programme sich
 * gleich anfühlen: dieselbe Seitenleiste, dieselben Karten, Tabellen,
 * Knöpfe und Farben. Wer das eine bedienen kann, findet sich im anderen
 * sofort zurecht.
 *
 * Gastronomie-eigene Ergänzungen stehen gesammelt am Ende der Datei.
 */

:root {
  --primary: #2b2b33;
  --primary-dark: #17171d;
  --accent: #8a4fbe;
  --accent-soft: #f2eafa;
  --bg: #f5f5f8;
  --card: #ffffff;
  --border: #e3e3ea;
  --border-strong: #d2d2dc;
  --text: #1d1f24;
  /* Eine Spur dunkler als frueher (#6b6f78). Auf Weiss war der alte Wert in
     Ordnung, auf den eingefaerbten Flaechen darunter – Marke, Chip, die
     hervorgehobene Spalte einer Kalkulation – kam er nur auf 4,3 zu 1. */
  --muted: #656972;
  --good: #2e7d4f;
  --warn: #a06a00;
  --bad: #b3372a;
  --shadow: 0 1px 2px rgba(20, 20, 30, 0.04), 0 4px 16px rgba(20, 20, 30, 0.05);
  --shadow-lift: 0 2px 6px rgba(20, 20, 30, 0.08), 0 12px 28px rgba(20, 20, 30, 0.10);
  --radius: 12px;
  --radius-sm: 8px;

  /* ---- Flaechen unterhalb der Karte ----
     Diese Toene standen frueher als feste Werte in den einzelnen Regeln:
     `background: white`, `#f4f4f7`, `#ececf1`. Im Dunkelmodus blieben sie
     hell stehen, waehrend die Schrift darauf mit `--text` aufhellte – weiss
     auf weiss. Betroffen war ausgerechnet das, was man taeglich anfasst:
     Eingabefelder, Auswahllisten, die Reiter der Scan-Station. Als Token
     gefasst, folgen sie dem Modus mit. */
  --field: #ffffff;       /* Eingabefeld, Auswahlliste, Reiter */
  --surface-2: #f4f4f7;   /* eingelassener Block: Rechenweg, Belegsumme */
  --surface-3: #ececf1;   /* Ablage hinter Karten, Balkenrinne */
  --chip-bg: #ececf1;     /* kleine Marke in einer Tabellenzelle */
  --raster: #f0f0f4;      /* Stundenraster im Belegungsplan */
  --zeile-hover: #fafafc; /* Zeile unter dem Mauszeiger */

  /* Schrift auf einer eingefaerbten Flaeche. Im Hellen ist `--primary` ein
     fast schwarzer Ton, im Dunkeln ein fast weisser – dieselbe Flaeche
     braucht also je nach Modus die andere Schriftfarbe. Fest verdrahtetes
     `color: white` liess den aktiven Reiter der Scan-Station im Dunkeln
     weiss auf hell stehen. */
  --auf-primary: #ffffff;

  /* Knopffarben getrennt von den Signalfarben.
     `--accent` und `--bad` faerben auch Schrift und Raender; im Dunkeln
     hellen sie dafuer auf. Als Knopfflaeche taugen die hellen Werte nicht –
     „Ausbuchen“ stand weiss auf Hellrot. Diese beiden bleiben deshalb in
     beiden Modi kraeftig und tragen immer weisse Schrift. */
  --knopf-accent: #8a4fbe;
  --knopf-bad: #b3372a;
  --auf-signal: #ffffff;

  /* ---- Eingefaerbte Zustaende ----
     Zweimal gebraucht und deshalb zweimal gefasst: kraeftig fuer Marken und
     Meldungen, blass fuer eine ganze Tabellenzeile – eine Zeile in
     Meldungsstaerke ueberschreit den Rest der Liste. */
  /* Die Schriftfarben sind eine Spur dunkler als `--good`/`--warn`: Auf der
     eingefaerbten Flaeche kamen sie sonst nur auf 4,1 bis 4,4 zu 1 und
     blieben damit unter dem, was man in einer Kueche aus zwei Metern noch
     lesen kann. Nachgemessen, nicht geschaetzt. */
  --gut-bg: #e4f3ea;   --gut-rand: #c9e6d5;   --gut-text: #287749;
  --warn-bg: #fbf1dc;  --warn-rand: #efdfba;  --warn-text: #976100;
  --bad-bg: #fbe6e2;   --bad-rand: #f2cec8;   --bad-text: #b3372a;
  --gut-zeile: #eaf5ee;
  --warn-zeile: #fdf7ea;
  --bad-zeile: #fdf0ee;

  /* Sagt dem Browser, in welchem Modus er seine eigenen Bedienelemente
     zeichnet – Bildlaufleisten und vor allem den Kalender hinter einem
     Datumsfeld. Ohne das steht ein dunkles Kalendersymbol auf dunklem Grund. */
  color-scheme: light;

  /* Im Hellen tragen Tabellenkopf und Zebrastreifen keine eigene Flaeche –
     die Linien reichen. Im Dunkeln braucht es beides, sonst verschwimmen die
     Zeilen ineinander. */
  --kopf-bg: transparent;
  --zebra: transparent;
  --logo-filter: none;

  /* ---- Die dunkle Palette, einmal hinterlegt ----
     Zwei Wege fuehren ins Dunkle: die Einstellung des Geraets und der
     Wandmodus fuer das fest montierte Tablet. Frueher setzte der Wandmodus
     nur sechs eigene Werte und liess den Rest hell stehen – auf einem Geraet
     in heller Einstellung war er damit schlechter lesbar als die normale
     Ansicht: weisse Knoepfe mit heller Schrift, dunkle Links auf dunkler
     Karte. Beide Wege greifen jetzt auf diese eine Liste zu; ein geaenderter
     Ton kann nicht mehr nur an einer Stelle ankommen. */
  --d-primary: #cfd6d8;
  --d-primary-dark: #e6ecee;
  --d-accent: #a276d0;
  --d-accent-soft: #262033;
  --d-bg: #12181a;
  --d-card: #1b2325;
  --d-border: #2b3639;
  --d-border-strong: #3d4b4e;
  --d-text: #e8eeef;
  --d-muted: #9aacaf;
  --d-good: #6dbf97;
  --d-warn: #d9a445;
  --d-bad: #e4877c;
  --d-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 4px 16px rgba(0, 0, 0, 0.30);
  --d-shadow-lift: 0 2px 6px rgba(0, 0, 0, 0.45), 0 12px 28px rgba(0, 0, 0, 0.40);

  /* Das Eingabefeld steht bewusst *heller* als die Karte (#1b2325): Ein Feld,
     das man befuellen soll, muss sich vom Grund abheben – im Hellen tut es
     das durch Weiss, im Dunkeln durch den helleren Ton. */
  --d-field: #242e31;
  --d-surface-2: #222b2e;
  --d-surface-3: #151b1d;
  --d-chip-bg: #2b3639;
  --d-raster: #2b3639;
  --d-zeile-hover: #222b2e;

  --d-gut-bg: #152420;   --d-gut-rand: #27473b;   --d-gut-text: #8fd3ae;
  --d-warn-bg: #2a2115;  --d-warn-rand: #4b3c1c;  --d-warn-text: #e0b869;
  --d-bad-bg: #2e1a18;   --d-bad-rand: #50302c;   --d-bad-text: #eda398;
  --d-gut-zeile: #16241f;
  --d-warn-zeile: #251e14;
  --d-bad-zeile: #2a1917;

  /* Im Dunkeln ist `--primary` der helle Wert – die Schrift darauf muss also
     dunkel sein, sonst steht Weiss auf Weiss. Die Knopffarben bleiben
     kraeftig und tragen weiter weisse Schrift. */
  --d-auf-primary: #12181a;
  --d-knopf-accent: #7b45ab;
  --d-knopf-bad: #9e3226;
  --d-auf-signal: #ffffff;
  --d-kopf-bg: #232c2f;
  --d-zebra: rgba(255, 255, 255, 0.015);
  --d-logo-filter: brightness(0.92);
}


* { box-sizing: border-box; }

body {
  font-family: -apple-system, "Segoe UI Variable Text", Segoe UI, Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--primary); }
a:hover { color: var(--accent); }
.muted { color: var(--muted); }
.hint { color: var(--muted); font-size: 0.82rem; margin: 0.25rem 0 0; }

/* ---------- Grundgeruest ---------- */

.layout { display: flex; min-height: 100vh; }

.sidebar {
  width: 244px;
  min-width: 244px;
  background: linear-gradient(180deg, #1c1c23 0%, #141419 100%);
  color: #eef1f3;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  /* Nicht die ganze Leiste scrollt, sondern nur die Menüliste darin: KMS hat
     mehr Einträge als auf einen Notebook-Bildschirm passen, und "Abmelden"
     darf dabei nicht nach unten aus dem Bild wandern. */
  overflow: hidden;
}

.sidebar .brand {
  font-weight: 700;
  font-size: 1.25rem;
  color: white;
  padding: 1.15rem 1.25rem 0.95rem;
  border-bottom: 1px solid rgba(255,255,255,0.10);
  letter-spacing: 0.02em;
}
.sidebar .brand-sub {
  font-size: 0.72rem; font-weight: 500; letter-spacing: 0.06em;
  text-transform: uppercase; color: rgba(255,255,255,0.45); display: block; margin-top: 0.15rem;
}

.sidebar nav { flex: 1; padding: 0.4rem 0 1rem; overflow-y: auto; }

.sidebar .nav-section {
  padding: 1rem 1.25rem 0.35rem;
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.38);
}

/* Die Abschnittsueberschrift ist ein Knopf: Sie klappt ihren Abschnitt zu.
   Aussehen soll sie wie vorher – wer nie darauf drueckt, merkt nichts davon.
   Deshalb keine Knopf-Optik, sondern nur der Pfeil als Hinweis darauf, dass
   hier etwas passiert. */
.sidebar button.nav-section {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  background: none;
  border: 0;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.sidebar button.nav-section:hover { color: rgba(255,255,255,0.75); }
.sidebar button.nav-section::after {
  content: '';
  width: 7px; height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.15s ease;
  flex: none;
}
/* Zugeklappt zeigt der Pfeil nach rechts – dorthin, wo der Inhalt hin ist. */
.sidebar .nav-gruppe.zu button.nav-section::after {
  transform: rotate(-45deg) translate(-1px, 1px);
}
.sidebar .nav-gruppe.zu .nav-gruppe-inhalt { display: none; }

.sidebar nav a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  color: #d8dce2;
  text-decoration: none;
  padding: 0.5rem 1.25rem;
  font-size: 0.94rem;
  font-weight: 500;
  border-left: 3px solid transparent;
  transition: background 0.12s ease, color 0.12s ease;
}
.sidebar nav a svg { width: 17px; height: 17px; flex: none; opacity: 0.75; }
.sidebar nav a:hover { background: rgba(255,255,255,0.07); color: #fff; }
.sidebar nav a.active {
  background: rgba(138,79,190,0.22);
  border-left-color: var(--accent);
  color: #fff;
}
.sidebar nav a.active svg { opacity: 1; }

/* Untereinander, nicht nebeneinander.
   Die Leiste war fuer zwei Dinge gebaut – Name und „Abmelden“ – und stand auf
   `space-between` in einer Zeile. Dazu kamen spaeter der Wandmodus-Schalter
   und der Weg ins Handbuch, und in 244 Pixel Breite passen vier Dinge
   nebeneinander nicht: „Hilfe & Handbuch“ ragte 91 Pixel ueber den Rand
   hinaus, „Abmelden“ 160 – also vollstaendig. Abgeschnitten hat es die
   Seitenleiste, und damit gab es aus der Oberflaeche keinen sichtbaren Weg
   mehr hinaus.

   Untereinander bleibt es lesbar, egal wie lang ein Name oder eine
   Rollenbezeichnung wird. */
.sidebar-footer {
  padding: 0.9rem 1.25rem 1.1rem;
  border-top: 1px solid rgba(255,255,255,0.10);
  font-size: 0.85rem;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.7rem;
}
.sidebar-footer .user-badge { color: white; line-height: 1.3; }
.sidebar-footer .user-badge span { color: rgba(255,255,255,0.5); font-size: 0.76rem; }

/* Die beiden Wege hinaus in einer Zeile, mit Umbruch als Rueckfall. */
.sidebar-footer .fuss-wege { display: flex; flex-wrap: wrap; gap: 0.25rem 1.1rem; }
.sidebar-footer a { color: #c9ced6; text-decoration: none; font-size: 0.82rem; white-space: nowrap; }
.sidebar-footer a:hover { color: #fff; text-decoration: underline; }

/* Der Schalter ueber die ganze Breite: Auf einem Tablet ist er damit sicher
   zu treffen, ohne dass er sich mit den Links um den Platz streitet. */
.sidebar-footer .inline-form { display: block; }
.sidebar-footer .btn { width: 100%; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.container {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: 1.75rem 1.75rem 2.5rem;
  flex: 1;
}

@media (max-width: 900px) {
  .layout { flex-direction: column; }
  .sidebar { width: 100%; min-width: 0; height: auto; position: static; overflow: visible; }
  .sidebar nav { display: flex; flex-wrap: wrap; padding: 0.4rem; overflow: visible; }
  /* Quer ist das Menue eine Reihe von Verweisen. Die Gruppen duerfen sie
     nicht in Kaesten zerlegen – `contents` nimmt die Huelle aus dem Layout
     heraus, die Eintraege bleiben Kinder der Reihe. Zugeklappt wird hier
     nichts: Ohne Ueberschriften gaebe es keinen Weg, es wieder zu oeffnen. */
  .sidebar .nav-gruppe,
  .sidebar .nav-gruppe-inhalt,
  .sidebar .nav-gruppe.zu .nav-gruppe-inhalt { display: contents; }
  /* Auch der Knopf verschwindet – nicht nur die Ueberschrift. Ein Schalter,
     der zuklappt, was quer ohnehin nicht zuklappt, waere eine Schaltflaeche
     ohne Wirkung. */
  .sidebar .nav-section,
  .sidebar button.nav-section { display: none; }
  .sidebar nav a { border-left: none; border-bottom: 3px solid transparent; padding: 0.5rem 0.8rem; }
  .sidebar nav a.active { border-bottom-color: var(--accent); }
  /* Quer ueber den Bildschirm ist Platz genug – hier duerfen die drei Dinge
     wieder nebeneinander, und der Schalter behaelt seine eigene Breite. */
  .sidebar-footer { flex-direction: row; align-items: center; flex-wrap: wrap; gap: 0.6rem 1.4rem; }
  .sidebar-footer .btn { width: auto; }
  .container { padding: 1.1rem; }
}

/* ---------- Seitenkopf ---------- */

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.35rem;
}
.page-head h1 { margin: 0; }
.page-sub { color: var(--muted); margin: 0.3rem 0 0; font-size: 0.92rem; }
.page-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

h1 { font-size: 1.55rem; margin: 0 0 1.1rem; letter-spacing: -0.01em; }
h2 { font-size: 1.12rem; margin: 0 0 0.8rem; letter-spacing: -0.01em; }
h3 { font-size: 1rem; margin: 0 0 0.5rem; }

/* ---------- Karten & Raster ---------- */

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.3rem;
  margin-bottom: 1.15rem;
  box-shadow: var(--shadow);
}
.card h2 { display: flex; align-items: center; gap: 0.5rem; }

/* Eine Karte, die warnt: Der Streifen links macht sie auf einen Blick
   unterscheidbar, ohne dass die ganze Seite rot wird. Benutzt fuer den
   Hinweis auf einem Datensatz, der zum Loeschen vorgemerkt ist. */
.card.hinweis { border-left: 4px solid var(--border-strong); }
.card.hinweis.warn { border-left-color: var(--warn); }
.card.hinweis.bad { border-left-color: var(--bad); }
.card.hinweis > h2 { font-size: 1rem; }
.card.hinweis > p:last-child { margin-bottom: 0; }

.grid { display: grid; gap: 1.15rem; }
.grid > .card { margin-bottom: 0; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.grid + .grid, .grid + .card { margin-top: 1.15rem; }

/* ---------- Tabellen ---------- */

table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 0.62rem 0.55rem; border-bottom: 1px solid var(--border); vertical-align: top; }
th {
  color: var(--muted); font-weight: 600; font-size: 0.74rem;
  text-transform: uppercase; letter-spacing: 0.05em;
  border-bottom: 1px solid var(--border-strong); white-space: nowrap;
}
tr:last-child td { border-bottom: none; }
/* Kopfzeile und Zebrastreifen sind im Hellen durchsichtig und tragen erst im
   Dunkeln eine Flaeche – dort verschwimmen die Zeilen sonst ineinander. */
thead th { background: var(--kopf-bg); }
tbody tr:nth-child(even) td { background: var(--zebra); }
tbody tr:hover td, table tr:hover td { background: var(--zeile-hover); }
td.num, th.num { text-align: right; white-space: nowrap; }
.table-wrap { overflow-x: auto; margin: 0 -0.3rem; padding: 0 0.3rem; }
.row-actions { white-space: nowrap; }

/* Aktionsspalte klebt am rechten Rand.
   Die Terminliste ist breiter als der Bildschirm; ohne das stuenden
   "Erledigt" und "Loeschen" ausserhalb des Sichtbereichs und waeren nur nach
   seitlichem Scrollen erreichbar - also praktisch nicht. */
.table-wrap td.aktionen, .table-wrap th.aktionen {
  position: sticky;
  right: 0;
  background: var(--card);
  white-space: nowrap;
  box-shadow: -8px 0 8px -8px rgba(0, 0, 0, 0.28);
}
tbody tr:hover td.aktionen, table tr:hover td.aktionen { background: var(--zeile-hover); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  background: var(--primary);
  color: var(--auf-primary);
  border: 1px solid transparent;
  padding: 0.6rem 1.05rem;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  /* Die Untergrenze fuer alles, was ein Finger treffen soll. */
  min-height: 46px;
  line-height: 1.25;
  transition: background 0.12s ease, box-shadow 0.12s ease, transform 0.06s ease;
}
.btn:hover { background: var(--primary-dark); color: var(--auf-primary); }
.btn:active { transform: translateY(1px); }
.btn.accent { background: var(--knopf-accent); color: var(--auf-signal); }
.btn.accent:hover { background: #7a41ab; color: var(--auf-signal); }
.btn.secondary { background: var(--field); color: var(--text); border-color: var(--border-strong); }
.btn.secondary:hover { background: var(--surface-2); color: var(--text); }
.btn.danger { background: var(--knopf-bad); color: var(--auf-signal); }
.btn.danger:hover { background: #972e23; color: var(--auf-signal); }
.btn.small {
  /* 32 Pixel waren es vorher – unter jeder Empfehlung (44 bis 48) und mit
     feuchten oder fettigen Fingern auf einem Tablet nicht zuverlaessig zu
     treffen. Ein Fehlgriff neben „Bearbeiten“ ist im Zweifel „Loeschen“. */
  padding: 0.5rem 0.85rem; font-size: 0.88rem; min-height: 44px;
}
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* ---------- Formulare ---------- */

label { display: block; font-weight: 600; margin: 0.75rem 0 0.25rem; font-size: 0.86rem; }
input, select, textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 0.97rem;
  font-family: inherit;
  background: var(--field);
  color: var(--text);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(138,79,190,0.15);
}
input[type="checkbox"] { width: auto; }
textarea { min-height: 74px; resize: vertical; }
form .row { display: flex; gap: 1rem; flex-wrap: wrap; }
form .row > div { flex: 1; min-width: 165px; }

/* Der Preisblock in einer `.row`: Preis, „netto oder brutto“ und MwSt gehoeren
   zusammen und stehen deshalb in einer Zelle untereinander. Er braucht mehr
   Platz als ein einzelnes Feld - sonst drueckt er die Nachbarn auf ihre
   Mindestbreite. */
form .row > .preisblock { flex: 2; min-width: 240px; }
form .row > .preisblock label { display: block; margin-bottom: 0.45rem; }
form .row > .preisblock label:last-of-type { margin-bottom: 0; }
.form-actions { margin-top: 1.15rem; display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.stack-form { margin-top: 0.7rem; max-width: 420px; }

/* Aufklapp-Bereiche (Bearbeiten-Formulare in Tabellen) */
details > summary { cursor: pointer; list-style: none; }
details > summary::-webkit-details-marker { display: none; }
details[open] > summary { margin-bottom: 0.3rem; }

/* ---------- Stammdatenlisten ----------
   Ein Aufbau fuer Lieferanten, Mitarbeiter und Tische: Zustand als Badge,
   Aktionen rechts, und das Bearbeiten-Formular in einer eigenen Zeile UNTER
   dem Datensatz. Vorher steckte es in der ersten Spalte und war damit auf
   einem Tablet halb so breit wie noetig. */

.liste tbody tr.unterzeile > td { border-bottom: 1px solid var(--border-strong); padding-top: 0; }
.liste tbody tr.unterzeile:hover > td { background: transparent; }
.liste tbody tr.unterzeile summary {
  display: inline-block; font-size: 0.8rem; font-weight: 600; color: var(--muted);
  padding: 0.18rem 0.6rem; border: 1px solid var(--border); border-radius: 999px;
}
.liste tbody tr.unterzeile summary:hover { color: var(--text); border-color: var(--border-strong); }
.liste tbody tr.unterzeile details[open] > summary { margin-bottom: 0.7rem; }

/* Zum Loeschen vorgemerkt: sichtbar, aber nicht alarmierend - der Satz ist
   noch da und wird weiter benutzt. Gilt fuer jede Liste, nicht nur die
   Stammdatenlisten: Seit auch Rechnungen vorgemerkt werden koennen, braucht
   die Markierung dieselbe Wirkung in einer gewoehnlichen Tabelle. */
tbody tr.vorgemerkt > td:first-child { box-shadow: inset 3px 0 0 var(--warn, #b26a00); }

/* Die Aktionsspalte darf umbrechen. Ein Wareneingang bringt Menge, Preis,
   Charge und MHD mit - in einer Zeile landet der Knopf sonst ausserhalb des
   Bildes, und die Buchung ist nicht auszuloesen.

   Kein `display: flex` auf der Zelle selbst: Ein <td> mit Flex-Anzeige ist
   fuer den Browser keine Tabellenzelle mehr, er stellt eine unsichtbare
   Zelle darum. Rahmen und Hintergrund haengen dann am Flex-Kasten, der nur
   so hoch ist wie sein Inhalt. Im Kassenbuch - zweizeilige Beschreibungen,
   und bei Buchungen aus einer Rechnung gar kein Knopf - lag die Trennlinie
   der letzten Spalte darum mitten in der Zeile oder schwebte als loser
   Strich ueber einer leeren Zelle. Die Knoepfe ordnen sich deshalb als
   gewoehnliche Zeilenelemente an; die Zelle bleibt eine Zelle. */
.row-actions { white-space: normal; }
.row-actions > * { vertical-align: middle; margin: 0.15rem 0.4rem 0.15rem 0; }
.row-actions > *:last-child { margin-right: 0; }
.row-actions form { display: inline-flex; gap: 0.3rem; align-items: center; flex-wrap: wrap; }
.row-actions input[type="text"], .row-actions input[type="date"] { min-width: 0; }
/* Kurze Hinweise anstelle eines Knopfes ("aus Rechnung", ein Zahldatum)
   sollen nicht mitten im Wort umbrechen - die Spalte ist schmal. */
.row-actions > .muted { white-space: nowrap; }

/* Neuanlage steht ueber der Liste, aber zugeklappt: Gearbeitet wird an dem,
   was schon da ist; angelegt wird seltener. */
.neu-anlegen > summary {
  display: inline-block; font-weight: 600;
  padding: 0.35rem 0.9rem; border-radius: 999px;
  border: 1px solid var(--border-strong); color: var(--text);
}
.neu-anlegen > summary::before { content: "+ "; }
.neu-anlegen[open] > summary { margin-bottom: 0.9rem; }

/* ---------- Badges ---------- */

.badge {
  display: inline-block; padding: 0.12rem 0.55rem; border-radius: 999px;
  font-size: 0.75rem; font-weight: 600; white-space: nowrap;
}
.badge.good { background: var(--gut-bg); color: var(--gut-text); }
.badge.warn { background: var(--warn-bg); color: var(--warn-text); }
.badge.bad { background: var(--bad-bg); color: var(--bad-text); }
.badge.neutral { background: var(--chip-bg); color: var(--muted); }
.badge.accent { background: var(--accent-soft); color: var(--accent); }

/* ---------- Kennzahlen ---------- */

.kpi { text-align: center; padding: 1.15rem 1rem; }
.kpi .value { font-size: 1.7rem; font-weight: 700; color: var(--primary-dark); letter-spacing: -0.02em; }
.kpi .value.good { color: var(--good); }
.kpi .value.bad { color: var(--bad); }
.kpi .value.accent { color: var(--accent); }
.kpi .label { color: var(--muted); font-size: 0.82rem; margin-top: 0.2rem; }

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

.flash {
  padding: 0.75rem 1rem; border-radius: var(--radius-sm); margin-bottom: 1rem;
  font-size: 0.93rem; border: 1px solid transparent;
}
.flash.error { background: var(--bad-bg); border-color: var(--bad-rand); color: var(--bad-text); }
.flash.success { background: var(--gut-bg); border-color: var(--gut-rand); color: var(--gut-text); }
.flash.warn { background: var(--warn-bg); border-color: var(--warn-rand); color: var(--warn-text); }

.empty { color: var(--muted); text-align: center; padding: 1.4rem 0; }

.tag-row { display: flex; gap: 0.4rem; flex-wrap: wrap; margin: 0.4rem 0; }

.toolbar {
  display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.1rem;
}
.toolbar form { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.toolbar input, .toolbar select { width: auto; min-width: 150px; }
.toolbar label { margin: 0; }

/* ---------- Kanban ---------- */

.kanban-board { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 1rem; align-items: start; }
.kanban-col { background: var(--surface-3); border-radius: var(--radius); padding: 0.8rem; }
.kanban-col h3 { margin: 0.2rem 0.25rem 0.75rem; font-size: 0.92rem; }
.kanban-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.7rem 0.8rem; margin-bottom: 0.6rem; box-shadow: var(--shadow);
}
.kanban-card .title { font-weight: 600; }
.kanban-card .meta { color: var(--muted); font-size: 0.82rem; margin-top: 0.2rem; }

/* ---------- Kuechenmonitor ----------
   Gebaut fuer zwei Meter Abstand: grosse Flaechen, drei Knoepfe je Posten,
   Farbe als Ampel. Zusammen mit dem Wandmodus wird daraus ein Bildschirm,
   den man vom Pass aus lesen kann. */

.bon-tafel {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 1rem; align-items: start; margin-bottom: 1.2rem;
}
.bon {
  background: var(--card); border: 1px solid var(--border); border-left: 5px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}
/* Wie lange der Bon steht - die Zahl, nach der am Pass entschieden wird. */
.bon.knapp { border-left-color: var(--warn); }
.bon.spaet { border-left-color: var(--bad); }
.bon.fertig { border-left-color: var(--good); opacity: 0.72; }
/* Gekocht, aber noch nicht bezahlt. Bewusst NICHT gedimmt wie ein bezahlter
   Bon: Hier steht noch Geld aus, und der Tisch ist noch besetzt. */
.bon.wartet { border-left-color: var(--good); }
/* Die Veranstaltung hebt sich ab: Sie hat eine Uhrzeit, zu der es fertig
   sein muss, und die kennt niemand auswendig. */
.bon-feier { border-left-color: var(--accent); }

.bon-kopf {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
  padding: 0.65rem 0.85rem; background: var(--surface-3); border-bottom: 1px solid var(--border);
}
.bon-nr { font-weight: 700; font-size: 1.05rem; }
.bon-name { font-weight: 500; }
.bon-zeit { margin-left: auto; color: var(--muted); font-size: 0.84rem; white-space: nowrap; }
.bon-notiz { margin: 0; padding: 0.5rem 0.85rem; font-size: 0.86rem; color: var(--muted); }

.bon-posten { list-style: none; margin: 0; padding: 0; }
.posten { padding: 0.7rem 0.85rem; border-top: 1px solid var(--border); }
.posten:first-child { border-top: 0; }
.posten-was { display: flex; gap: 0.5rem; align-items: baseline; }
.posten-menge { font-weight: 700; font-variant-numeric: tabular-nums; }
.posten-name { font-weight: 600; }
.posten-wer { color: var(--muted); font-size: 0.82rem; margin-top: 0.15rem; }
.posten-notiz { font-size: 0.85rem; margin-top: 0.25rem; }
.posten-stand { font-size: 0.8rem; margin-top: 0.35rem; }
.posten-rezept { margin-top: 0.4rem; font-size: 0.86rem; }
.posten-rezept summary { cursor: pointer; color: var(--muted); }
.posten-rezept .prewrap { margin-top: 0.35rem; }
.posten-knoepfe { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.5rem; }
.posten-knoepfe .inline-form { margin: 0; }

/* Der Stand als Flaeche und nicht nur als Wort: Auf Abstand zaehlt die Farbe. */
.posten-in_progress { background: var(--warn-zeile); }
.posten-done { background: var(--gut-zeile); }
.posten-done .posten-name { text-decoration: line-through; }
.posten-cancelled { background: var(--bad-zeile); }
.posten-cancelled .posten-name { text-decoration: line-through; }

.bon-fuss {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; justify-content: space-between;
  padding: 0.55rem 0.85rem; border-top: 1px solid var(--border); background: var(--surface-3);
  font-size: 0.82rem;
}
.bon-fuss .inline-form { margin: 0; }
.monitor-auto { display: flex; align-items: center; gap: 0.4rem; font-size: 0.86rem; margin: 0; }
.monitor-auto input { min-width: 0; width: auto; }

/* ---------- Postenstand: „wo haengt es?“ ----------
   Die Frage, die ein Bildschirm mit zwoelf Bons nicht beantwortet. Eine
   Kachel je Posten, jede ein Weg auf dessen eigenen Bildschirm. Die Faerbung
   folgt derselben Regel wie am Bon: ab zehn Minuten knapp, ab zwanzig spaet. */

.postenstand-reihe {
  display: grid; gap: 0.6rem;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
}
.postenstand-kachel {
  display: flex; flex-direction: column; gap: 0.2rem;
  padding: 0.7rem 0.85rem; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2); color: inherit; text-decoration: none;
}
a.postenstand-kachel:hover { border-color: var(--accent); }
.postenstand-kachel .ps-name { font-weight: 700; }
.postenstand-kachel .ps-zahlen { font-size: 0.85rem; font-variant-numeric: tabular-nums; }
.postenstand-kachel .ps-warten { font-size: 0.8rem; color: var(--muted); }
.postenstand-kachel .ps-offen { color: var(--bad); }
.postenstand-kachel .ps-laufend { color: var(--warn); }
/* Nichts mehr offen: Die Kachel tritt zurueck, statt mit einer Null zu
   winken. Am Pass zaehlt, was NICHT fertig ist. */
.postenstand-kachel.fertig { background: var(--gut-zeile); }
.postenstand-kachel.fertig .ps-offen,
.postenstand-kachel.fertig .ps-laufend { color: var(--muted); }
.postenstand-kachel.knapp { background: var(--warn-zeile); }
.postenstand-kachel.spaet { background: var(--bad-zeile); border-color: var(--bad); }

.postenwahl-reihe { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* ---------- Gaenge auf dem Bon ----------
   Was zu einem Gang gehoert, geht zusammen raus - auch wenn es drei Posten
   machen. Ohne die Zwischenzeile stehen zwoelf Zeilen untereinander und die
   Zusammengehoerigkeit steht nur in der Kleinschrift. */
.bon-gang-titel {
  padding: 0.35rem 0.85rem; background: var(--surface-3);
  border-top: 1px solid var(--border);
  font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
}
.bon-gang-titel .muted { font-weight: 500; text-transform: none; letter-spacing: 0; }
/* „ohne Gang“ ist keine Ordnungszahl, sondern die Auskunft, dass es keine
   gibt – es tritt entsprechend zurueck. */
.bon-gang-titel.ohne-gang { color: var(--muted); font-weight: 600; }
/* ---------- Das Gericht als Klammer ----------
   Ein Gericht beschaeftigt oft mehrere Posten: den Zander macht der Saucier,
   das Gratin dazu der Entremetier. Als lose Zeilen nebeneinander steht auf
   dem Bon dreimal etwas, das zusammen EIN Teller ist. Wer entscheiden soll,
   ob der Teller rauskann, liest so am Bon vorbei. */
.bon-gericht { border-top: 1px solid var(--border); }
.bon-gericht:first-child { border-top: 0; }
.gericht-kopf {
  display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.55rem 0.85rem 0.15rem;
  cursor: pointer;
}
.gericht-menge { font-weight: 700; font-variant-numeric: tabular-nums; }
.gericht-name { font-weight: 700; font-size: 1.02rem; }
/* Die Bilanz des Tellers: am offenen die Zaehlung, am fertigen die einzige
   Zeile, die er noch hat. */
.gericht-stand { margin-left: auto; font-size: 0.8rem; color: var(--muted); }

/* **Ein fertiger Teller klappt zusammen.** Am Pass zaehlt, was noch NICHT
   fertig ist; was durch ist, braucht eine Zeile und nicht vier. Er tritt
   dabei zurueck, ohne zu verschwinden – wer nachsehen will, wer wann
   abgehakt hat, tippt darauf. */
.bon-gericht.fertig { background: var(--gut-zeile); }
.bon-gericht.fertig .gericht-name { color: var(--muted); font-weight: 600; }
.bon-gericht.fertig .gericht-stand { color: var(--good); font-weight: 700; }
.bon-gericht.fertig > .gericht-kopf { padding-bottom: 0.55rem; }
/* Zugeklappt braucht der Teller keinen eigenen Abschluss. */
.bon-gericht:not([open]) > .gericht-kopf { padding-bottom: 0.5rem; }

/* Die Arbeiten ruecken unter ihre Ueberschrift ein – so ist auf einen Blick
   zu sehen, was zu welchem Teller gehoert. */
.bon-gericht .bon-posten { padding-left: 0.85rem; }
.bon-gericht .posten { border-top: 0; padding-top: 0.35rem; padding-bottom: 0.55rem; }

/* Der Gang am einzelnen Posten: klein und rechts, damit er den Namen nicht
   verdraengt. */
.posten-gang {
  margin-left: auto; font-size: 0.74rem; font-weight: 700;
  color: var(--accent); white-space: nowrap;
}
/* Unter einer Gericht-Ueberschrift steht der Gang schon in der Zwischenzeile
   darueber – an jeder Arbeit wiederholt waere er Rauschen. */
.bon-gericht .posten-gang { display: none; }

/* ---------- Notizkacheln ----------
   Ein Textfeld ist im Service der langsamste Weg, den es gibt:
   Bildschirmtastatur auf, tippen, Tastatur verdeckt den Bonknopf, Tippfehler.
   „ohne Zwiebeln“ ist neunmal von zehn gemeint - also ist es eine Kachel. */
.posten-notizfeld { margin-top: 0.45rem; font-size: 0.86rem; }
.posten-notizfeld summary { cursor: pointer; color: var(--muted); }
.notiz-form { display: flex; flex-direction: column; gap: 0.45rem; margin-top: 0.4rem; }
.notiz-form .btn { align-self: flex-start; }

.notiz-kacheln { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.notiz-kachel {
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface-2);
  color: var(--text); padding: 0.3rem 0.75rem; font-size: 0.84rem; cursor: pointer;
  min-height: 36px;
}
.notiz-kachel:hover { border-color: var(--accent); }
/* Was schon im Feld steht, faerbt seine Kachel: Ohne das naehme der zweite
   Tipp unversehens etwas weg. */
.notiz-kachel.gesetzt {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
/* Beim Bonieren wird mit dem Daumen bedient - dort duerfen sie groesser sein. */
.notiz-kacheln-gross { margin: 0.5rem 0 0.9rem; }
.notiz-kacheln-gross .notiz-kachel { min-height: 44px; padding: 0.45rem 0.95rem; font-size: 0.92rem; }

/* Im Wandmodus wird der Monitor zum Bildschirm: weniger Spalten, groessere
   Schrift, Knoepfe, die man im Vorbeigehen trifft. */
body[data-wandmodus="1"] .bon-tafel { grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); }
body[data-wandmodus="1"] .bon-nr { font-size: 1.3rem; }
body[data-wandmodus="1"] .posten-name { font-size: 1.1rem; }
body[data-wandmodus="1"] .bon-gang-titel { font-size: 0.92rem; }
body[data-wandmodus="1"] .gericht-name { font-size: 1.2rem; }
body[data-wandmodus="1"] .postenstand-kachel .ps-name { font-size: 1.15rem; }
body[data-wandmodus="1"] .postenstand-kachel .ps-zahlen { font-size: 1rem; }
/* Am Wandbildschirm wird nicht getippt - die Notizkacheln nehmen dort nur
   Platz weg. Gelesen wird die Notiz weiterhin: Sie steht am Posten. */
body[data-wandmodus="1"] .posten-notizfeld { display: none; }

/* ---------- Buchungsworkflow ----------
   Die Reihenfolge des Tages als Folge von Karten: Nummer, Regel, was ansteht.
   Bewusst untereinander und nicht nebeneinander - eine Reihenfolge liest man
   von oben nach unten. */

.wf-schritt h2 { display: flex; align-items: center; gap: 0.6rem; }
.wf-nummer {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.9rem; border-radius: 999px; flex: none;
  background: var(--accent-soft); color: var(--accent); font-size: 0.95rem; font-weight: 700;
}
.wf-regel { margin: 0.2rem 0 0.4rem; }
.wf-stand { list-style: none; margin: 0.8rem 0; padding: 0; display: grid; gap: 0.4rem; }
.wf-stand li a {
  display: flex; align-items: baseline; gap: 0.6rem; text-decoration: none;
  padding: 0.45rem 0.7rem; border-radius: var(--radius-sm);
  background: var(--surface-3); color: var(--text);
}
.wf-stand li a:hover { background: var(--surface-2); }
.wf-stand li.warn a { background: var(--warn-zeile); }
.wf-stand li.bad a { background: var(--bad-zeile); }
.wf-zahl { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 2.2rem; }
.wf-text { color: var(--muted); }
.wf-stand li.warn .wf-text, .wf-stand li.bad .wf-text { color: var(--text); }

/* ---------- Balkendiagramme ---------- */

.bar-row { display: flex; align-items: center; gap: 0.7rem; margin: 0.3rem 0; }
.bar-row .bar-label { width: 130px; min-width: 130px; font-size: 0.84rem; color: var(--muted); text-align: right; }
.bar-row .bar-track { flex: 1; background: var(--surface-3); border-radius: 999px; height: 20px; overflow: hidden; }
.bar-row .bar-fill { background: var(--accent); height: 100%; border-radius: 999px; min-width: 2px; transition: width 0.3s ease; }
.bar-row .bar-fill.income { background: var(--good); }
.bar-row .bar-fill.expense { background: var(--bad); }
.bar-row .bar-value { font-size: 0.84rem; white-space: nowrap; min-width: 90px; text-align: right; }

/* ---------- Login ---------- */

.login-wrap { display: flex; justify-content: center; padding-top: 8vh; }
.login-card { max-width: 390px; width: 100%; text-align: left; box-shadow: var(--shadow-lift); }

/* ---------- Unternehmenslogo ----------
   Das Logo eines Betriebs kann quer oder hoch sein; deshalb ueberall eine
   Hoehenbegrenzung und `object-fit: contain`, damit nichts verzerrt. */
img.brand-logo { filter: var(--logo-filter); }
.brand-logo {
  display: block; max-width: 100%; max-height: 46px;
  object-fit: contain; margin-bottom: 0.5rem;
}
.login-logo { display: block; max-width: 100%; max-height: 70px; object-fit: contain; margin-bottom: 0.9rem; }
.logo-vorschau {
  max-width: 260px; max-height: 110px; object-fit: contain;
  /* Bleibt auch im Dunkeln weiss: Ein Betriebslogo ist meist dunkle Tinte
     auf durchsichtigem Grund und waere auf dunkler Flaeche unsichtbar. */
  padding: 0.6rem; border: 1px solid var(--border); border-radius: 8px; background: #fff;
}

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

.section-tabs { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
.section-tabs a {
  text-decoration: none; padding: 0.42rem 0.9rem; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--field); color: var(--text); font-size: 0.88rem;
}
.section-tabs a:hover { border-color: var(--accent); color: var(--accent); }
.section-tabs a.active { background: var(--primary-dark); color: var(--auf-primary); border-color: var(--primary-dark); }

/* ---------- Kanban-Kartenvorschau ---------- */
/* Bildet das PDF-Layout nach (Karte 100 x 60 mm), damit vor dem Druck
   sichtbar ist, was auf dem Papier landet. */

.cards-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; position: sticky; top: 0.6rem; z-index: 5;
}

.kanban-print-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 1rem; margin-top: 1.15rem;
}

.kb-card {
  position: relative; display: flex; flex-direction: column;
  aspect-ratio: 100 / 60; background: var(--card); cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  overflow: hidden; box-shadow: var(--shadow); transition: box-shadow .15s, opacity .15s;
}
.kb-card:hover { box-shadow: var(--shadow-lift); }
/* Abgewählte Karte blasser - auf einen Blick sichtbar, was gedruckt wird.
   Gesteuert über die Klasse .is-off statt über :has(input:checked): Chrome
   erneuert die :has()-Auswertung nicht zuverlässig, wenn `checked` per
   JavaScript gesetzt wird (Knöpfe "Alle"/"Keine"). */
.kb-card.is-off { opacity: 0.42; filter: saturate(0.25); }

.kb-check {
  position: absolute; top: 0.55rem; right: 0.55rem; width: 20px; height: 20px;
  border-radius: 5px; border: 2px solid rgba(255,255,255,0.85); background: transparent;
}
.kb-card:not(.is-off) .kb-check { background: white; border-color: white; }
.kb-card:not(.is-off) .kb-check::after {
  content: ""; position: absolute; left: 5px; top: 1px;
  width: 6px; height: 11px; border: solid var(--accent);
  border-width: 0 2.5px 2.5px 0; transform: rotate(45deg);
}

.kb-head {
  background: var(--knopf-accent); color: var(--auf-signal); padding: 0.4rem 0.7rem;
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
}
.kb-brand { font-weight: 700; font-size: 0.74rem; letter-spacing: 0.12em; }
.kb-loc {
  font-weight: 700; font-size: 0.76rem; margin-right: 1.6rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.kb-body { flex: 1; padding: 0.6rem 0.7rem 0.2rem; min-width: 0; position: relative; }

/* QR rechts in einer eigenen Spalte - der Text links endet davor, damit nie
   Schrift über dem Code liegt (das war beim alten Strichcode das Problem). */
.kb-qr {
  position: absolute; top: 0.5rem; right: 0.7rem; width: 27%;
  display: flex; flex-direction: column; align-items: center; gap: 0.15rem;
}
.kb-qr svg { width: 100%; height: auto; display: block; }
.kb-qr span {
  /* Der Code unter dem QR ist zum Abtippen da, wenn der Scanner streikt –
     dafuer muss er lesbar sein. */
  font-family: "Consolas", "SF Mono", monospace; font-size: 0.74rem;
  color: var(--muted); letter-spacing: 0.02em;
}
/* Platz für die QR-Spalte freihalten */
.kb-name, .kb-cat, .kb-row, .kb-supplier { padding-right: 30%; }
.kb-name {
  font-weight: 700; font-size: 1.02rem; line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-cat { color: var(--muted); font-size: 0.75rem; margin-top: 0.1rem; }

.kb-row { display: flex; gap: 0.7rem; margin-top: 0.5rem; align-items: stretch; }
.kb-qty {
  background: var(--surface-2); border-radius: 6px; padding: 0.3rem 0.55rem;
  min-width: 104px; display: flex; flex-direction: column; justify-content: center;
}
.kb-qty strong { font-size: 1.05rem; line-height: 1.1; }
.kb-fields { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; flex: 1; }
.kb-fields b, .kb-supplier b {
  display: block; font-size: 0.8rem; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.kb-label {
  /* 0,58 rem waren rund 9 Pixel und aus einem Meter nicht mehr lesbar. */
  display: block; font-size: 0.75rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.kb-supplier { margin-top: 0.45rem; }

.kb-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.35rem 0.7rem 0.5rem; border-top: 1px dashed var(--border-strong);
  font-size: 0.72rem; color: var(--muted);
}
.kb-barcode { font-family: "Consolas", "SF Mono", monospace; letter-spacing: 0.05em; }

@media (max-width: 700px) {
  .kanban-print-grid { grid-template-columns: 1fr; }
  .cards-bar { position: static; }
}

/* ---------- Scan-Station: Modus-Umschalter und Kamera ---------- */

.mode-switch { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; margin-bottom: 0.9rem; }
.mode {
  display: flex; align-items: center; gap: 0.6rem; cursor: pointer; margin: 0;
  border: 2px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 0.6rem 0.7rem; background: var(--card); font-weight: 400;
}
.mode input { display: none; }
.mode small { color: var(--muted); }
.mode.active { border-color: var(--accent); background: var(--accent-soft); }
.mode-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; }
.mode-dot.bad { background: var(--bad); }
.mode-dot.good { background: var(--good); }

.scan-view {
  position: relative; background: #101014; border-radius: var(--radius-sm);
  overflow: hidden; aspect-ratio: 4 / 3;
}
.scan-view video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Quadratischer Rahmen - der QR-Code ist quadratisch */
.scan-frame {
  position: absolute; top: 10%; bottom: 10%; aspect-ratio: 1 / 1;
  left: 50%; transform: translateX(-50%);
  border: 2px solid rgba(255,255,255,0.85); border-radius: 6px;
  box-shadow: 0 0 0 9999px rgba(0,0,0,0.35);
}
#scanner:not(.laeuft) .scan-frame { display: none; }
/* Kurze Pause nach einem Treffer: Bild abdunkeln, damit sichtbar ist,
   dass gebucht wird - danach laeuft die Kamera von selbst weiter. */
#scanner.pause .scan-view video { filter: brightness(0.45) grayscale(0.6); }
#scanner.pause .scan-frame { border-color: var(--good); border-width: 3px; }

/* Charge/Haltbarkeit nur im VOLL-Modus */
.voll-felder { transition: opacity .15s; }
.voll-felder.aus { display: none; }

.scan-log { list-style: none; margin: 0; padding: 0; max-height: 260px; overflow-y: auto; }
.scan-log li {
  padding: 0.4rem 0.6rem; border-left: 3px solid var(--border-strong);
  font-size: 0.86rem; margin-bottom: 0.3rem; background: var(--surface-2); border-radius: 0 6px 6px 0;
}
.scan-log li.gut { border-left-color: var(--good); }
.scan-log li.schlecht { border-left-color: var(--bad); color: var(--bad); }

.scan-status { margin: 0.6rem 0 0; font-size: 0.88rem; color: var(--muted); }
.scan-status.good { color: var(--good); font-weight: 600; }
.scan-status.bad { color: var(--bad); font-weight: 600; }

/* ---------- Dialogfenster (z.B. nach dem Beleg-Upload) ---------- */

.dialog-backdrop {
  display: flex; align-items: flex-start; justify-content: center;
  padding: 2.5rem 0; min-height: 60vh;
}
.dialog { max-width: 560px; width: 100%; box-shadow: var(--shadow-lift); }
.dialog h1 { margin: 0 0 0.3rem; font-size: 1.3rem; color: var(--good); }
.dialog table { margin-top: 0.9rem; }
.dialog-filename {
  margin-top: 1rem; padding: 0.7rem 0.8rem;
  background: var(--accent-soft); border-radius: var(--radius-sm);
}
.dialog-filename code { font-size: 0.86rem; word-break: break-all; }

/* ---------- Speicherort auf dem eigenen Rechner ---------- */

.folder-box {
  display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap;
  padding: 0.8rem 0.9rem; margin: 1rem 0 0;
  background: var(--accent-soft); border-radius: var(--radius-sm);
}
.folder-box .folder-icon { font-size: 1.3rem; line-height: 1; }
.folder-box .folder-text { flex: 1 1 14rem; min-width: 0; }
.folder-box .folder-text strong { word-break: break-word; }
.folder-box .folder-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.folder-name { font-weight: 600; }

/* ---------- Kurzmeldungen beim Speichern ---------- */

.toast-host {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 60;
  display: flex; flex-direction: column; gap: 0.5rem;
  max-width: min(26rem, calc(100vw - 2rem));
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  background: var(--card); color: var(--text);
  border: 1px solid var(--border-strong); border-left-width: 4px;
  border-radius: var(--radius-sm); box-shadow: var(--shadow-lift);
  padding: 0.65rem 0.85rem; font-size: 0.88rem; word-break: break-word;
  white-space: pre-line;   /* Erfolgsmeldung steht auf drei Zeilen */
}
.toast-ok { border-left-color: var(--good); }
.toast-bad { border-left-color: var(--bad); color: var(--bad); }
.toast-wait { border-left-color: var(--accent); color: var(--muted); }
.toast-info { border-left-color: var(--border-strong); }

footer { text-align: center; color: var(--muted); padding: 1.8rem; font-size: 0.82rem; }

@media print {
  .sidebar, footer, .toolbar, .page-actions, .no-print, .toast-host { display: none !important; }
  .main { display: block; }
  .card { border: none; box-shadow: none; }
  body { background: white; }
}

/* ---------- Kanban-Karten am Board: anklickbar, Zustand auf einen Blick ---------- */

.kbb-row {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 0.7rem 0; border-bottom: 1px solid var(--border);
}
.kbb-row:last-child { border-bottom: none; }
.kbb-info { flex: 1 1 18rem; min-width: 0; line-height: 1.35; }
.kbb-info span { display: block; font-size: 0.82rem; }
.kbb-cards { display: flex; gap: 0.45rem; flex-wrap: wrap; }
.kbb-cards form { margin: 0; }
.kbb-count { font-size: 0.82rem; color: var(--muted); white-space: nowrap; min-width: 5.5rem; text-align: right; }
.kbb-count.warn { color: var(--bad); font-weight: 600; }

/* Die Kachel ist der Knopf - Farbe traegt die Aussage, die Schrift bestaetigt sie
   (Farbe allein reicht bei Rot/Gruen nicht fuer alle Augen). */
.kbb-chip {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 3.4rem; min-height: 3.4rem; gap: 0.1rem;
  border: 2px solid transparent; border-radius: var(--radius-sm);
  font-family: inherit; font-weight: 700; cursor: pointer;
  transition: transform 0.06s ease, box-shadow 0.12s ease, background 0.12s ease;
}
.kbb-chip:hover { box-shadow: var(--shadow-lift); }
.kbb-chip:active { transform: translateY(1px); }
.kbb-chip:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.kbb-chip-no { font-size: 1.05rem; line-height: 1; }
.kbb-chip-state { font-size: 0.75rem; letter-spacing: 0.06em; }

.kbb-chip.voll { background: var(--gut-bg); border-color: var(--good); color: var(--gut-text); }
.kbb-chip.voll:hover { background: var(--gut-zeile); }
.kbb-chip.leer { background: var(--bad-bg); border-color: var(--bad); color: var(--bad-text); }
.kbb-chip.leer:hover { background: var(--bad-zeile); }

@media (prefers-reduced-motion: reduce) {
  .kbb-chip { transition: none; }
}


/* ---------------------------------------------------------------------------
 * Ergänzungen für die Gastronomie
 * ------------------------------------------------------------------------- */

/* Allergen-Kennzeichen: klein, rund, in der Zeile lesbar. */
.allergen {
  display: inline-block; min-width: 1.35rem; text-align: center;
  padding: 0.05rem 0.3rem; margin-right: 0.15rem;
  border-radius: 4px; background: var(--accent-soft); color: var(--accent);
  font-size: 0.72rem; font-weight: 700;
}

/* Haltbarkeit: die Ampel, auf die es im Kühlhaus ankommt. */
tr.mhd-abgelaufen td { background: var(--bad-zeile); }
tr.mhd-knapp td { background: var(--warn-zeile); }
tr.unter-minimum td { background: var(--bad-zeile); }

/* Tagesplan: eine Zeile je Reservierung, Uhrzeit gross vorne. */
.tagesplan { list-style: none; margin: 0; padding: 0; }
.tagesplan li {
  display: flex; gap: 0.9rem; align-items: baseline;
  padding: 0.55rem 0; border-bottom: 1px solid var(--border);
}
.tagesplan li:last-child { border-bottom: none; }
.tagesplan .zeit {
  font-weight: 700; font-size: 1.05rem; min-width: 3.6rem;
  font-variant-numeric: tabular-nums;
}
.tagesplan .wer { flex: 1 1 12rem; min-width: 0; }
.tagesplan .wer span { display: block; font-size: 0.82rem; color: var(--muted); }

/* Kalkulation: Zielwert-Vergleich in der Zeile. */
.quote-gut { color: var(--good); font-weight: 600; }
.quote-schlecht { color: var(--bad); font-weight: 600; }

/* Netzadresse auf der Startseite - gross genug zum Abtippen am Tablet. */
.netzadresse {
  display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap;
  padding: 0.75rem 0.9rem; margin-top: 0.9rem;
  background: var(--accent-soft); border-radius: var(--radius-sm);
}
.netzadresse code {
  font-size: 1.02rem; font-weight: 700; letter-spacing: 0.02em;
  word-break: break-all;
}

/* Scan-Station: das Eingabefeld ist der Arbeitsplatz - entsprechend gross. */
.scan-eingabe {
  font-size: 1.25rem; padding: 0.85rem 0.9rem; text-align: center;
  letter-spacing: 0.06em;
}

/* Zahlenkolonnen in Tabellen gleichmässig ausrichten. */
td.num, th.num, .num { font-variant-numeric: tabular-nums; }

/* ---------- Formularraster ----------
   Die meisten Masken sind zweispaltig: Beschriftung über dem Feld, zwei
   Felder nebeneinander. Auf dem Tablet fällt das automatisch auf eine
   Spalte zusammen - das ist der ganze Grund für `auto-fit`. */
.form-grid {
  display: grid; gap: 0 1rem;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  align-items: start;
}
.form-grid > .wide { grid-column: 1 / -1; }
.form-grid label.check {
  display: flex; align-items: center; gap: 0.5rem;
  font-weight: 500; margin-top: 1.5rem;
}
.form-grid label.check input { margin: 0; }
.form-grid .form-actions { margin-top: 1.15rem; }

/* Mehrere kleine Formulare in einer Tabellenzeile nebeneinander. */
.inline-form { display: inline-flex; gap: 0.3rem; align-items: center; margin-right: 0.4rem; }
.inline-form input, .inline-form select { width: auto; min-width: 0; padding: 0.3rem 0.4rem; font-size: 0.84rem; }

/* Kleine Marken für Aufzählungen in Tabellenzellen (Lagerorte, feste Werte). */
.chip {
  display: inline-block; margin: 0 0.25rem 0.25rem 0;
  padding: 0.1rem 0.5rem; border-radius: 999px;
  background: var(--chip-bg); color: var(--muted); font-size: 0.78rem; white-space: nowrap;
}
/* Eine Charge, deren Frist drueckt - in der Kartenuebersicht faellt damit auf,
   an welchem Fach etwas liegt, das weg muss. */
.chip.chip-warn { background: var(--warn-zeile); color: var(--text); }
.chip.chip-bad { background: var(--bad-zeile); color: var(--text); }

/* Vorzeichen in Geldspalten - Farbe statt Minuszeichen suchen. */
td.pos, .pos { color: var(--good); }
td.neg, .neg { color: var(--bad); }

/* Freitexte mit eigenen Zeilenumbrüchen (Zubereitung, Notizen). */
.prewrap { white-space: pre-wrap; }

/* Die gerade geöffnete Zeile einer Auswahlliste. */
tr.row-active td { background: var(--accent-soft); }

/* ---------- QR-Codes ---------- */
.qr-block { display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
.qr-block svg {
  width: 200px; height: 200px; flex: none;
  /* Ebenfalls fest weiss: Ein QR-Code braucht seinen hellen Rand, sonst
     findet ihn keine Handy-Kamera. */
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px; background: white;
}
/* In Tabellen klein - dort zählt die Übersicht, nicht die Scanbarkeit. */
td .qr-mini svg { width: 62px; height: 62px; display: block; }

/* Befehlszeilen zum Abtippen oder Kopieren. */
pre.befehl {
  background: #17171d; color: #e8e8ee; padding: 0.8rem 0.9rem;
  border-radius: var(--radius-sm); overflow-x: auto;
  font-family: "Consolas", "SF Mono", monospace; font-size: 0.84rem;
  user-select: all;
}

/* ---------- Zahlenfelder ohne Pfeile ----------
   Die kleinen Auf/Ab-Pfeile treffen mit der Maus niemand, verstellen den Wert
   beim Scrollen über dem Feld und sind auf einem Tablet vollends unbrauchbar.
   Getippt wird ohnehin. `inputmode` sorgt weiter für die Zifferntastatur. */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---------- Belegungsplan ----------
   Ein Zeitraster aus Tischen und Stunden. Die Blöcke sitzen in Prozent statt
   in Pixeln, damit das Raster auf dem Tablet genauso stimmt wie am Bildschirm
   im Büro. */
.belegung { display: flex; flex-direction: column; gap: 2px; min-width: 640px; }
.belegung-kopf, .belegung-zeile { display: flex; align-items: stretch; gap: 0.5rem; }
.belegung-name {
  width: 120px; min-width: 120px; display: flex; flex-direction: column;
  justify-content: center; font-size: 0.86rem; line-height: 1.2;
}
.belegung-name .muted { font-size: 0.74rem; }
.belegung-spur {
  position: relative; flex: 1; min-height: 34px;
  background: repeating-linear-gradient(
    to right, var(--raster) 0 1px, transparent 1px calc(100% / 26));
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.belegung-spur.gesperrt { background: var(--bad-zeile); }
.belegung-kopf .belegung-spur { min-height: 20px; border: none; background: none; }
.belegung-stunde {
  position: absolute; top: 0; font-size: 0.7rem; color: var(--muted);
  transform: translateX(-50%);
}
.belegung-block {
  position: absolute; top: 3px; bottom: 3px;
  background: var(--knopf-accent); color: var(--auf-signal); border-radius: 5px;
  font-size: 0.76rem; padding: 0 0.4rem; overflow: hidden; white-space: nowrap;
  display: flex; align-items: center; text-decoration: none;
}
.belegung-block:hover { background: #7a41ab; color: var(--auf-signal); }
.belegung-warnung {
  /* 18 x 18 Pixel mit 0,72 rem Schrift – aus einem Meter Abstand ein roter
     Punkt ohne Aussage. Ein Warnzeichen, das man nicht lesen kann, ist keins. */
  position: absolute; right: 4px; top: 4px;
  background: var(--knopf-bad); color: var(--auf-signal); border-radius: 50%;
  width: 26px; height: 26px; display: flex; align-items: center;
  justify-content: center; font-size: 0.95rem; font-weight: 700;
}

/* ---------- Monatskalender ---------- */
.kalender { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.kalender-kopf {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted); text-align: center; padding: 0.3rem 0;
}
.kalender-tag {
  min-height: 88px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.35rem 0.4rem; display: flex; flex-direction: column; gap: 2px;
  text-decoration: none; color: var(--text); background: var(--card);
}
.kalender-tag:hover { border-color: var(--accent); color: var(--text); }
.kalender-tag.leer { background: var(--surface-2); border-style: dashed; }
.kalender-tag.heute { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.kalender-tag.gesperrt { background: var(--bad-zeile); }
.kalender-zahl { font-weight: 700; font-size: 0.86rem; }
.kalender-gedecke { font-size: 0.72rem; color: var(--muted); }
.kalender-termin {
  font-size: 0.7rem; background: var(--accent-soft); color: var(--accent);
  border-radius: 4px; padding: 1px 4px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}

/* --- Scan-Station: erkannte Karte und Kamera --------------------------- */
.card.gescannt { border-left: 4px solid var(--accent); }
.gescannt-kopf {
  margin: 0; font-size: .75rem; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent);
}
.gescannt-artikel { margin: .2rem 0 0; font-size: 1.35rem; font-weight: 600; }
.gescannt-mehr { margin: .15rem 0 0; color: var(--muted); }

.kamera { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }
/* Das `label` ist der eigentliche Knopf - das Dateifeld dahinter bleibt
   verborgen, weil es in jedem Browser anders aussieht. */
.kamera-knopf { cursor: pointer; }

/* --- Sucher der Live-Kamera -------------------------------------------- */
.kamerabild { margin-top: .4rem; }
.sucher {
  position: relative;
  max-width: 480px;
  border-radius: 10px;
  overflow: hidden;
  background: #000;
}
.sucher video { display: block; width: 100%; height: auto; }

/* Zielrahmen. Er zeigt, wohin die Karte gehalten werden soll - ohne ihn
   hält man sie zu weit weg, und dann ist der Code zu klein zum Lesen. */
.sucher-rahmen {
  position: absolute; inset: 12% 22%;
  border: 3px solid rgba(255, 255, 255, .85);
  border-radius: 8px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .25);
  pointer-events: none;
}

/* Die Sekunde Schwarz nach einem Treffer. */
.sucher-blende {
  position: absolute; inset: 0;
  background: #000;
  opacity: 0;
  transition: opacity .12s ease-out;
  pointer-events: none;
}
.sucher-blende.zu { opacity: 1; transition: none; }

.sucher-fuss {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  margin-top: .5rem;
}
.kamera-status { color: var(--muted); font-size: .9rem; }
.kamera-status.gut { color: var(--good); font-weight: 600; }
.kamera-status.hinweis { color: var(--warn); }

/* --- Einheit und Hinweis am Mengenfeld --------------------------------- */
.einheit-anzeige {
  font-weight: 600;
  color: var(--accent);
}
.einheit-anzeige:empty { display: none; }
.feld-hinweis {
  font-weight: 400;
  color: var(--muted);
  font-size: .85em;
}

/* Die Gegenprobe unter den Belegzeilen: Positionssumme gegen
   Rechnungsbetrag. Steht bewusst direkt unter der Tabelle und nicht in einer
   eigenen Karte - sie gehoert zu den Zahlen darueber. */
.beleg-summe {
  display: flex; flex-wrap: wrap; gap: 0.25rem 1.1rem;
  margin-top: 0.7rem; padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  background: var(--surface-2); font-size: 0.9rem;
}
.beleg-summe.passt { background: var(--gut-zeile); }
.beleg-summe.passt-nicht { background: var(--bad-zeile); }
.beleg-summe [data-summe-vergleich] { color: var(--muted); }
.beleg-summe.passt [data-summe-vergleich] { color: var(--good); }
.beleg-summe.passt-nicht [data-summe-vergleich] { color: var(--bad); font-weight: 600; }

/* Ein Haekchen mit seiner Beschriftung daneben statt darunter. `label` steht
   im Formularraster auf `display: block`, sonst saesse der Text unter der
   Box und die Zeile waere doppelt so hoch wie noetig. */
label.feld-schalter {
  display: flex; align-items: center; gap: 0.5rem;
  font-weight: 400; margin: 0.75rem 0 0.25rem;
}
label.feld-schalter input[type="checkbox"] { margin: 0; }

/* Erklärtext in einer Tabellenzelle.
   Ohne das Folgende ist er unlesbar, und zwar auf zwei Arten gleichzeitig:
   `th` steht auf `white-space: nowrap`, also wächst die Zelle auf die volle
   Textlänge und schiebt die Wertespalte aus der Karte hinaus - dann fehlen
   auch alle anderen Zahlen der Tabelle. Und `text-transform: uppercase`
   macht aus einem erklärenden Halbsatz ein GESCHRIENES Etwas. */
th .feld-hinweis, td .feld-hinweis {
  display: block;
  white-space: normal;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.4;
  max-width: 28rem;
  margin-top: .2rem;
}

/* Derselbe Kleintext, aber als Warnung: Er steht dort, wo eine Einstellung
   mehr mitnimmt, als sie auf den ersten Blick verspricht. */
.feld-hinweis.warnung { color: var(--warn); }

/* --- Rückfrage zur offenen Bestellung ---------------------------------- */
.card.nachfrage { border-left: 4px solid var(--warn); }
.nachfrage-knoepfe {
  display: flex; flex-wrap: wrap; gap: .6rem; align-items: center;
}
.nachfrage-knoepfe form { margin: 0; }
.hinweis-klein { color: var(--muted); font-size: .9em; margin-top: .6rem; }

/* --- Was die Kamera schon gebucht hat ---------------------------------- */
.sofort { margin: 0; white-space: nowrap; }
.gebucht {
  list-style: none; margin: .6rem 0 0; padding: 0;
  max-height: 15rem; overflow-y: auto;
}
.gebucht li {
  padding: .4rem .6rem; border-left: 3px solid var(--good);
  background: var(--surface-2); border-radius: 4px; margin-bottom: .3rem;
  font-size: .92rem;
}
.gebucht li.schlecht { border-left-color: var(--bad); }
.gebucht-frage {
  margin-top: .4rem; display: flex; flex-wrap: wrap; align-items: center;
  gap: .5rem; color: var(--warn);
}
.gebucht-frage form { margin: 0; }

/* Ausgeblendete Formularfelder.
   Ohne das gewinnt die `display`-Regel des Rasters gegen `hidden`, und ein
   Feld, das verschwinden soll, bleibt stehen. */
.form-grid [hidden] { display: none; }

/* Kalkulation: die Zeile, auf die es ankommt.
   Auf der Rezept-, Produkt- und Veranstaltungsseite steht am Ende einer
   Tabelle voller Zwischenwerte der Preis, um den es eigentlich geht. Ohne
   Hervorhebung muss man ihn suchen. */
tr.hervor th, tr.hervor td {
  background: var(--accent-soft);
  border-top: 2px solid var(--accent);
}
tr.hervor td { font-size: 1.05em; }

/* Aufzählungen mit Erklärtext - Mängel der Kalkulationsgrundlage und die
   Grenzen des Faktors. Enger gesetzt als eine gewöhnliche Liste, weil sie
   unter einer Überschrift und nicht im Fliesstext stehen. */
.maengel, .hinweis-liste {
  margin: .6rem 0 0; padding-left: 1.2rem; color: var(--muted);
}
.maengel li, .hinweis-liste li { margin-bottom: .45rem; line-height: 1.5; }
.maengel li { color: var(--warn); }

/* Rechenweg als Block - eine Formel über mehrere Zeilen, in der die
   Einrückung die Aussage trägt. Als Fliesstext wäre sie nicht zu lesen. */
pre.rechenweg {
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: .8rem 1rem;
  margin: 0 0 1rem;
  overflow-x: auto;
  font-size: .92rem;
  line-height: 1.6;
}

/* Rechenweg zu einer Kalkulation: je Zahl eine Zeile aus Bezeichnung,
   Formel mit eingesetzten Werten und Ergebnis.

   Bewusst ein Raster und keine Tabelle. Eine Formel wie
   „0,8720 € ÷ 6,0748 € × 100" wird lang; in einer Tabellenzelle mit
   `white-space: nowrap` schöbe sie die Ergebnisspalte aus der Karte - der
   Fehler, wegen dem die Kalkulationskarte schon einmal leer aussah. Hier
   darf die mittlere Spalte umbrechen, ohne dass etwas verrutscht. */
/* Eine Zeile, die nur der Vollständigkeit halber dasteht: die
   Zentralabteilung in der Abteilungsauswertung. Sie hat keinen eigenen Umsatz
   und kein Ergebnis - ihre Kosten stehen bei den anderen. Zurückgenommen
   dargestellt, damit das Auge bei den Abteilungen bleibt, um die es geht. */
tr.muted-row td { color: var(--muted); }
tr.muted-row td strong { font-weight: 600; }

/* Farbige Beträge in Tabellen - Beitrag im Plus oder im Minus. */
td .good, th .good { color: var(--good); }
td .bad, th .bad { color: var(--bad); }

/* Mehrere Ankreuzfelder nebeneinander - die Mitarbeiterbereiche einer
   Abteilung. Untereinander gestellt nähmen fünf Häkchen eine halbe Seite ein
   und rissen das Formularraster auseinander. */
.checkreihe {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 1.1rem;
  margin-top: .3rem;
}
.checkreihe .check { margin: 0; white-space: nowrap; }

/* Jede Abteilungszeile als eigenes Formular - eine Trennlinie macht sichtbar,
   wo die eine aufhört und die nächste anfängt. */
.abteilung-zeile { border-top: 1px solid var(--line); padding-top: .9rem; margin-top: .9rem; }
.abteilung-zeile:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }

.rechenweg-huelle { container-type: inline-size; }
.rechenweg {
  margin-top: 1.2rem;
  border-top: 1px solid var(--line);
  padding-top: .9rem;
}
.rechenweg h3 { margin: 0 0 .6rem; font-size: .95rem; }
.rechenweg .schritt {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) 1fr minmax(6rem, auto);
  gap: .2rem .9rem;
  align-items: baseline;
  padding: .35rem 0;
  border-bottom: 1px solid var(--line);
}
.rechenweg .schritt:last-of-type { border-bottom: 0; }
.rechenweg .was { color: var(--muted); font-size: .88rem; }
.rechenweg .formel {
  font-variant-numeric: tabular-nums;
  font-size: .9rem;
  overflow-wrap: anywhere;
}
.rechenweg .ist {
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rechenweg .luecke { color: var(--warn); font-weight: 500; }

/* In einer schmalen Karte untereinander: Drei Spalten auf 380 px sind keine
   drei Spalten, sondern drei umgebrochene Wortsäulen.

   Massgeblich ist die Breite der *Karte*, nicht die des Fensters - dieselbe
   Kalkulation steht auf der Rezeptseite in einer halben Karte und unter dem
   Deckungsbeitrag über die volle Breite. Eine Fensterabfrage träfe beide
   gleich und damit eine von beiden falsch. */
@container (max-width: 34rem) {
  .rechenweg .schritt { grid-template-columns: 1fr auto; }
  .rechenweg .was { grid-column: 1 / -1; }
}

/* Rückfall für Browser ohne Container-Abfragen: dann wenigstens am Handy. */
@media (max-width: 640px) {
  .rechenweg .schritt { grid-template-columns: 1fr auto; }
  .rechenweg .was { grid-column: 1 / -1; }
}

/* ---------- Scan-Station: Rechnung einlesen ---------- */

/* Die Positionstabelle ist eine Maske in Tabellenform: In jeder Zelle steht
   ein Feld, und die Felder brauchen eigene Breiten - ohne sie zieht ein
   Auswahlfeld mit langen Artikelnamen die Tabelle über den Bildschirm hinaus. */
.beleg-zeilen td { vertical-align: top; }
.beleg-zeilen select { max-width: 22rem; }
.beleg-zeilen input.schmal { width: 6rem; text-align: right; }
.beleg-zeilen input[type="date"] { width: 9.5rem; }
.beleg-zeilen .zeile-hinweis {
  display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center;
  margin-top: 0.3rem; font-size: 0.78rem;
}
.beleg-zeilen .unterzeile .form-grid { margin: 0; }

/* ---------- Die Positionstabelle auf einem schmalen Bildschirm ----------

   **Das Problem.** Neun Spalten, davon vier mit Auswahlfeldern, sind auf
   einem Tablet quer schon eng und hochkant unbedienbar: Die Tabelle laeuft
   weit ueber den Rand hinaus, der Kopf verschwindet beim Scrollen, und wer in
   der dritten Zeile den Lagerort setzen will, weiss nach dem Wischen nicht
   mehr, in welcher Zeile er ist. Genau dort wird gebucht - an der Rampe, mit
   dem Tablet in der Hand.

   **Was hier passiert.** Unter 900 Bildpunkten wird aus jeder Zeile eine
   Karte: Die Zellen stehen untereinander, und jede traegt ihre Ueberschrift
   selbst (`data-spalte`, im HTML gesetzt). Es bleibt dieselbe Tabelle und
   dasselbe Formular - nur gefaltet. */
@media (max-width: 900px) {
  .beleg-zeilen thead { position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
  .beleg-zeilen,
  .beleg-zeilen tbody,
  .beleg-zeilen tr,
  .beleg-zeilen td { display: block; width: auto; }
  .beleg-zeilen tbody tr {
    border: 1px solid var(--border); border-radius: 10px;
    margin-bottom: 0.7rem; padding: 0.55rem 0.7rem; background: var(--card);
  }
  /* Die Unterzeile gehoert zur Zeile darueber und darf nicht als eigene
     Karte danebenstehen - sie ist der Zusatz „falls neuer Artikel“. */
  .beleg-zeilen tbody tr.unterzeile {
    margin-top: -0.7rem; border-top: 0;
    border-radius: 0 0 10px 10px; margin-bottom: 0.9rem;
  }
  .beleg-zeilen td { border: 0; padding: 0.3rem 0; text-align: left; }
  .beleg-zeilen td.num { text-align: left; }
  /* Die Ueberschrift der Spalte wandert in die Zelle - ohne sie waere eine
     gefaltete Tabelle eine Reihe von Feldern ohne Bedeutung. */
  .beleg-zeilen td[data-spalte]::before {
    content: attr(data-spalte) ": ";
    display: block; font-size: 0.74rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
    margin-bottom: 0.15rem;
  }
  .beleg-zeilen select,
  .beleg-zeilen input.schmal,
  .beleg-zeilen input[type="date"] { width: 100%; max-width: none; text-align: left; }
  /* Preis und Preisart gehoeren zusammen und duerfen nebeneinander bleiben:
     Zwei Zeilen untereinander waeren die Einladung, die eine zu aendern und
     die andere zu uebersehen. */
  .beleg-zeilen td.preis-zelle { display: flex; flex-wrap: wrap; gap: 0.4rem; }
  .beleg-zeilen td.preis-zelle::before { flex-basis: 100%; }
  .beleg-zeilen td.preis-zelle input.schmal,
  .beleg-zeilen td.preis-zelle select.schmal { width: auto; flex: 1 1 6rem; }

  /* Der Fuss ist die Gegenprobe: „Summe der Zeilen“ gegen „auf dem Beleg
     steht“. Gefaltet stuenden Beschriftung und Betrag untereinander und die
     Gegenueberstellung waere weg - hier bleiben sie in einer Zeile. */
  .beleg-zeilen tfoot { display: block; }
  .beleg-zeilen tfoot tr {
    display: flex; justify-content: space-between; gap: 0.6rem;
    border: 0; margin: 0; padding: 0.35rem 0.7rem; background: transparent;
  }
  .beleg-zeilen tfoot td { padding: 0; }
  /* Die leere Ausgleichsspalte am Ende faellt weg. */
  .beleg-zeilen tfoot td:empty { display: none; }
}

/* ---------- Was dieser Server lesen kann ----------
   „Belege einlesen geht nicht“ war eine Sackgasse: Vier grundverschiedene
   Ursachen sahen alle gleich aus. Die Liste trennt sie und sagt zu jeder
   Zeile, ob sie steht. */
.ocr-liste { list-style: none; margin: 0 0 0.9rem; padding: 0; }
.ocr-liste li {
  position: relative; padding: 0.3rem 0 0.3rem 1.6rem; font-size: 0.92rem;
}
.ocr-liste li::before {
  position: absolute; left: 0; top: 0.3rem; font-weight: 700;
}
.ocr-liste li.gut::before { content: "\2713"; color: var(--good); }
.ocr-liste li.offen::before { content: "\2013"; color: var(--muted); }
.ocr-warum { margin-bottom: 0.9rem; }
.ocr-warum summary { cursor: pointer; color: var(--muted); }
.ocr-warum table { margin-top: 0.7rem; }

/* Der gelesene Text ist Beweisstück, nicht Gestaltung: Er steht so da, wie er
   vom Beleg kam - mit Zeilenumbrüchen und in fester Schrittweite, sonst lässt
   er sich nicht mit dem Papier vergleichen. */
.beleg-text pre {
  max-height: 18rem; overflow: auto; white-space: pre-wrap; word-break: break-word;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.6rem 0.7rem; font-size: 0.78rem; margin: 0.5rem 0 0;
}

.ablauf { margin: 0; padding-left: 1.2rem; color: var(--muted); }
.ablauf li { margin-bottom: 0.35rem; }
.ablauf strong { color: var(--text); }

/* ---------- Positionsfenster (Slide-over) ---------- */

/* Kommt von rechts herein - dort, wo die Zeile steht, aus der es geoeffnet
   wurde. Ein Fenster in der Bildschirmmitte verdeckt genau die Liste, in der
   man sich gerade orientiert. */
dialog.seitenfenster {
  margin: 0 0 0 auto; height: 100%; max-height: 100%; width: min(46rem, 100%);
  border: none; border-left: 1px solid var(--border-strong);
  background: var(--card); color: var(--text); padding: 0;
  box-shadow: -8px 0 24px rgba(0, 0, 0, 0.12);
}
dialog.seitenfenster::backdrop { background: rgba(20, 20, 28, 0.35); }
.seitenfenster-kopf {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem 1.1rem; border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--card); margin: 0;
}
.seitenfenster-inhalt { padding: 1.1rem; overflow-y: auto; max-height: calc(100% - 4rem); }
.seitenfenster-inhalt .table-wrap { margin: 0; }

@media (max-width: 700px) {
  dialog.seitenfenster { width: 100%; border-left: none; }
}

/* Positionen bearbeiten: ein Block je Position, zugeklappt. Zwanzig
   aufgeklappte Formulare untereinander sind keine Maske mehr. */
.positionsform { border-top: 1px solid var(--border); padding: 0.5rem 0; }
.positionsform > summary { cursor: pointer; padding: 0.35rem 0; }
.positionsform > summary:hover { color: var(--accent); }
.positionsform .form-grid { margin-top: 0.6rem; }

/* Die Gegenprobe unter dem MwSt-Feld eines Preisblocks. Sie steht dort, weil
   die MwSt entscheidet, was aus dem Preis wird - und weil unter dem Preisfeld
   selbst kein Platz ist, ohne die Formularspalten zu verschieben. */
[data-preis-gegenprobe]:empty { display: none; }
[data-preis-gegenprobe] { display: block; margin-top: 0.2rem; }
[data-preis-gegenprobe].fehlt { color: var(--bad); font-weight: 600; }

/* ---------- Bestellungen: Positionen unter der Zeile ---------- */

/* Die Positionen stehen als eigene Zeile unter ihrer Bestellung, nicht in
   einer zweiten Tabelle: So bleibt der Zusammenhang sichtbar, ohne dass die
   Spaltenbreiten der Liste durcheinandergeraten. Abgesetzt wird sie über die
   Schriftgrösse und einen Strich an der Seite - eine zweite Rahmenlinie
   liesse die Liste wie zwei Tabellen aussehen. */
.positionszeile > td {
  padding-top: 0; padding-bottom: .55rem;
  border-top: 0;
}
.positionen {
  list-style: none; margin: 0; padding: 0 0 0 .8rem;
  border-left: 2px solid var(--border);
  display: flex; flex-wrap: wrap; gap: .15rem 1.4rem;
  font-size: .84rem;
}
.positionen li { white-space: nowrap; }
.positionen li.erledigt { color: var(--muted); }
.positionen li.gestrichen { color: var(--muted); text-decoration: line-through; }
.positionen-leer { font-size: .84rem; padding-left: .8rem; }

@media (max-width: 640px) {
  .positionen { flex-direction: column; gap: .2rem; }
  .positionen li { white-space: normal; }
}

/* ---------- Break-Even-Diagramm ----------
   Gezeichnet wird serverseitig als SVG (siehe m_breakeven). Die Farben stehen
   hier und nicht im SVG selbst: So sieht das Diagramm aus wie der Rest der
   Oberflaeche, und eine Aenderung an der Palette wirkt auch hier. */

.be-diagramm {
  width: 100%; overflow-x: auto;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: .5rem;
}
.be-diagramm svg { display: block; width: 100%; min-width: 520px; height: auto; }

.be-netz { stroke: var(--border); stroke-width: 1; }
.be-achse { fill: var(--muted); font-size: 12px; }

/* Die Flaechen liegen unter den Linien und muessen sie durchscheinen lassen -
   deshalb Deckkraft statt einer hellen Volltonfarbe: Auf dem Ueberlappungs-
   rand blieben sonst die Kurven unsichtbar, und genau dort passiert es. */
.be-zone { stroke: none; }
.be-zone.deckung { fill: var(--bad); opacity: .16; }
.be-zone.gewinn  { fill: var(--good); opacity: .20; }

.be-fix {
  stroke: var(--muted); stroke-width: 2; stroke-dasharray: 7 5;
}
.be-kosten { fill: none; stroke: var(--bad); stroke-width: 2.5; stroke-linejoin: round; }
.be-umsatz { fill: none; stroke: var(--good); stroke-width: 2.5; stroke-linejoin: round; }

.be-schnitt { stroke: var(--good); stroke-width: 1.5; stroke-dasharray: 3 4; opacity: .8; }
.be-schnittpunkt { fill: var(--card); stroke: var(--good); stroke-width: 3; }

/* Der Ist-Marker ist die Antwort auf "wo bin ich gerade" - er muss auffallen,
   ohne die Kurven zu verdecken. */
.be-heute { stroke: var(--accent); stroke-width: 2.5; }
.be-punkt { stroke: var(--card); stroke-width: 2.5; }
.be-punkt.kosten { fill: var(--bad); }
.be-punkt.umsatz.gewinn { fill: var(--good); }
.be-punkt.umsatz.deckung { fill: var(--warn); }

.be-blase rect { fill: var(--card); stroke-width: 2; }
.be-blase text { fill: var(--muted); font-size: 11px; }
.be-blase text.wert { fill: var(--text); font-size: 13px; font-weight: 600; }
.be-blase.gewinn rect { stroke: var(--good); }
.be-blase.deckung rect { stroke: var(--warn); }
.be-marke { fill: var(--good); font-size: 12px; font-weight: 600; }

/* Ein durchsichtiges Feld je Tag traegt die Sprechblase des Browsers. Beim
   Ueberfahren wird es leicht sichtbar - sonst raet man, welchen Tag man hat. */
.be-tag { fill: transparent; }
.be-tag:hover { fill: var(--accent); opacity: .08; }

.be-legende {
  list-style: none; margin: .7rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .3rem 1.3rem; font-size: .84rem; color: var(--muted);
}
.be-legende li { display: flex; align-items: center; gap: .4rem; }
.be-legende li::before {
  content: ""; width: 16px; height: 3px; border-radius: 2px; background: var(--muted);
}
.be-legende li.umsatz::before { background: var(--good); }
.be-legende li.kosten::before { background: var(--bad); }
.be-legende li.fix::before { background: repeating-linear-gradient(90deg, var(--muted) 0 5px, transparent 5px 9px); }
.be-legende li.deckung::before { height: 11px; background: var(--bad); opacity: .3; }
.be-legende li.gewinn::before { height: 11px; background: var(--good); opacity: .35; }

/* Die Zeitraumumschaltung: Monat, Quartal, Jahr - und Blaettern. */
.be-steuerung { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-bottom: 1rem; }
.be-steuerung .be-perioden { display: flex; gap: .25rem; }
.be-steuerung .be-titel { font-weight: 600; margin: 0 .3rem; }

/* ---------- Belegzeilen: Preis, Preisart und Zeilensumme ----------
   Die Preiszelle traegt drei Dinge, die zusammengehoeren: den Preis, seine
   Art (netto/brutto) und die Gegenprobe. Auseinandergezogen auf drei Spalten
   waere es die Einladung, das eine zu aendern und das andere zu uebersehen -
   und genau daran gehen Positionssumme und Rechnungsbetrag auseinander. */

.beleg-zeilen select.schmal { width: 6.2rem; }
.beleg-zeilen [data-zeile-gegenprobe] { display: block; white-space: nowrap; }
.beleg-zeilen [data-zeile-summe] { white-space: nowrap; }
.beleg-zeilen [data-zeile-steuer] { display: block; white-space: nowrap; }

/* Die Aufteilung je Steuersatz im Summenkasten. Sie steht auf einer eigenen
   Zeile: Auf einem Beleg mit 7 % und 19 % sind das zwei Angaben, und
   nebeneinandergedraengt liest sie niemand. */
.beleg-summe .beleg-saetze { flex-basis: 100%; color: var(--muted); font-size: .84rem; }

/* Die Herkunft eines vorbelegten Preises - "Aus dem Infosatz von Metro". */
[data-preis-herkunft] { color: var(--muted); }
[data-preis-herkunft].warnt { color: var(--warn); font-weight: 500; }

/* ---------- Zurückgenommene Zeilen ----------
   Storniert heisst: steht noch da, zählt nicht mehr. Beides muss man sehen –
   deshalb bleibt die Zeile lesbar und wird nur zurückgenommen, nicht versteckt.
   Der Durchstrich allein reicht nicht (er ist auf kleinen Schriften kaum zu
   erkennen), das Abzeichen in der Zeile sagt es im Klartext dazu. */
.zeile-storniert > td { opacity: 0.55; }
.zeile-storniert > td:first-child,
.zeile-storniert .num { text-decoration: line-through; }
.zeile-storniert .badge { opacity: 1; text-decoration: none; }

/* Der Weg zurück, direkt in der Erfolgsmeldung. Er soll auffallen, ohne die
   Meldung zu überschreien – deshalb eine eigene Zeile statt Fettdruck. */
.flash-undo {
  display: inline-block; margin-top: 0.35rem;
  font-weight: 600; text-decoration: underline;
}

/* ---------- Belegmaske: Abzugszeilen und die Gegenprobe ----------
   Eine Abzugszeile (Storno, Rabatt, Gutschein) mindert den Betrag und ist kein
   Verkauf. Sie faellt deshalb aus der Reihe, statt sich darin zu verstecken –
   frueher wurde sie kommentarlos verworfen, und der gebuchte Umsatz war zu hoch. */
.zeile-abzug > td { background: var(--warn-zeile); }

.zeile-summe > td {
  border-top: 1px solid var(--border-strong, #b4c0c2);
  font-size: 0.9rem; padding-top: 0.55rem;
}
.zeile-summe.stimmt > td { color: #2a6b4e; }
.zeile-summe.weicht-ab > td { color: #9b2d23; font-weight: 600; }

/* Die Zahl der offenen Punkte im Menü. Sie ist eine Aufforderung, keine
   Verzierung – deshalb kräftig und rund, aber klein genug, um den Eintrag
   nicht zu sprengen. */
.nav-zahl {
  font-style: normal; font-weight: 700; font-size: 0.72rem;
  background: var(--knopf-bad); color: var(--auf-signal);
  border-radius: 999px; padding: 0.05em 0.45em; margin-left: 0.35rem;
}

/* ---------- Prüfliste ---------- */
.pruef-punkt { border-left: 4px solid var(--border-strong, #b4c0c2); }
.pruef-punkt.pruef-bad { border-left-color: var(--bad); }
.pruef-punkt.pruef-warn { border-left-color: var(--warn); }
.pruef-beispiele { margin: 0.6rem 0 0; padding-left: 1.15rem; }
.pruef-beispiele li { margin-bottom: 0.25rem; font-size: 0.92rem; }

/* Ein besetzter Tisch im Belegungsplan. Farbe allein reicht nicht – der Punkt
   vor dem Namen sagt dasselbe noch einmal, für alle Augen und aus zwei Metern. */
.belegung-block.ist-da {
  background: var(--gut-bg);
  border-color: var(--good);
  font-weight: 600;
}

/* ==========================================================================
   Wandmodus – die Oberfläche für ein fest montiertes Tablet
   ==========================================================================
   Zwei Meter Abstand, gedimmtes Licht, feuchte oder fettige Finger. Dafür ist
   die normale Ansicht nicht gebaut: 32 Pixel hohe Knöpfe trifft man so nicht,
   und 9 Pixel Schrift liest man nicht. Der Modus hängt am Gerät und schaltet
   sich über den Knopf unten in der Leiste.

   Bewusst als eigener Zweig und nicht als zweites Stylesheet: Was hier steht,
   sind Abweichungen von der einen Gestaltung – und die bleibt die Grundlage,
   damit beides nicht auseinanderläuft. */

[data-wandmodus="1"] {
  --primary: var(--d-primary);
  --primary-dark: var(--d-primary-dark);
  --accent: var(--d-accent);
  --accent-soft: var(--d-accent-soft);
  --bg: var(--d-bg);
  --card: var(--d-card);
  --border: var(--d-border);
  --border-strong: var(--d-border-strong);
  --text: var(--d-text);
  --muted: var(--d-muted);
  --good: var(--d-good);
  --warn: var(--d-warn);
  --bad: var(--d-bad);
  --shadow: var(--d-shadow);
  --shadow-lift: var(--d-shadow-lift);

  --field: var(--d-field);
  --surface-2: var(--d-surface-2);
  --surface-3: var(--d-surface-3);
  --chip-bg: var(--d-chip-bg);
  --raster: var(--d-raster);
  --zeile-hover: var(--d-zeile-hover);

  --gut-bg: var(--d-gut-bg);   --gut-rand: var(--d-gut-rand);   --gut-text: var(--d-gut-text);
  --warn-bg: var(--d-warn-bg);   --warn-rand: var(--d-warn-rand); --warn-text: var(--d-warn-text);
  --bad-bg: var(--d-bad-bg);   --bad-rand: var(--d-bad-rand);   --bad-text: var(--d-bad-text);
  --gut-zeile: var(--d-gut-zeile);
  --warn-zeile: var(--d-warn-zeile);
  --bad-zeile: var(--d-bad-zeile);

  --auf-primary: var(--d-auf-primary);
  --knopf-accent: var(--d-knopf-accent);
  --knopf-bad: var(--d-knopf-bad);
  --auf-signal: var(--d-auf-signal);

  --kopf-bg: var(--d-kopf-bg);
  --zebra: var(--d-zebra);
  --logo-filter: var(--d-logo-filter);

  color-scheme: dark;
}
[data-wandmodus="1"] body,
body[data-wandmodus="1"] { background: var(--bg); color: var(--text); font-size: 19px; }

body[data-wandmodus="1"] .card,
body[data-wandmodus="1"] .sidebar { background: var(--card); border-color: var(--border); }

body[data-wandmodus="1"] .btn { min-height: 52px; font-size: 1.05rem; padding: 0.7rem 1.2rem; }
body[data-wandmodus="1"] .btn.small { min-height: 46px; font-size: 0.98rem; padding: 0.55rem 1rem; }
body[data-wandmodus="1"] th,
body[data-wandmodus="1"] td { padding: 0.85rem 0.7rem; font-size: 1rem; }
body[data-wandmodus="1"] input,
body[data-wandmodus="1"] select { min-height: 48px; font-size: 1rem; }
body[data-wandmodus="1"] .kbb-chip { width: 4.4rem; min-height: 4.4rem; }
body[data-wandmodus="1"] .kbb-chip-state,
body[data-wandmodus="1"] .kb-label { font-size: 0.8rem; }
body[data-wandmodus="1"] .belegung-warnung { width: 26px; height: 26px; font-size: 0.9rem; }

/* ---------- Allergene: der dritte Zustand ----------
   „nicht geprüft“ ist keine Warnung vor einem Allergen, sondern vor einer
   fehlenden Angabe – deshalb gestrichelt statt gefüllt. „keine“ ist eine
   Zusage und darf ruhig grün sein. Beide tragen Text und nicht nur Farbe. */
.allergen-offen {
  display: inline-block; font-size: 0.72rem; font-weight: 600;
  padding: 0.1em 0.45em; border-radius: 3px;
  border: 1px dashed var(--warn, #a05d06); color: var(--warn, #a05d06);
}
.allergen-keine {
  display: inline-block; font-size: 0.72rem; font-weight: 600;
  padding: 0.1em 0.45em; border-radius: 3px;
  background: var(--gut-bg); color: var(--gut-text);
}

/* ---------- Küchenzettel: Gang vor Posten ----------
   Der Gang trägt die Gliederung des Abends, der Posten die Arbeitsteilung
   darin. Deshalb steht der Gang deutlich über dem Posten und nicht daneben. */
.gang-kopf {
  margin: 1.4rem 0 0.2rem; padding-bottom: 0.25rem;
  border-bottom: 2px solid var(--border-strong, #b4c0c2);
  font-size: 1.1rem;
}
.gang-kopf:first-of-type { margin-top: 0.4rem; }
.posten-kopf {
  margin: 0.75rem 0 0.15rem; font-size: 0.88rem;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted, #667477);
}

/* ==========================================================================
   Dunkler Bildschirm
   ==========================================================================
   Zwei Wege dorthin, und sie sind verschieden gemeint:

   – Der **Wandmodus** weiter oben ist eine Entscheidung fuer ein Geraet: Das
     Tablet an der Wand ist immer dunkel und immer gross, egal was das
     Betriebssystem meint.

   – Was hier steht, folgt der Einstellung des Geraets. Wer sein Tablet oder
     seinen Rechner abends auf dunkel stellt, bekommt KMS ebenfalls dunkel –
     ohne dafuer irgendwo einen Schalter suchen zu muessen.

   Umgesetzt ueber die Farbwerte und nicht ueber eigene Regeln je Baustein:
   So bleibt die eine Gestaltung die Grundlage, und beide Ansichten koennen
   nicht auseinanderlaufen. */

@media (prefers-color-scheme: dark) {
  :root {
    --primary: var(--d-primary);
    --primary-dark: var(--d-primary-dark);
    --accent: var(--d-accent);
    --accent-soft: var(--d-accent-soft);
    --bg: var(--d-bg);
    --card: var(--d-card);
    --border: var(--d-border);
    --border-strong: var(--d-border-strong);
    --text: var(--d-text);
    --muted: var(--d-muted);
    --good: var(--d-good);
    --warn: var(--d-warn);
    --bad: var(--d-bad);
    --shadow: var(--d-shadow);
    --shadow-lift: var(--d-shadow-lift);

    --field: var(--d-field);
    --surface-2: var(--d-surface-2);
    --surface-3: var(--d-surface-3);
    --chip-bg: var(--d-chip-bg);
    --raster: var(--d-raster);
    --zeile-hover: var(--d-zeile-hover);

    --gut-bg: var(--d-gut-bg);     --gut-rand: var(--d-gut-rand);   --gut-text: var(--d-gut-text);
    --warn-bg: var(--d-warn-bg);   --warn-rand: var(--d-warn-rand); --warn-text: var(--d-warn-text);
    --bad-bg: var(--d-bad-bg);     --bad-rand: var(--d-bad-rand);   --bad-text: var(--d-bad-text);
    --gut-zeile: var(--d-gut-zeile);
    --warn-zeile: var(--d-warn-zeile);
    --bad-zeile: var(--d-bad-zeile);

    --auf-primary: var(--d-auf-primary);
    --knopf-accent: var(--d-knopf-accent);
    --knopf-bad: var(--d-knopf-bad);
    --auf-signal: var(--d-auf-signal);

    --kopf-bg: var(--d-kopf-bg);
    --zebra: var(--d-zebra);
    --logo-filter: var(--d-logo-filter);

    color-scheme: dark;
  }

}

/* ==========================================================================
   Bearbeiten in einer Tabellenzeile
   ==========================================================================
   Ein Klick auf „Bearbeiten“ oeffnete das Formular INNERHALB der Zeile, und
   alles darunter rutschte nach unten. Auf einem Tablet verliert man beim
   Scrollen genau die Zeile, die man bearbeiten wollte – und beim Zuklappen
   springt die Seite an eine andere Stelle.

   Geloest ueber die Darstellung und nicht durch Umbau von zwoelf Masken: Das
   Formular bleibt, wo es im Text steht (ohne Skript klappt es weiterhin auf),
   wird im geoeffneten Zustand aber als Ebene ueber der Liste gezeigt. Die
   Liste darunter bleibt stehen, wo sie war.

   **Die Ebene ist das ganze `details` – und ihr Inhalt eine Spalte.**

   Hier stand einmal etwas anderes: Nicht das `details` wurde zur Ebene,
   sondern *jedes seiner Kinder ausser dem `summary`*, jedes an dieselbe
   feste Stelle in der Bildschirmmitte. Das ging genau so lange gut, wie eine
   Maske genau ein Kind hatte – ein Formular. Sobald daneben noch ein
   Hinweissatz stand, lagen **beide** uebereinander, und der Hinweis – im
   Text der letzte – deckte das Formular zu. Sichtbar war ein Kasten mit
   einem Satz darin, darunter unerreichbar die Felder.

   Genau das war beim Beleg einlesen zu sehen: „Angaben fuer einen neuen
   Artikel“ zeigte den Erklaersatz und verdeckte Bezeichnung, Art und
   Kanban-Zustand. Anfassen liess sich nichts mehr.

   Betroffen war nicht eine Maske, sondern jede mit mehr als einem Kind –
   Fehlmengen, Eingangsrechnung, Bestellposition, die Loeschvormerkung aus
   `m_vormerken()`. Deshalb ist die Regel hier geaendert und nicht in acht
   Masken: Eine Darstellungsregel, die vom Aufbau des Inhalts abhaengt, ist
   eine Falle fuer jede Maske, die spaeter dazukommt.

   Jetzt ist das `details` selbst der bildschirmfuellende, verdunkelte
   Hintergrund, und seine Kinder stehen darin als **Spalte** untereinander:
   das `summary` als Kopf, danach so viele Abschnitte, wie die Maske
   mitbringt. Zusammen ergeben sie einen durchgehenden Kasten – aber keiner
   liegt mehr auf dem anderen, und es ist gleichgueltig, wie viele es sind.

   **Der Verdunkler ist der Hintergrund des `details` und kein
   Pseudoelement.** Ein Pseudoelement ist ein Kind: Es malt ueber den
   Hintergrund seines eigenen Elements, faerbt also die Ebene mit ein und
   faengt ausserdem die Klicks auf deren Rand ab. Als Hintergrund liegt es
   dort, wo es hingehoert – dahinter.

   **Zentriert ueber `safe center`.** Ein gewoehnliches
   `justify-content: center` schiebt Inhalt, der hoeher ist als der
   Bildschirm, nach BEIDEN Seiten hinaus – der obere Rand waere dann nicht
   mehr erreichbar, auch nicht durch Rollen. `safe` heisst: zentrieren,
   solange Platz ist, und sonst oben anfangen. */

td details[open],
.row-actions details[open] {
  position: fixed; inset: 0; z-index: 41;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; justify-content: safe center;
  padding: 1rem; overflow: auto;
  background: rgba(15, 20, 22, 0.45);
  text-align: left;
}

/* Der Auslöser wird zum Kopf der Ebene und sagt, wie man wieder herauskommt.
   Der dritte Selektor ist kein Zufall: Die Listenmasken geben ihrem `summary`
   ein Pillenaussehen mit hoeherer Spezifitaet, und ohne ihn stuende im Kopf
   eine Pille statt einer Ueberschrift. */
td details[open] > summary,
.row-actions details[open] > summary,
.liste tbody tr.unterzeile details[open] > summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  width: min(680px, calc(100vw - 2rem));
  margin: 0;
  padding: 1rem 1.25rem 0.75rem;
  background: var(--card); color: var(--text);
  border: 1px solid var(--border-strong); border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  font-size: 1rem; font-weight: 700;
}

/* **Diese Zeile braucht noch Angaben.** Der Auslöser sagt es, statt sich von
   selbst aufzuklappen: Auf einem Beleg, dessen Artikel noch keiner kennt,
   waeren das zwoelf Ebenen gleichzeitig. */
.liste tbody tr.unterzeile summary.noetig {
  color: var(--warn); border-color: var(--warn); font-weight: 700;
}
.liste tbody tr.unterzeile summary.noetig::before {
  content: "! "; font-weight: 700;
}
/* In der geoeffneten Ebene ist die Aufforderung erledigt – dort steht sie als
   Ueberschrift und braucht kein Ausrufezeichen mehr. */
.liste tbody tr.unterzeile details[open] > summary.noetig::before { content: none; }

/* Ein `summary` im Knopfaussehen traegt seine eigene Beschriftung. */
td details[open] > summary:not(.btn)::after,
.row-actions details[open] > summary:not(.btn)::after,
.liste tbody tr.unterzeile details[open] > summary:not(.btn)::after {
  content: "schliessen";
  font-size: 0.78rem; font-weight: 600; color: var(--muted); white-space: nowrap;
}

/* Ein `summary` senkt sich im Knopfaussehen beim Druecken um einen Punkt –
   in einem Kopf, der die halbe Ebene breit ist, sieht das aus wie ein
   Wackler. */
td details[open] > summary:active,
.row-actions details[open] > summary:active { transform: none; }

/* Die Abschnitte darunter: gleiche Breite, gemeinsamer Rand, kein eigener
   Abstand nach aussen – zusammen sind sie EIN Kasten. */
td details[open] > *:not(summary),
.row-actions details[open] > *:not(summary) {
  width: min(680px, calc(100vw - 2rem));
  margin: 0;
  padding: 0 1.25rem;
  background: var(--card); color: var(--text);
  border: 1px solid var(--border-strong); border-top: 0;
}
td details[open] > summary + *,
.row-actions details[open] > summary + * { padding-top: 0.9rem; }
td details[open] > :last-child,
.row-actions details[open] > :last-child {
  padding-bottom: 1.15rem;
  border-radius: 0 0 var(--radius) var(--radius);
}

@media (max-width: 700px) {
  td details[open],
  .row-actions details[open] { padding: 0.5rem; }
  td details[open] > summary,
  .row-actions details[open] > summary,
  .liste tbody tr.unterzeile details[open] > summary { padding: 0.8rem 0.9rem 0.6rem; }
  td details[open] > *:not(summary),
  .row-actions details[open] > *:not(summary) { padding: 0 0.9rem; }
}

/* Suche über alle Bereiche, ganz oben in der Leiste. */
.nav-suche { padding: 0 1.25rem 0.25rem; }
.nav-suche input {
  width: 100%; min-height: 40px; margin: 0;
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); padding: 0.45rem 0.7rem; font-size: 0.92rem;
}
.nav-hilfe { font-size: 0.88rem; }
.such-treffer { list-style: none; padding: 0; margin: 0; }
.such-treffer li {
  padding: 0.55rem 0; border-bottom: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: 0.2rem 0.8rem; align-items: baseline;
}
.such-treffer li:last-child { border-bottom: none; }
.such-treffer a { font-weight: 600; }

/* Hilfeseite: Listen mit Luft, damit man den Weg findet statt ihn zu suchen. */
.hilfe-liste { padding-left: 1.15rem; }
.hilfe-liste li { margin-bottom: 0.55rem; }

/* Blätterleiste unter einer langen Liste. */
.blaettern {
  display: flex; align-items: center; justify-content: center;
  gap: 0.9rem; flex-wrap: wrap;
  padding: 0.9rem 0 0.2rem; margin-top: 0.6rem;
  border-top: 1px solid var(--border);
}
.blaettern-stand { font-size: 0.88rem; color: var(--muted); }
.blaettern [aria-disabled="true"] { opacity: 0.4; pointer-events: none; }

/* ---------------------------------------------------------------------------
   Kachelfelder: antippen statt auswählen

   Gebaut für einen Daumen an einem Wandgerät, nicht für einen Mauszeiger.
   Deshalb die Masse: Eine Kachel ist mindestens 96 Pixel hoch – das ist die
   Grösse, die man im Vorbeigehen trifft, ohne hinzusehen. Der Korb hängt sich
   unten fest, sobald etwas darin liegt: Wer die zwanzigste Kachel drückt, soll
   nicht scrollen müssen, um abzuschicken.
   ------------------------------------------------------------------------- */
.kachelfeld { margin: 0.4rem 0 0.8rem; }

.kachel-suche { margin-bottom: 0.9rem; }
.kachel-suche input {
  width: 100%; max-width: 26rem; min-height: 46px; font-size: 1rem;
}

.kachel-gruppe { margin-bottom: 1.1rem; }
.kachel-gruppe > h3 {
  font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin: 0 0 0.45rem;
}

.kacheln {
  display: grid; gap: 0.5rem;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
}

.kachel-huelle { position: relative; }
.kachel-huelle[hidden] { display: none; }

.kachel {
  width: 100%; min-height: 96px;
  display: flex; flex-direction: column; justify-content: center; gap: 0.15rem;
  padding: 0.6rem 0.65rem; text-align: left;
  background: var(--field); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  cursor: pointer; font: inherit;
  /* Ein Doppeltipp darf nicht als Zoom durchgehen: Am Tablet ist genau das
     die Geste, mit der hier „zwei“ gemeint ist. */
  touch-action: manipulation; -webkit-user-select: none; user-select: none;
  transition: background 0.08s, border-color 0.08s, transform 0.08s;
}
.kachel:hover { border-color: var(--accent); }
.kachel:active { transform: scale(0.97); }
.kachel:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.kachel-name {
  font-weight: 600; line-height: 1.2;
  /* Lange Namen brechen, statt die Kachel zu sprengen – aber höchstens auf
     drei Zeilen, sonst wird das Raster ungleich hoch. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.kachel-zusatz { font-size: 0.85rem; color: var(--muted); }
.kachel-hinweis { font-size: 0.75rem; color: var(--muted); }

/* Was ausgewählt ist, ist auch ohne Farbe zu erkennen: kräftiger Rand,
   eingefärbte Fläche und die Zahl in der Ecke. Farbe allein trägt hier
   nichts – am Pass steht das Gerät oft im Gegenlicht. */
.kachel.gewaehlt {
  background: var(--accent-soft); border-color: var(--accent); border-width: 2px;
  padding: calc(0.6rem - 1px) calc(0.65rem - 1px);
}

.kachel-zahl {
  position: absolute; top: -0.5rem; right: -0.5rem;
  min-width: 2rem; height: 2rem; padding: 0 0.35rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--knopf-accent); color: #fff;
  font-weight: 700; font-size: 0.95rem;
  border-radius: 999px; box-shadow: var(--shadow);
}
.kachel-zahl[hidden] { display: none; }

/* Der Weg zurück, genauso gross wie der Weg hin. Unten links, damit er nicht
   unter dem Daumen liegt, der gerade die Kachel drückt. */
.kachel-minus {
  position: absolute; left: -0.4rem; bottom: -0.4rem;
  width: 2.1rem; height: 2.1rem; padding: 0; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  background: var(--card); color: var(--text);
  border: 2px solid var(--border-strong); border-radius: 999px;
  font-size: 1.2rem; font-weight: 700; cursor: pointer;
  box-shadow: var(--shadow); touch-action: manipulation;
}
.kachel-minus:hover { border-color: var(--bad); color: var(--bad); }
.kachel-minus[hidden] { display: none; }

/* ---- Der Korb ----
   Er klebt unten am Fenster, solange etwas darin liegt. Ohne das müsste man
   nach jeder Auswahl ans Seitenende – mit einer Hand, mitten im Service. */
.kachel-korb {
  position: sticky; bottom: 0; z-index: 20;
  margin-top: 0.8rem; padding: 0.7rem 0.8rem;
  background: var(--card); border: 2px solid var(--accent);
  border-radius: var(--radius); box-shadow: var(--shadow-lift);
}
.kachel-korb[hidden] { display: none; }

.korb-zeilen {
  display: flex; flex-wrap: wrap; gap: 0.35rem 0.5rem; margin-bottom: 0.6rem;
  max-height: 6.5rem; overflow-y: auto;
}
.korb-zeile {
  padding: 0.2rem 0.55rem; border-radius: 999px;
  background: var(--chip-bg); font-size: 0.88rem; white-space: nowrap;
}
.korb-fuss { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.korb-fuss .btn.gross { min-height: 54px; font-size: 1.05rem; flex: 1 1 14rem; }
.korb-hinweis { margin: 0.5rem 0 0; font-size: 0.8rem; color: var(--muted); }

/* Im Wandmodus wird alles eine Nummer grösser: zwei Meter Abstand, feuchte
   Finger, und der Bildschirm hängt fest. */
body[data-wandmodus="1"] .kacheln {
  grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
}
body[data-wandmodus="1"] .kachel { min-height: 118px; font-size: 1.02rem; }
body[data-wandmodus="1"] .kachel-zahl { min-width: 2.4rem; height: 2.4rem; font-size: 1.05rem; }
body[data-wandmodus="1"] .kachel-minus { width: 2.6rem; height: 2.6rem; font-size: 1.4rem; }
body[data-wandmodus="1"] .korb-fuss .btn.gross { min-height: 62px; font-size: 1.15rem; }

/* Der ausführliche Weg unter dem Kachelfeld. Er ist da für den Betrag, der
   auf keine Kachel passt – eine halbe Portion, ein Sonderpreis – und für den
   Fall, dass kein JavaScript läuft. Zugeklappt, damit er den schnellen Weg
   nicht zustellt. */
.langer-weg { margin-top: 0.9rem; border-top: 1px solid var(--border); padding-top: 0.7rem; }
.langer-weg > summary {
  cursor: pointer; font-size: 0.9rem; color: var(--muted); padding: 0.3rem 0;
}
.langer-weg > summary:hover { color: var(--text); }

/* Ein Artikel, der nirgends mehr liegt, bleibt antippbar – aber sichtbar
   anders: Angefordert werden kann er, geholt wird nichts. Das Lager sieht an
   der Anfrage, dass zu bestellen und nicht zu laufen ist. */
.kachel.kachel-leer { border-style: dashed; }
.kachel.kachel-leer .kachel-hinweis { color: var(--bad); }

/* ---------- Reiter in beschrifteten Gruppen ----------
   Sechs gleich aussehende Reiter nebeneinander sagen nicht, dass die ersten
   drei ein Handgriff am Regal sind und die letzten drei etwas anderes. Die
   Überschrift kostet eine Zeile und beantwortet die Frage vorher. */
.reiter-gruppen {
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.8rem; margin-bottom: 1.1rem;
}
.reiter-gruppe { display: flex; flex-direction: column; gap: 0.3rem; }
.reiter-titel {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted);
}
.reiter-gruppe .section-tabs { margin-bottom: 0; }

/* Was die gewählte Bedienart tut – über dem Feld, in das gescannt wird, und
   nicht nur im Handbuch. */
.modus-hinweis {
  margin: -0.4rem 0 1.1rem; padding: 0.6rem 0.8rem;
  background: var(--surface-2); border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* ---------- Tagesablauf: wann, wer, und die Handgriffe ----------
   Regel und Begründung sagen, warum ein Weg der richtige ist. Wer neu ist,
   hat zuerst eine andere Frage: Was drücke ich jetzt? Die nummerierte Liste
   ist die Antwort darauf und steht deshalb zwischen beiden – nach der Regel,
   vor der Begründung. */
.wf-wer {
  display: flex; flex-wrap: wrap; gap: 0.3rem 1.4rem;
  margin: 0 0 0.7rem; font-size: 0.9rem; color: var(--muted);
}
.wf-marke {
  display: inline-block; padding: 0.05em 0.45em; margin-right: 0.25rem;
  border-radius: 3px; background: var(--chip-bg); color: var(--text);
  font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
}

.wf-anleitung {
  margin: 0.9rem 0; padding: 0.8rem 1rem 0.8rem 0.6rem;
  background: var(--surface-2); border-radius: var(--radius-sm);
}
.wf-anleitung > h3 {
  margin: 0 0 0.5rem 0.55rem; font-size: 0.78rem;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
}
.wf-anleitung ol { margin: 0; padding-left: 1.6rem; }
.wf-anleitung li { margin-bottom: 0.5rem; line-height: 1.5; }
.wf-anleitung li:last-child { margin-bottom: 0; }

/* ---------- Kassieren am Bon ----------
   Steht unter dem Bon und nicht beim Bonieren: Wenn der Gast bestellt, weiss
   niemand, ob er bar oder mit Karte zahlt. Der Streifen erscheint nur, wo
   wirklich etwas offen ist. */
.bon-kasse {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;
  padding: 0.6rem 0.8rem; border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.bon-kasse { flex-direction: column; align-items: stretch; }
.kasse-kopf { display: flex; flex-wrap: wrap; gap: 0.3rem 1rem; align-items: baseline; }
.bon-offen { font-size: 0.9rem; color: var(--muted); margin-right: auto; }
.bon-offen strong { color: var(--text); font-size: 1.05rem; }
.bon-proKopf { font-size: 0.85rem; color: var(--muted); }
.bon-proKopf strong { color: var(--text); }
.kasse-fuss { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.kasse-fuss select { flex: 1 1 9rem; min-width: 0; }

/* Getrennt zahlen. Zugeklappt, weil „alles zusammen“ der Normalfall ist –
   dafür soll niemand erst Haken setzen müssen. */
.kasse-teilen > summary {
  cursor: pointer; font-size: 0.88rem; color: var(--accent); padding: 0.35rem 0;
}
.kasse-zeilen { list-style: none; margin: 0.3rem 0 0.5rem; padding: 0; }
.kasse-zeilen li { border-bottom: 1px solid var(--border); }
.kasse-zeilen li:last-child { border-bottom: none; }
.kasse-zeilen label {
  display: flex; align-items: center; gap: 0.5rem;
  /* Fingergross: Am Tisch wird das im Stehen angekreuzt. */
  padding: 0.55rem 0.2rem; cursor: pointer; font-size: 0.92rem;
}
.kasse-zeilen input[type="checkbox"] { width: 1.35rem; height: 1.35rem; flex: none; }
.kz-menge { color: var(--muted); flex: none; }
.kz-name { flex: 1 1 auto; min-width: 0; }
.kz-betrag { flex: none; font-variant-numeric: tabular-nums; }

/* Der Zustand, den es vorher nicht gab: gekocht, aber nicht bezahlt. */
.bon-wartet {
  margin: 0; padding: 0.45rem 0.8rem;
  background: var(--warn-bg); color: var(--warn-text);
  border-bottom: 1px solid var(--warn-rand); font-size: 0.85rem;
}
.bon-gaeste {
  font-size: 0.8rem; font-weight: 600; color: var(--muted);
  padding: 0.05em 0.4em; border-radius: 3px; background: var(--chip-bg);
  white-space: nowrap;
}

body[data-wandmodus="1"] .kasse-zeilen label { padding: 0.75rem 0.2rem; font-size: 1rem; }
body[data-wandmodus="1"] .kasse-zeilen input[type="checkbox"] { width: 1.6rem; height: 1.6rem; }

/* Welche Tische schon einen offenen Bon haben – damit der Service sieht, wohin
   er bucht, ohne auf die Tafel zu wechseln. */
.offene-tische { display: flex; flex-wrap: wrap; gap: 0.3rem 0.5rem; align-items: baseline; }
.tisch-marke {
  padding: 0.15rem 0.5rem; border-radius: 999px;
  background: var(--chip-bg); color: var(--text); font-size: 0.85rem; white-space: nowrap;
}

/* ---------- Getrennt kassieren: Teilmenge und Zwischensumme ----------
   Am Tisch warten drei Leute, während der Kellner ankreuzt. Was er dabei
   nicht tun soll, ist addieren – deshalb rechnet die Seite mit. */
.kz-zeile { display: flex; align-items: center; gap: 0.5rem; }

.kz-teilen {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0 0.2rem 0.55rem 2.4rem;   /* auf Höhe des Zeilentextes eingerückt */
}
.kz-teilen[hidden] { display: none; }
.kz-teilen-text { font-size: 0.82rem; color: var(--muted); }

/* Fingergrosse Schrittknöpfe: Ein Zahlenfeld am Tablet zu treffen ist
   Fummelei, zwei Knöpfe daneben sind der Weg, der benutzt wird. */
.kz-schritt {
  width: 2.2rem; height: 2.2rem; flex: none; padding: 0; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  background: var(--field); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  font-size: 1.1rem; font-weight: 700; cursor: pointer; touch-action: manipulation;
}
.kz-schritt:hover { border-color: var(--accent); color: var(--accent); }
.kz-teilen input[type="number"] {
  width: 3.4rem; flex: none; text-align: center;
  font-variant-numeric: tabular-nums;
}
.kz-teilsumme {
  font-size: 0.85rem; color: var(--text); font-variant-numeric: tabular-nums;
}

.kasse-summe {
  display: flex; flex-wrap: wrap; gap: 0.3rem 1.2rem; justify-content: space-between;
  margin: 0.2rem 0 0.6rem; padding: 0.5rem 0.7rem;
  background: var(--accent-soft); border-radius: var(--radius-sm);
  font-size: 0.92rem;
}
.kasse-summe[hidden] { display: none; }
.kasse-summe strong { font-variant-numeric: tabular-nums; }

body[data-wandmodus="1"] .kz-schritt { width: 2.7rem; height: 2.7rem; font-size: 1.3rem; }
body[data-wandmodus="1"] .kz-teilen input[type="number"] { width: 4rem; min-height: 2.7rem; }

/* ---------- Kanban-Kartendruck: Auswahl ----------
   Angekreuzt wird in der Zeile, gedruckt unten. Der Haken ist fingergross:
   Die Kartenliste wird am Regal durchgegangen, nicht am Schreibtisch. */
.kartenwahl-alle { display: inline-flex; align-items: center; }
td.mittig, th.mittig { text-align: center; width: 2.6rem; }
td.mittig input[type="checkbox"],
th.mittig input[type="checkbox"] { width: 1.3rem; height: 1.3rem; }
.kartendruck-fuss { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.9rem; }
.kartendruck-fuss [hidden] { display: none; }

/* Nur für Vorleseprogramme – sichtbar wäre es doppelt gemoppelt. */
.sr-nur {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Die Einheitenwahl neben dem Mengenfeld. Sie erscheint nur, wo der Artikel
   eigene Einheiten führt – ein Feld mit einer einzigen Möglichkeit ist ein
   Bedienschritt ohne Entscheidung. */
.mengeneinheit[hidden] { display: none; }

/* ---------- „Aus 1 Kiste werden 24 Flaschen“ ----------
   Das Formular liest sich als der Satz, den es speichert. Zwei Felder mit den
   Überschriften „Name“ und „Faktor“ wären dieselbe Eingabe und halb so
   verständlich. */
.einheit-satz {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;
  margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--border);
}
.einheit-satz input,
.einheit-satz select { min-height: 44px; width: auto; }
.einheit-satz input { max-width: 7rem; }
.einheit-satz > span { color: var(--muted); }
.einheit-satz > span strong { color: var(--text); }


/* ---------- Dienstplan ----------
   Sieben Kaesten nebeneinander, so wie der Plan am Schwarzen Brett haengt.
   Auf einem schmalen Bildschirm werden daraus sieben untereinander – eine
   Woche quer zu scrollen findet im Betrieb niemand. */

.dienstplan {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0.9rem;
  margin-top: 0.9rem;
}
.dienstplan-tag {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.75rem 0.8rem 0.85rem;
  background: var(--card);
}
.dienstplan-tag.heute { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.dienstplan-tag h3 { margin: 0 0 0.5rem; font-size: 0.95rem; display: flex; gap: 0.4rem;
  align-items: baseline; flex-wrap: wrap; }
.dienstplan-tag h3 .muted { font-size: 0.8rem; font-weight: 400; }

.dienstplan .schichten { list-style: none; margin: 0 0 0.6rem; padding: 0;
  display: flex; flex-direction: column; gap: 0.5rem; }
.dienstplan .schicht {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.5rem;
  padding: 0.45rem 0.55rem;
  border-radius: 8px;
  background: var(--surface-2);
  font-size: 0.88rem;
}
/* Eine abgesagte Schicht bleibt stehen und bleibt lesbar – sie ist die
   Luecke im Plan, und die soll man sehen. */
.dienstplan .schicht.abgesagt { opacity: 0.6; }
.dienstplan .schicht.abgesagt .zeit { text-decoration: line-through; }
.dienstplan .schicht .zeit { font-variant-numeric: tabular-nums; font-weight: 600; }
.dienstplan .schicht .wer { display: flex; flex-direction: column; gap: 0.1rem; }
.dienstplan .schicht .wer .muted { font-size: 0.78rem; }
.dienstplan .schicht .stand,
.dienstplan .schicht .row-actions { grid-column: 1 / -1; }
/* Vier Knoepfe in einer Kastenbreite: kleiner gesetzt, damit sie in eine
   Zeile passen. Auf dem Tablet bleiben sie trotzdem zu treffen - der Kasten
   ist mindestens 230 Pixel breit. */
.dienstplan .schicht .row-actions { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.15rem; }
.dienstplan .schicht .row-actions .btn { padding: 0.2rem 0.5rem; font-size: 0.76rem; }
.dienstplan .schicht-neu summary { font-size: 0.85rem; cursor: pointer; color: var(--muted); }
.dienstplan .schicht-neu[open] summary { margin-bottom: 0.5rem; }
