/* source/style_css/010_root_palette_header_nav.css - style.css part 1 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
:root {
    /* Helle "welcome.php"-Palette (lp-System) — ersetzt die frühere dunkle Greek-Taverna-Theme
       im gesamten Staff-Modul (Kasse/Küche/Bar/Admin/Personal), auf Nutzerwunsch angeglichen. */
    --djk-black: #f8fafc;
    --djk-black-soft: #eef2f7;
    --djk-black-card: #ffffff;
    /* Farbe der gerade aktiven Warengruppe (Kasse), wird von kasse.js beim Öffnen/Wechseln
       gesetzt — siehe #warengruppenRow. Startwert Gelb, bis JS den echten Wert kennt. */
    --aktive-warengruppe-farbe: var(--djk-yellow);
    /* Das dunkle Band ganz oben in der Kasse (Tisch, Suche, Symbolknöpfe). Bewusst KEINE
       Themenfarbe: es ist in beiden Erscheinungsbildern dasselbe Band, und die Schrift, der
       Platzhalter und die Lupe darin sind fest hell gesetzt. Als Variable, weil derselbe Wert
       sonst an zwei Stellen steht und beim nächsten Ändern eine davon stehen bleibt. */
    /* Die Stuehle im Tischplan (10.09.2026). Sie gehoeren in den umschaltbaren Satz und
       nicht als feste Hex-Werte an die drei Plaene: `--djk-black` ist im STANDARD hell
       (#f8fafc) und erst unter `body.thema-dunkel` wirklich dunkel. Wer den Grund fuer fest
       haelt, waehlt die Farbe fuer den falschen Fall — genau das war beim ersten Anlauf
       passiert: fuer die Tischwahl stand „zu blass fuer Weiss" im Kommentar und ein noch
       HELLERER Ton im Code. */
    --tisch-stuhl: #64748b;
    --tisch-stuhl-rand: #475569;
    --kasse-leiste: #242830;
    --djk-yellow: #3b82f6;
    --djk-yellow-dark: #2563eb;
    --djk-blue: #8b5cf6;
    --djk-blue-light: #a78bfa;
    --djk-white: #0f172a;
    --djk-gray: #64748b;
    --djk-border: #e2e8f0;
    --djk-danger: #ef4444;
    --djk-success: #10b981;
    --djk-copper: #f59e0b;
    --radius: 5px;
    --shadow: 0 4px 16px rgba(30, 41, 59, 0.08);
    --transition: 0.2s ease;
    --djk-sidebar-bg: #ffffff;
    --djk-sidebar-bg-active: #eff6ff;
    --djk-sidebar-border: #e2e8f0;
    --djk-sidebar-text: #475569;
    --djk-sidebar-section: #2563eb;
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    touch-action: pan-x pan-y;
    /* Verhindert, dass ein leichtes Zittern beim Antippen (normal bei Touchscreens) vom
       Browser als "Pull-to-Refresh"-Geste interpretiert wird und die Seite neu lädt. */
    overscroll-behavior: contain;
    /* html hatte sonst keinen eigenen Hintergrund (Browser-Standard: weiß) — beim nativen
       iOS-Rubber-Band-Überziehen am unteren Rand blitzt genau dieser weiße html-Hintergrund
       kurz unter der fixierten unteren Leiste (z. B. .kasse-bottom-bar) auf, auch wenn
       overscroll-behavior:contain das Durchreichen an den Browser-Chrome selbst verhindert. */
    background: var(--djk-black);
}

body {
    font-family: 'Segoe UI', Roboto, -apple-system, BlinkMacSystemFont, sans-serif;
    background: var(--djk-black);
    color: var(--djk-white);
    min-height: 100vh;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

/* Ein Verweis nimmt die Farbe seiner Umgebung.
   Hier stand `var(--djk-black)`. Das ist in diesem Projekt die FLAECHE, nicht die Schrift —
   dieselbe Verwechslung wie beim Z-Bericht. Solange alles dunkel war, fiel sie nicht auf; seit
   der hellen Palette ist `--djk-black` fast weiss, und jeder ungestylte Verweis auf einer
   weissen Karte war unsichtbar (Kontrast 1,05 — gemeldet am 11.08.2026 an der Telefonnummer
   einer Bestellung).
   `inherit` statt einer festen Farbe, weil ein Verweis auf jedem Grund stehen kann: auf der
   weissen Karte, auf einer gelben Marke, im dunklen Erscheinungsbild. Er liest sich dann immer
   wie der Text daneben und kann nie mit seinem eigenen Hintergrund verschmelzen. */
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }

img { max-width: 100%; display: block; }

.container {
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 20px;
}

/* ---------- Header / Nav ---------- */
.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(8px);
    border-bottom: 2px solid var(--djk-yellow);
    padding-top: env(safe-area-inset-top, 0px);
}

.site-header .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 68px;
    padding-left: max(20px, env(safe-area-inset-left, 0px));
    padding-right: max(20px, env(safe-area-inset-right, 0px));
}

.brand {
    display: flex;
    align-items: center;
    gap: 12px;
    font-weight: 800;
    font-size: 1.15rem;
    letter-spacing: 0.5px;
    color: var(--djk-white);
}

.brand .logo-badge {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: var(--djk-yellow);
    color: var(--djk-black);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    font-size: 1.1rem;
    flex-shrink: 0;
}

.brand .logo-badge-img { object-fit: cover; background: none; }

.brand small {
    display: block;
    color: var(--djk-gray);
    font-weight: 400;
    font-size: 0.7rem;
}

.nav-links {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nav-links a, .nav-links button {
    color: var(--djk-white);
    padding: 9px 16px;
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.92rem;
    transition: background var(--transition), color var(--transition);
}

.nav-links a:hover { background: rgba(59, 130, 246, 0.12); text-decoration: none; }

.nav-links .btn-cta {
    background: var(--djk-yellow);
    color: var(--djk-black);
}

.nav-links .btn-cta:hover { background: var(--djk-yellow-dark); }

/* #navLinks (ID) statt .nav-links (Klasse), damit dies unabhängig von der Ladereihenfolge
   immer gegen .home-landing .nav-links a (home.css) gewinnt — sonst ueberschreibt Letzteres
   per Cascade-Reihenfolge bei gleicher Spezifitaet die Icon-Farbe (schon einmal so einem Bug
   beim Warenkorb-Icon begegnet, siehe Git-Historie). */
#navLinks a.nav-icon-link {
    padding: 0;
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: var(--djk-yellow);
    border: 2px solid var(--djk-yellow);
    position: relative;
    flex-shrink: 0;
}

#navLinks a.nav-icon-link:hover { background: rgba(59, 130, 246, 0.12); }
#navLinks a.nav-icon-link .icon { width: 19px; height: 19px; }

.nav-cart-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    background: var(--djk-danger);
    color: #fff;
    border-radius: 50%;
    min-width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.68rem;
    font-weight: 800;
    padding: 0 3px;
}

.top-icons {
    display: none;
    align-items: center;
    gap: 8px;
}

/* A-/A+ Schriftgrößen-Steuerung für die Küche/Bar-Ticketboards (nur Desktop-Topbar,
   siehe personal/includes/header.php $topbarFontControls) — skaliert per JS nur den
   Ticket-Inhalt (#kuecheBoard), nicht die restliche Seite. */
.kueche-font-controls {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-right: 10px;
}
.topbar-font-btn {
    background: none;
    border: 2px solid var(--djk-yellow);
    color: var(--djk-yellow);
    border-radius: 50%;
    width: 34px;
    height: 34px;
    cursor: pointer;
    font-weight: 800;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.topbar-font-btn:hover { background: rgba(59, 130, 246, 0.12); }
.topbar-font-btn-sm { font-size: 0.7rem; }
.topbar-font-btn-lg { font-size: 1.15rem; }

.top-icons a {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--djk-yellow);
    border: 2px solid var(--djk-yellow);
    position: relative;
    flex-shrink: 0;
}

.top-icons a:hover { background: rgba(59, 130, 246, 0.12); text-decoration: none; }
.top-icons a .icon { width: 19px; height: 19px; }



/*
 * BAR ODER BANK an der Ausgabe (25.08.2026) -- zwei Knoepfe statt einer Liste zum Aufklappen.
 *
 * Es sind genau zwei Moeglichkeiten, und beide muessen ohne Oeffnen sichtbar sein: wer eine
 * Rechnung erfasst, soll die Frage BEANTWORTEN und nicht erst suchen. Keiner ist vorgewaehlt --
 * ein vorgehaktes "Bar" waere bequem und im Kassenbuch eine Luege.
 *
 * Das Feld selbst bleibt unsichtbar, aber BEDIENBAR (nicht display:none): so springt die
 * Tastatur weiter hinein, der Browser meldet sein `required` an der richtigen Stelle, und
 * Vorlesegeraete finden die Gruppe.
 */
.zahlart-wahl {
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 0;
    margin: 0;
    padding: 0;
    min-width: 0;
}
.zahlart-wahl legend {
    padding: 0;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--djk-gray);
}
.zahlart-wahl > label + label { margin-top: 0; }
.zahlart-knopf { display: block; cursor: pointer; }
.zahlart-knopf input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
}
.zahlart-knopf > span {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: var(--feld-hoehe, 43px);
    padding: 0 12px;
    border: 1.5px solid var(--djk-border);
    border-radius: 8px;
    background: var(--djk-card, #fff);
    font-weight: 600;
    line-height: 1;
}
.zahlart-knopf input:checked + span {
    border-color: var(--djk-yellow);
    box-shadow: inset 0 0 0 1.5px var(--djk-yellow);
}
/* Sichtbar auch fuer den, der mit der Tastatur geht -- sonst waere der Knopf fuer ihn stumm. */
.zahlart-knopf input:focus-visible + span { outline: 2px solid var(--djk-yellow); outline-offset: 2px; }

/* Zwei nebeneinander, sobald Platz ist. */
@media (min-width: 560px) {
    .zahlart-wahl { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
    .zahlart-wahl legend { flex: 0 0 100%; }
    .zahlart-knopf { flex: 1 1 120px; }
}

/* In der Liste: die fertige Angabe als ruhige Marke, die fehlende als Frage. */
.zahlart-marke { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; white-space: nowrap; }
.zahlart-offen { color: var(--djk-gray); font-style: italic; margin-right: 6px; }
.zahlart-nachtragen { display: inline-flex; gap: 4px; flex-wrap: wrap; }

/* Bottom app-style tab bar (mobile) */
.bottom-nav {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    background: rgb(255 255 255 / 55%);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--djk-border);
    padding: 6px max(8px, env(safe-area-inset-left, 0px)) calc(6px + env(safe-area-inset-bottom, 0px)) max(8px, env(safe-area-inset-right, 0px));
}

.bottom-nav-inner {
    display: flex;
    align-items: center;
}

.bottom-nav a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1;
    color: var(--djk-gray);
    font-size: 0.65rem;
    font-weight: 600;
    padding: 6px 4px;
    border-radius: 5px;
    text-align: center;
}

.bottom-nav a:hover { text-decoration: none; }
.bottom-nav a .icon { width: 22px; height: 22px; }
.bottom-nav a.active { color: var(--djk-yellow); }
.bottom-nav-icon-wrap { position: relative; display: inline-flex; }
.bottom-nav-icon-wrap .nav-cart-badge { top: -6px; right: -8px; }

/* source/style_css/015_root_palette_header_nav_continued.css - style.css: root palette header nav continued, part 2 of 78 (built by werkzeuge/parts_build.php) */
/*
 * DIE VOLLE LEISTE (25.08.2026) -- sie traegt jetzt alles, was frueher oben stand.
 *
 * Vorher waren es hoechstens vier Punkte, jetzt koennen es acht sein (Kasse, Online, Kueche,
 * Bar, Verlauf, Reservierungen, A-/A+, Abmelden). Auf einem 360-Pixel-Telefon bleiben damit
 * rund 45 Pixel je Punkt: das Zeichen bleibt gross genug zum Treffen, die Schrift wird kleiner,
 * und ein zu langes Wort bricht nicht um, sondern wird gekuerzt. Umbrechen waere schlimmer --
 * die Leiste wuerde doppelt so hoch und naehme dem Brett eine Reihe Zettel.
 */
.bottom-nav--voll .bottom-nav-inner { gap: 0; }
.bottom-nav--voll a,
.bottom-nav--voll button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    flex: 1 1 0;
    min-width: 0;                 /* ohne dies weigert sich ein Flex-Kind zu schrumpfen */
    color: var(--djk-gray);
    font-size: 0.58rem;
    font-weight: 600;
    line-height: 1.15;
    padding: 5px 2px;
    border: 0;
    background: none;
    border-radius: 5px;
    text-align: center;
    cursor: pointer;
}
.bottom-nav--voll a > span:last-child,
.bottom-nav--voll button > span:last-child {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.bottom-nav--voll .icon { width: 20px; height: 20px; }
.bottom-nav--voll a.active { color: var(--djk-yellow); }

/* A-/A+ tragen kein Sinnbild, sondern einen Buchstaben -- er muss so gross wirken wie ein
   Zeichen daneben, sonst sieht die Leiste an dieser Stelle leer aus. */
.bottom-nav-zeichen {
    font-size: 1.05rem;
    font-weight: 800;
    line-height: 20px;
    color: var(--djk-gray);
}
.bottom-nav-zeichen--klein { font-size: 0.8rem; }

/* Abmelden steht ganz rechts, weil es in der Datei zuletzt kommt -- keine Regel noetig: alle
   Punkte teilen sich die Breite gleich (flex: 1 1 0). Das Zeichen ist rot (ICON_FARBE), die
   Beschriftung darunter bleibt grau wie bei den uebrigen: zwei rote Zeilen waeren ein Alarm,
   und Abmelden ist kein Alarm. */

/* Auf sehr schmalen Geraeten zaehlt jeder Pixel. */
@media (max-width: 400px) {
    .bottom-nav--voll a,
    .bottom-nav--voll button { font-size: 0.52rem; padding: 5px 1px; }
    .bottom-nav--voll .icon { width: 18px; height: 18px; }
}

@media (max-width: 780px) {
    .nav-toggle,
    .nav-links { display: none !important; }
    .top-icons { display: flex; }
    .bottom-nav { display: block; }
    body { padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }
    .site-footer { display: none; }
    /* Personal/Staff-Seiten (Küche/Bar/Verlauf) haben auf dem Handy bereits die untere
       Navigationsleiste (Kasse/Küche/Bar/Verlauf/Abmelden) — der obere Header mit
       Marke+Rolle+Logout-Icon ist dort nur redundanter Platzverbrauch. Nur für
       .personal-body ausblenden, damit die öffentliche Seite unverändert bleibt. */
    .personal-body .site-header { display: none; }
}

/* source/style_css/020_hero_sections_buttons_forms.css - style.css part 3 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
.nav-toggle {
    display: none;
    background: none;
    border: 2px solid var(--djk-yellow);
    color: var(--djk-yellow);
    border-radius: 5px;
    width: 42px;
    height: 42px;
    font-size: 1.2rem;
    cursor: pointer;
}

/* ---------- Hero ---------- */
.hero {
    padding: 64px 0 48px;
    text-align: center;
    background:
        radial-gradient(ellipse at top, rgba(59, 130, 246, 0.14), transparent 55%),
        radial-gradient(ellipse at 20% 100%, rgba(139, 92, 246, 0.14), transparent 60%);
}

.hero-icon {
    display: block;
    width: 48px;
    height: 48px;
    color: var(--djk-blue-light);
    margin: 0 auto 14px;
    opacity: 0.9;
}

.hero-icon .icon { width: 100%; height: 100%; }

.badge.hero-tagline {
    margin: 0 0 16px;
    background: var(--djk-blue);
    color: var(--djk-white);
}

.hero h1 {
    font-size: clamp(2rem, 5vw, 3.2rem);
    margin: 0 0 14px;
    font-weight: 900;
    letter-spacing: -0.5px;
}

.hero h1 span { color: var(--djk-yellow); }

.hero p {
    color: var(--djk-gray);
    font-size: 1.1rem;
    max-width: 620px;
    margin: 0 auto 28px;
}

.hero-actions {
    display: flex;
    gap: 14px;
    justify-content: center;
    flex-wrap: wrap;
}

.stripe {
    height: 16px;
    background-color: var(--djk-black);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='16' viewBox='0 0 24 16'%3E%3Cpath d='M0 13H7V3H12V13H17V3H24' fill='none' stroke='%23f2c14e' stroke-width='2.6' stroke-linecap='square'/%3E%3C/svg%3E");
    background-repeat: repeat-x;
    background-position: center;
}

/* ---------- Sections ---------- */
.section {
    padding: 48px 0;
}

.section-title {
    font-size: 1.6rem;
    font-weight: 800;
    margin-bottom: 24px;
    text-align: center;
}

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 18px;
}

.mitglied-card {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 22px;
    text-align: center;
    transition: transform var(--transition), border-color var(--transition);
}

.mitglied-card:hover {
    transform: translateY(-4px);
    border-color: var(--djk-yellow);
}

.mitglied-card .icon-wrap {
    width: 52px;
    height: 52px;
    margin: 0 auto 12px;
    border-radius: 50%;
    background: rgba(59, 130, 246, 0.12);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--djk-yellow);
}
.mitglied-card .icon-wrap .icon { width: 26px; height: 26px; }
.mitglied-card h3 { margin: 0; font-size: 1.05rem; }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 26px;
    border-radius: 5px;
    font-weight: 700;
    font-size: 0.95rem;
    cursor: pointer;
    border: 2px solid transparent;
    transition: all var(--transition);
    touch-action: manipulation;
}

.btn-primary {
    background: var(--djk-yellow);
    color: #ffffff;
}
.btn-primary:hover { background: var(--djk-yellow-dark); text-decoration: none; }

.btn-outline {
    background: transparent;
    border-color: var(--djk-yellow);
    color: var(--djk-yellow-dark);
}
.btn-outline:hover { background: rgba(59, 130, 246, 0.1); text-decoration: none; }

.btn-danger {
    background: var(--djk-danger);
    color: #fff;
}

.btn-block { width: 100%; }
.btn-sm { padding: 8px 16px; font-size: 0.85rem; }

button.link-btn {
    background: none;
    border: none;
    color: var(--djk-yellow);
    cursor: pointer;
    font: inherit;
    padding: 0;
}

/* ---------- Forms ---------- */
.form-card {
    /* background: var(--djk-black-card); */
    /* border: 1px solid var(--djk-border); */
    border-radius: var(--radius);
    padding: 20px;
    width: 100%;
    margin: 0 auto;
    /* box-shadow: var(--shadow); */
}

.form-card h2 {
    margin-top: 0;
    font-size: 1.5rem;
}

/* source/style_css/030_admin_sidebar.css - style.css part 4 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Admin: Sidebar-Layout (ersetzt Top-Nav in admin/*) ---------- */
.admin-shell {
    display: flex;
    min-height: 100vh;
}

.admin-sidebar-nav {
    width: 260px;
    flex-shrink: 0;
    background: var(--djk-sidebar-bg);
    border-right: 1px solid var(--djk-sidebar-border);
    display: flex;
    flex-direction: column;
    height: 100vh;
    position: sticky;
    top: 0;
    transition: width var(--transition);
    z-index: 200;
}

.admin-sidebar-search-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px;
    border-bottom: 1px solid var(--djk-sidebar-border);
    flex-shrink: 0;
}

.admin-sidebar-search {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid var(--djk-sidebar-border);
    border-radius: 5px;
    padding: 0 10px;
}
.admin-sidebar-search .icon { width: 16px; height: 16px; flex-shrink: 0; color: var(--djk-sidebar-text); }
/* Das `[type="text"]` ist Absicht und kein Beiwerk: die Grundregel für alle Textfelder steht
   weiter unten (Abschnitt BEDIENELEMENTE) und wiegt mit Element + Attribut genauso schwer wie
   eine Klasse. Bei gleichem Gewicht entscheidet die Reihenfolge — ohne das Attribut hier
   bekäme dieses Feld Rand, Grund und Polster der Grundregel und wäre nicht mehr das randlose
   Feld in der Suchpille, sondern ein Kasten im Kasten (Falle 1). */
.admin-sidebar-search input[type="text"] {
    flex: 1;
    min-width: 0;
    background: none;
    border: none;
    outline: none;
    color: var(--djk-white);
    font-size: 0.85rem;
    padding: 9px 0;
}
.admin-sidebar-search input[type="text"]:focus { box-shadow: none; }
.admin-sidebar-search input::placeholder { color: var(--djk-sidebar-text); }

.admin-sidebar-links {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 10px 0 12px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.admin-sidebar-group-label {
    padding: 4px 18px;
    color: var(--djk-sidebar-section);
    font-weight: 800;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
    overflow: hidden;
}

.admin-sidebar-group { display: flex; flex-direction: column; }

.admin-sidebar-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 18px;
    color: var(--djk-sidebar-text);
    font-weight: 600;
    font-size: 0.88rem;
    white-space: nowrap;
    overflow: hidden;
}
.admin-sidebar-link .icon { width: 19px; height: 19px; flex-shrink: 0; }
/* Beide Zustände stammten noch aus der Zeit, als das Menü dunkel war: weiße Schrift auf
   hellem Grund — der gewählte Punkt war praktisch unlesbar und hob sich kaum ab. Jetzt trägt
   er die Menüfarbe, kräftiger Schrift und einen Balken links, der ihn schon aus dem Augenwinkel
   findbar macht. */
.admin-sidebar-link:hover {
    background: #cccccc96;
    color: var(--djk-sidebar-text);
    text-decoration: none;
}
.admin-sidebar-link.active {
    background: var(--djk-sidebar-bg-active);
    color: var(--djk-sidebar-section);
    font-weight: 800;
    box-shadow: inset 3px 0 0 var(--djk-sidebar-section);
}
.admin-sidebar-link.active:hover { background: var(--djk-sidebar-bg-active); color: var(--djk-sidebar-section); }
.admin-sidebar-link.active .icon { color: var(--djk-sidebar-section); }
.admin-sidebar-link.is-hidden { display: none; }
.admin-sidebar-group.is-hidden { display: none; }

.admin-sidebar-submenu-toggle {
    width: 100%;
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
    text-align: left;
}
.admin-sidebar-chevron {
    margin-left: auto;
    display: flex;
    flex-shrink: 0;
    transition: transform var(--transition);
}
.admin-sidebar-chevron .icon { width: 15px; height: 15px; }
.admin-sidebar-submenu-toggle.active .admin-sidebar-chevron { transform: rotate(180deg); }

.admin-sidebar-submenu {
    display: none;
    flex-direction: column;
    padding: 2px 0 6px;
}
.admin-sidebar-submenu.open { display: flex; }
/* Von der Menüsuche ausgeblendet. Muss NACH der `.open`-Regel stehen: beide wiegen gleich viel
   (Klasse + Klasse), bei gleicher Spezifität entscheidet die Reihenfolge — davor hätte
   `.open { display: flex }` sie überstimmt und ein weggefiltertes Untermenü bliebe stehen. */
.admin-sidebar-submenu.is-hidden,
.admin-sidebar-sublink.is-hidden { display: none; }

.admin-sidebar-sublink {
    padding: 9px 18px 9px 49px;
    color: var(--djk-sidebar-text);
    font-weight: 600;
    font-size: 0.83rem;
    white-space: nowrap;
    overflow: hidden;
}
.admin-sidebar-sublink:hover { background: rgba(0, 0, 0, 0.18); color: var(--djk-white); text-decoration: none; }
/*
 * ═══ EIN PUNKT ZU EINEM PROGRAMM, DAS NICHT GEBUCHT IST (12.09.2026) ═══
 *
 * Der Wirt hatte die Wahl zwischen „gar nicht zeigen" und „abgeschaltet zeigen" und hat sich
 * fuer das zweite entschieden. Ein Punkt, der fehlt, hinterlaesst eine Frage; ein Punkt, der
 * grau dasteht, beantwortet sie.
 *
 * Deutlich leiser als ein aktiver Punkt — er soll da sein, nicht anziehen. Kein Mauszeiger,
 * kein Aufleuchten beim Ueberfahren: was nicht klickt, darf auch nicht so aussehen.
 * `user-select: none`, damit ein Fingertipp auf dem Tablett nicht den Text markiert statt
 * nichts zu tun.
 */
.admin-sidebar-gesperrt {
    display: flex;
    align-items: center;
    gap: 12px;
    opacity: 0.42;
    cursor: default;
    user-select: none;
}
.admin-sidebar-gesperrt:hover { background: transparent; color: var(--djk-sidebar-text); }
/* Das Schloss steht RECHTS am Rand, wie der Pfeil eines Klappmenues — dort sucht das Auge
   die Auskunft ueber den Zustand der Zeile, nicht neben dem Namen. */
.admin-sidebar-schloss { margin-left: auto; display: inline-flex; }
.admin-sidebar-schloss .icon { width: 15px; height: 15px; }
/* Als Unterpunkt traegt die Zeile schon den Einzug aus `.admin-sidebar-sublink`; das `gap`
   der Flex-Reihe kaeme dann doppelt. */
.admin-sidebar-sublink.admin-sidebar-gesperrt { gap: 8px; }
/*
 * Ein ganzer Block, der zu einem nicht gebuchten Programm gehoert (12.09.2026).
 *
 * Die Ueberschrift und der Hinweis bleiben LESBAR — sie sagen ja gerade, warum hier nichts
 * geht. Blass wird nur, was man bedienen koennte, und bedienen laesst es sich nicht.
 */
.admin-form-section-gesperrt .toggle-switch,
.admin-form-section-gesperrt input,
.admin-form-section-gesperrt select { pointer-events: none; }
.admin-form-section-gesperrt > *:not(.admin-form-section-title):not(.admin-gesperrt-hinweis) {
    opacity: 0.45;
}
.admin-gesperrt-hinweis {
    border-left: 3px solid var(--djk-yellow);
    padding-left: 9px;
}
.admin-sidebar-sublink.active { color: var(--djk-yellow); font-weight: 700; }

/* Die Ansichts-Schalter im Menüfuß. Am großen Bildschirm stehen sie schon oben in der
   Kopfleiste — dort sind sie näher an dem, was sie verändern; hier wären sie doppelt. Auf dem
   Handy gibt es die Kopfleiste nicht, und dies ist der einzige Ort, an dem sie erreichbar sind
   (das Menü öffnet sich dort über „Mehr"). */
.admin-sidebar-ansicht {
    display: none;
    flex-shrink: 0;
    gap: 8px;
    padding: 10px 14px;
    border-top: 1px solid var(--djk-sidebar-border);
    flex-wrap: wrap;
}
.admin-sidebar-ansicht .ansicht-schalter {
    background: rgba(15, 23, 42, .06);
    border-color: rgba(15, 23, 42, .12);
}
.admin-sidebar-ansicht .ansicht-schalter-taste { color: var(--djk-sidebar-text); }

.admin-sidebar-footer {
    flex-shrink: 0;
    padding: 8px 0;
    border-top: 1px solid var(--djk-sidebar-border);
    display: flex;
    flex-direction: column;
}

.admin-sidebar-collapse-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: 5px;
    border: 1px solid var(--djk-sidebar-border);
    background: rgba(0, 0, 0, 0.2);
    color: var(--djk-sidebar-text);
    font-size: 1.1rem;
    cursor: pointer;
}
.admin-sidebar-collapse-btn:hover { color: var(--djk-yellow); border-color: var(--djk-yellow); }

/* Eingeklappt: nur Icons, kein Text */
/* Zwei Wege zum selben Zustand, und der zweite ist der wichtige:
   `.is-collapsed` setzt das Skript, wenn jemand den Knopf drückt — das läuft erst am Ende der
   Seite. `html.admin-menue-zu` setzt dagegen ein winziges Skript im <head>, also VOR dem ersten
   Zeichnen. Ohne das erschien das Menü bei jedem Seitenwechsel kurz breit und klappte dann
   sichtbar zusammen; die Übergangsanimation an `width` machte daraus ein deutliches Zucken.
   Steht die Klasse von Anfang an, ändert sich die Breite gar nicht mehr — und ohne Änderung
   gibt es auch keine Animation. Die Animation bleibt genau dort, wo sie hingehört: beim
   Drücken des Knopfes. */
.admin-sidebar-nav.is-collapsed,
html.admin-menue-zu .admin-sidebar-nav { width: 72px; }
.admin-sidebar-nav.is-collapsed .admin-sidebar-search,
.admin-sidebar-nav.is-collapsed .admin-sidebar-group-label,
.admin-sidebar-nav.is-collapsed .admin-sidebar-link span,
html.admin-menue-zu .admin-sidebar-nav .admin-sidebar-search,
html.admin-menue-zu .admin-sidebar-nav .admin-sidebar-group-label,
html.admin-menue-zu .admin-sidebar-nav .admin-sidebar-link span { display: none; }
.admin-sidebar-nav.is-collapsed .admin-sidebar-search-row,
html.admin-menue-zu .admin-sidebar-nav .admin-sidebar-search-row { justify-content: center; }
.admin-sidebar-nav.is-collapsed .admin-sidebar-link,
html.admin-menue-zu .admin-sidebar-nav .admin-sidebar-link { justify-content: center; padding-left: 0; padding-right: 0; }
.admin-sidebar-nav.is-collapsed .admin-sidebar-submenu,
html.admin-menue-zu .admin-sidebar-nav .admin-sidebar-submenu { display: none !important; }

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

.admin-topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 20px;
    background: #cccccc;
    position: sticky;
    top: 0;
    z-index: 50;
}
/* `--djk-white` ist im hellen Schema die SCHRIFTfarbe (#0f172a), `--djk-black` die Fläche
   (#f8fafc) — die Namen stammen aus dem alten dunklen Schema und sind seitdem verdreht.
   Hier stand `--djk-black`: nahezu weiße Schrift auf dem grauen #cccccc der Leiste, ein
   Kontrast von 1,3:1. Der Seitentitel war praktisch nicht zu lesen. */
.admin-topbar-title { font-weight: 800; font-size: 1.05rem; flex: 1; color: var(--djk-white); }
.admin-topbar-icon { position: relative; color: var(--djk-white); display: flex; opacity: 0.75; }
.admin-topbar-icon:hover { opacity: 1; }
.admin-topbar-icon .icon { width: 22px; height: 22px; }
.admin-topbar-badge {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--djk-black);
    color: var(--djk-yellow);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    font-size: 0.85rem;
    flex-shrink: 0;
}

/* Der Inhaltsbereich der Verwaltung. Die 30 px sind die Vorgabe des Wirts (11.08.2026) — sie
   geben den Seiten Luft zum Rand hin, auch dort, wo der Inhalt nicht in einem `.container`
   steckt und sonst an der Seitenleiste klebt. Am Telefon bleiben die Seiten randlos, siehe die
   Regel in @media (max-width: 900px): dort waeren 30 px links und rechts zusaetzlich zu den
   20 px des `.container` ein Drittel der Bildschirmbreite. */
.admin-content { flex: 1; padding: 30px; }
.admin-content-guest { display: flex; align-items: center; justify-content: center; min-height: 100vh; }

/* source/style_css/040_mobile_bottom_nav.css - style.css part 5 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* Mobil: Bottom-Nav ersetzt das seitliche Menü (siehe @media (max-width: 900px) weiter unten) *//* ================= Handy-Kopfzeile und der runde Beleg-Knopf (24.08.2026) ================
 *
 * Der Wirt hat es auf dem Telefon gezeichnet: in der Mitte der Name der Anwendung, rechts die
 * gelbe Glocke, unten rechts ein runder Knopf mit einem Plus, der den Lieferantenbeleg
 * fotografiert. Alles drei gilt nur auf dem schmalen Schirm — am Schreibtisch bleibt die
 * Kopfzeile, wie sie war.
 */
.admin-topbar-marke { display: none; }

@media (max-width: 900px) {
    /* Der Seitenname tritt zurueck: WO man ist, sagt die Fussleiste ohnehin. */
    .admin-topbar-title { display: none; }
    .admin-topbar-marke {
        display: block;
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        font-weight: 800;
        font-size: 1rem;
        letter-spacing: .01em;
        color: var(--djk-white, #fff);
        pointer-events: none;   /* nur Beschriftung — Knoepfe darunter bleiben erreichbar */
        white-space: nowrap;
    }
    .admin-topbar { position: relative; }

    /* Die Glocke traegt ihre Hausfarbe wieder — in der Kopfzeile hatte deren eigene Regel sie
       uebermalt. Staerker geschrieben als `.ikon-gelb`, damit es keine Reihenfolge-Frage ist. */
    .admin-topbar .admin-topbar-glocke .icon { color: #f59e0b !important; }

    /* Der runde Beleg-Knopf ist seit dem 14.09.2026 weg — Belege erfasst e-buchung. */
}


.admin-bottom-nav {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    background: var(--djk-sidebar-bg);
    border-top: 1px solid var(--djk-sidebar-border);
    padding: 6px max(8px, env(safe-area-inset-left, 0px)) calc(6px + env(safe-area-inset-bottom, 0px)) max(8px, env(safe-area-inset-right, 0px));
}
.admin-bottom-nav-inner { display: flex; align-items: center; }
.admin-bottom-nav a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1;
    color: var(--djk-sidebar-text);
    font-size: 0.62rem;
    font-weight: 600;
    padding: 6px 2px;
    border-radius: 5px;
    text-align: center;
}
.admin-bottom-nav a:hover { text-decoration: none; }
.admin-bottom-nav a .icon { width: 21px; height: 21px; }
.admin-bottom-nav a.active { color: var(--djk-yellow); }
/* "Mehr"-Button öffnet den (auf Mobil sonst versteckten) Sidebar-Vollbild-Overlay statt zu
   navigieren — gleiches Aussehen wie die Bottom-Nav-Links, aber ein <button> statt <a>. */
.admin-bottom-nav button {
    background: none;
    border: none;
    cursor: pointer;
    font-family: inherit;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1;
    color: var(--djk-sidebar-text);
    font-size: 0.62rem;
    font-weight: 600;
    padding: 6px 2px;
    border-radius: 5px;
    text-align: center;
}
.admin-bottom-nav button .icon { width: 21px; height: 21px; }
.admin-bottom-nav button.active { color: var(--djk-yellow); }
.admin-topbar-icon-mobile-only { display: none; }
.admin-sidebar-mobile-close { display: none; }

/* Mobil: horizontale Tab-Leiste für Kategorien/Extras/Präfixe (Produkte) bzw. Tischkategorien (Tische) —
   ersetzt den Zugriff, den vorher nur das (jetzt versteckte) Desktop-Untermenü bot. Auf Desktop nicht sichtbar. */
.admin-mobile-subnav { display: none; }

/* Leicht abgesetzter Hintergrund für den Inhaltsbereich gegenüber der (jetzt ebenfalls
   hellen) Sidebar — die restlichen Variablen kommen bereits hell aus :root, keine
   Überschreibung mehr nötig (bis vor Kurzem war hier eine dunkle Basis-Theme aktiv). */
.admin-main-area {
    background: #eef1f5;
}
body.admin-body .form-card,
body.admin-body .mitglied-card,
body.admin-body .modal-box { box-shadow: var(--shadow); }
body.admin-body .field label { color: var(--djk-white); }
body.admin-body .clients-table th { color: var(--djk-gray); }
body.admin-body .tag { background: rgba(37, 99, 235, 0.12); color: var(--djk-yellow-dark); }
/* Etwas mehr Luft in der Marke — das gilt in beiden Erscheinungsbildern. Der GRUND dagegen
   nicht: durchscheinendes Weiß steht schön auf dem getönten Grund des warmen Bildes, auf der
   weißen Karte des klassischen wäre es weiß auf weiß und damit gar keine Marke mehr. */
body.admin-body .tag.muted {
    background: var(--djk-black-soft);
    color: var(--djk-gray);
    padding: 5px 10px;
}
/* Nur am großen Bildschirm: dort liegt die Marke auf dem getönten Grund und hebt sich davon ab.
   Auf dem Handy fällt der warme Rahmen weg (siehe unten), der Grund ist wieder hell — 58 %
   Weiß auf einer weißen Karte wäre dann weiß auf weiß. */
@media (min-width: 901px) {
    body.ansicht-warm .tag.muted { background: rgba(255, 255, 255, .58); }
}
body.admin-body .admin-produkt-price,
body.admin-body .aktivitaet-typ { color: var(--djk-yellow-dark); }
body.admin-body .stat-pill .num { color: var(--djk-white); }
body.admin-body .btn-outline { border-color: var(--djk-yellow-dark); color: var(--djk-yellow-dark); }
body.admin-body .btn-outline:hover { background: rgba(37, 99, 235, 0.08); }
body.admin-body .empty-state, body.admin-body .hint { color: var(--djk-gray); }

@media (max-width: 900px) {
    /* Hier — und nur hier — erscheinen die Ansichts-Schalter im Menü: die Kopfleiste, in der sie
       am großen Bildschirm stehen, gibt es auf dem Handy nicht. */
    .admin-sidebar-ansicht { display: flex; }

    /* Mobil: kein seitliches Menü mehr — Bottom-Nav übernimmt die Hauptnavigation, siehe .admin-bottom-nav.
       Der "Mehr"-Button blendet dasselbe Sidebar-Element per .is-mobile-open wieder als Vollbild-Overlay
       ein (weiterspringende Regel direkt danach) — so bleiben Buchhaltung/Reservierungen/Küche/Online Shop
       auf dem Handy erreichbar, statt in einer überfüllten Bottom-Nav zu verschwinden. */
    .admin-sidebar-nav { display: none !important; }
    .admin-sidebar-nav.is-mobile-open {
        display: flex !important;
        position: fixed;
        inset: 0;
        z-index: 300;
        width: 100% !important;
        height: 100dvh;
        /* Oben MUSS derselbe Sicherheitsabstand stehen wie unten. `inset: 0` beginnt bei
           Bildschirmzeile null — auf einem iPhone liegt dort die Statusleiste mit Uhrzeit,
           Empfang und Akku. Ohne diesen Abstand schob sich das Suchfeld darunter, und beides
           war übereinander zu lesen. Unten war der Abstand längst da, oben fehlte er. */
        padding-top: env(safe-area-inset-top, 0px);
        /* Auch unten PLUS statt MAX: auf einem Android-Geraet mit Wisch-Bedienung sind es
           rund 24 Punkte, und `max(16, 24)` liess dem letzten Menuepunkt keinen Abstand zum
           Balken. Dieselbe Verwechslung wie oben in der Kopfleiste der Kasse. */
        padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-search { display: flex !important; }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-group-label { display: block !important; }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-link span { display: inline !important; }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-link { justify-content: flex-start !important; padding-left: 18px !important; padding-right: 18px !important; }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-search-row { justify-content: space-between !important; }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-collapse-btn { display: none; }
    .admin-sidebar-nav.is-mobile-open.is-collapsed .admin-sidebar-submenu.open { display: flex !important; }
    .admin-sidebar-nav.is-mobile-open .admin-sidebar-mobile-close {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        width: 38px;
        height: 38px;
        border-radius: 5px;
        border: 1px solid var(--djk-sidebar-border);
        background: rgba(0, 0, 0, 0.2);
        color: var(--djk-sidebar-text);
        font-size: 1.4rem;
        line-height: 1;
        cursor: pointer;
    }
    .admin-bottom-nav { display: block; }
    /* iOS blendet die App unter der Statusleiste ein (Kopfzeile: status-bar-style
       black-translucent). Ohne diesen Abstand liegen Uhrzeit, WLAN und Akku auf der
       ersten Zeile der Seite — auf dem Handy ist das die Reiter-Leiste, weil die Topbar
       dort ausgeblendet ist. env() liefert 0, wenn die Leiste undurchsichtig ist, der
       Abstand entsteht also nur dort, wo er gebraucht wird.
       Bewusst am Container und nicht an der Reiter-Leiste: nicht jede Admin-Seite hat
       eine, dann stünde die jeweils erste Zeile wieder unter der Uhr. */
    .admin-content {
        /* Seitlich randlos: die 30 px der Grundregel kaemen zu den 20 px des `.container`
           hinzu, und auf einem 375er Telefon blieben vom Inhalt keine 280 px uebrig. */
        padding-left: 0;
        padding-right: 0;
        padding-top: env(safe-area-inset-top, 0px);
        padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    }
    /* Mobil: Topbar komplett entfernt (nicht nur umgefärbt) — Titel/Icons/Zurück-Pfeil sind
       auf Mobil nicht mehr nötig, da Bottom-Nav + Subnav die komplette Navigation abdecken. */
    .admin-topbar { display: none; }
    /* Mobil: nicht mehr "sticky" (gleicher iOS-Bug wie bei der Topbar — Taps direkt unter
       einem sticky-Element landen dort manchmal ins Leere, z. B. auf die erste Produktkarte). */
    .admin-filter-bar {
        position: static;
        background: var(--djk-black-soft);
        padding: 10px 0;
        margin-bottom: 10px;
    }
    /* Umbrechen statt seitwärts scrollen: auf dem Handy soll nichts quer wegrutschen —
       dasselbe Gesetz wie bei den Tabellen weiter unten. Wer die hinteren Reiter nicht sieht,
       findet sie auch nicht; ein zweite Zeile kostet 30 Pixel und löst das. */
    .admin-mobile-subnav {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        padding: 10px;
        margin-bottom: 4px;
    }
    .admin-mobile-subnav a {
        flex: 0 1 auto;
        padding: 7px 14px;
        border-radius: 5px;
        border: 1px solid var(--djk-border);
        font-size: 0.78rem;
        font-weight: 700;
        white-space: nowrap;
        background: #80b0ff;
    }
    .admin-mobile-subnav a:hover { text-decoration: none; color: var(--djk-white); }
    .admin-mobile-subnav a.active { background: var(--djk-yellow); border-color: var(--djk-yellow); color: var(--djk-black); }
}

/* source/style_css/050_admin_products_layout.css - style.css part 6 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Admin Produkte: two-column desktop layout ---------- */
.admin-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 6px;
}

.admin-tab-btn {
    flex: 1;
    min-width: 80px;
    background: none;
    border: none;
    border-radius: 5px;
    padding: 10px 8px;
    color: var(--djk-gray);
    font-weight: 700;
    font-size: 0.82rem;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.admin-tab-btn.active { background: var(--djk-yellow); color: var(--djk-black); }
.admin-tab-btn:not(.active):hover { background: var(--djk-black-soft); color: var(--djk-white); }

.admin-tab-panel { display: none; }
.admin-tab-panel.active { display: block; }

/* Meine Bestellung: Online-Shop-Bestellverfolgung — bewusst eigene Akzentfarben statt
   des sonst überall verwendeten Gelb, damit Status auf einen Blick unterscheidbar ist. */
.order-track-card {
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-left: 4px solid var(--djk-copper);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 12px;
}
.order-track-card:last-child { margin-bottom: 0; }
.order-track-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.order-track-datum { font-size: 0.82rem; color: var(--djk-gray); }
.order-track-status {
    font-size: 0.78rem;
    font-weight: 800;
    padding: 4px 10px;
    border-radius: 999px;
}
.order-status-offen { background: rgba(245, 158, 11, 0.16); color: var(--djk-copper); }
.order-status-bestaetigt { background: rgba(139, 92, 246, 0.16); color: var(--djk-blue-light); }
.order-status-fertig { background: rgba(76, 175, 80, 0.16); color: #15803d; }
.order-status-unterwegs { background: rgba(76, 175, 80, 0.22); color: #15803d; }
.order-status-storniert { background: rgba(224, 90, 90, 0.16); color: var(--djk-danger); }
.order-track-meta { font-size: 0.85rem; color: var(--djk-gray); margin-bottom: 10px; line-height: 1.5; }
.order-track-items { list-style: none; margin: 0 0 10px; padding: 0; }
.order-track-items li {
    font-size: 0.88rem;
    padding: 6px 0;
    border-bottom: 1px solid var(--djk-border);
}
.order-track-items li:last-child { border-bottom: none; }
.order-track-item-menge { font-weight: 700; color: var(--djk-copper); margin-right: 4px; }
.order-track-item-extras { color: var(--djk-gray); font-size: 0.82rem; }
.order-track-total { font-weight: 800; font-size: 0.9rem; color: var(--djk-white); border-top: 1px solid var(--djk-border); padding-top: 8px; }

/* Detaillierte Käufe: one block per order, items shown as a tally/strichliste */
.kauf-block {
    padding: 12px 0;
    border-bottom: 1px solid var(--djk-border);
}

.kauf-block:last-child { border-bottom: none; }

.kauf-datum {
    font-weight: 700;
    color: var(--djk-yellow);
    margin-bottom: 8px;
    font-size: 0.9rem;
}

.kauf-table { width: 100%; border-collapse: collapse; table-layout: fixed; }

.kauf-table td {
    padding: 4px 0;
    font-size: 0.88rem;
    border: none;
    vertical-align: middle;
}

.kauf-name { color: var(--djk-white); width: 42%; overflow-wrap: break-word; }

.kauf-strichliste-cell {
    width: 43%;
    text-align: right;
}
.kauf-strichliste-cell .strichliste { justify-content: flex-end; }

.kauf-anzahl {
    color: var(--djk-gray);
    font-size: 0.75rem;
    text-align: right;
    width: 40px;
}

/* Bierdeckel: traditional five-bar tally marks */
.strichliste {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}

.strich-gruppe line {
    stroke: var(--djk-yellow);
    stroke-width: 2;
    stroke-linecap: round;
}

/* Bierdeckel: runde Bierdeckel-Karte mit Strichliste "aufgeschrieben" */
.bierdeckel-coaster {
    position: relative;
    width: 100%;
    max-width: 250px;
    aspect-ratio: 1 / 1;
    margin: 6px auto 22px;
    filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.45));
    transform: rotate(-1.2deg);
}
.bierdeckel-coaster-bg { width: 100%; height: 100%; display: block; }
.coaster-ring-outer {
    fill: #ecdcb8;
    stroke: #a9793f;
    stroke-width: 4;
}
.coaster-ring-inner {
    fill: none;
    stroke: #b8965f;
    stroke-width: 1.2;
    stroke-dasharray: 3 3;
}
.coaster-arc-text {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 1.5px;
    fill: #7a5324;
    text-transform: uppercase;
}
.bierdeckel-coaster-content {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 0 40px;
    text-align: center;
}
.bierdeckel-coaster-label {
    font-size: 0.95rem;
    font-weight: 800;
    color: #5c3f1c;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}
.bierdeckel-coaster-strokes {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 8px;
    max-width: 160px;
}
.bierdeckel-coaster-strokes .strich-gruppe line {
    stroke: #6b4423;
}
.bierdeckel-coaster-price {
    font-size: 0.78rem;
    font-weight: 600;
    color: #8a6a3a;
}

.admin-filter-bar {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

/* Filterleiste: dieselben Felder wie überall sonst (siehe "Bedienelemente" weiter unten) —
   weißer Grund, damit ein Eingabefeld auf einen Blick als solches lesbar ist. Vorher trugen
   diese beiden als einzige einen grauen Hintergrund und sahen dadurch abgeschaltet aus. */
.admin-filter-bar .input-icon input {
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    color: var(--djk-white);
    width: 100%;
    padding: 12px 14px 12px 42px;
    border-radius: var(--feld-radius);
}

/* Nur noch die Mindestbreite — Grund, Rand, Ecken und Pfeil stehen in der Grundregel `select`. */
.admin-filter-bar select { min-width: 180px; }

.admin-mini-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}

.admin-mini-card {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 10px;
    text-align: center;
    display: flex;
    flex-direction: column;
    height: 100%;
}

.admin-mini-card .product-tile-photo { border-radius: 5px; height: 150px; margin-bottom: 6px; }
.admin-mini-card h3 {
    font-size: 0.8rem;
    margin: 0 0 4px;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    line-height: 1.25;
    min-height: 2.5em;
}
.admin-mini-card .hint { font-size: 0.68rem; margin-bottom: 4px; }

.admin-mini-card-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
    margin-top: auto;
    padding-top: 8px;
}

.admin-mini-card-actions > * { margin: 0; min-width: 0; }
.admin-mini-card-actions form { display: flex; }
.admin-mini-card-actions .btn { width: 100%; padding: 6px 4px; font-size: 0.7rem; }

/* Drei Bedienelemente statt zwei: der schmale Schalter vorn bekommt nur seine eigene Breite,
   die beiden Knöpfe teilen sich den Rest wie bisher. Bewusst als eigene Klasse statt :has() —
   die Zeile soll auch dort stimmen, wo :has() noch nicht greift. */
.admin-mini-card-actions-drei { grid-template-columns: auto 1fr 1fr; }

/* Der Mengenknopf der Kasse ("2×") als Schalter in der Extra-Liste. Hell = das Extra darf
   mehrfach auf ein Gericht, blass = nur einmal. Er sieht aus wie sein Gegenstück an der
   Kasse (.extra-menge-btn), damit man ihn dort wiedererkennt. */
.extra-menge-schalter {
    padding: 6px 9px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-gray);
    font-size: 0.7rem;
    font-weight: 800;
    cursor: pointer;
    white-space: nowrap;
}
.extra-menge-schalter.active {
    border-color: var(--djk-yellow);
    color: var(--djk-yellow);
    background: rgba(59, 130, 246, 0.12);
}

.rechnung-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    cursor: pointer;
    font-size: 0.85rem;
}

.rechnung-row:has(.rechnung-check:checked) { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.08); }

.admin-chip-remove {
    background: none;
    border: none;
    color: var(--djk-danger);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
}

/* Die Größen (Verwaltung → Produkte → Größen). Eine Größe ist ein Wort ("30 cm"), deshalb
   nebeneinander statt untereinander. Stand bis zum 10.08.2026 als `style="…"` in produkte.php —
   dieselben Werte, nur jetzt erreichbar (siehe „TABELLEN: ZWEI ANSICHTEN"). */
.groessen-liste { display: flex; gap: 8px; flex-wrap: wrap; }
.groessen-chip {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    padding: 6px 6px 6px 14px;
}
.groessen-chip-name {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--djk-white);
    text-decoration: none;
}

.admin-produkt-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 12px;
}

.admin-produkt-card {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 10px;
    text-align: center;
    transition: border-color var(--transition), transform var(--transition);
}

.admin-produkt-card:hover { border-color: var(--djk-yellow); transform: translateY(-2px); }
.admin-produkt-card .product-tile-photo { border-radius: 5px; margin-bottom: 8px; }
.admin-produkt-card h3 {
    font-size: 0.82rem;
    margin: 0 0 4px;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    min-height: 2.5em;
}
.admin-produkt-nummer { color: var(--djk-gray); font-weight: 600; }
.admin-produkt-price { color: var(--djk-yellow); font-weight: 800; margin: 6px 0; }

@media (max-width: 640px) {
    .admin-produkt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
    .admin-mini-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .admin-produkt-card { padding: 6px; min-width: 0; }
    .admin-produkt-card h3 { font-size: 0.68rem; }
    .admin-produkt-price { font-size: 0.72rem; }
    .admin-mini-card-actions .btn, .admin-produkt-card .admin-mini-card-actions .btn { font-size: 0.62rem; padding: 5px 2px; }
    .admin-filter-bar select { min-width: 0; width: 100%; }
}

.form-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
    margin-bottom: 20px;
}

.form-grid .full { grid-column: 1 / -1; }

.field { margin-bottom: 16px; }
/* Innerhalb eines .form-grid übernimmt bereits dessen gap den Abstand zwischen Feldern —
   die eigene .field-margin würde diesen Abstand sonst verdoppeln. */
.form-grid .field { margin-bottom: 0; }

.field label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--djk-yellow);
    margin-bottom: 6px;
}

/* source/style_css/060_form_controls.css - style.css part 7 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==========================================================================================
   BEDIENELEMENTE — ein Satz Felder, Auswahllisten, Kästchen und Schalter fürs ganze Projekt.

   Vorher hatte fast jede Seite ihre eigene Fassung: mal grauer, mal weißer Grund, mal ein
   goldener Pfeil aus dem alten dunklen Farbschema, mal gar keiner. Ab hier gilt EIN Satz
   Merkmale, und alles andere leitet sich davon ab:

     weißer Grund · 1px Rand · 5px Ecken · volle Breite · gleicher Fokusring

   Die vier Werte stehen als Variablen, damit ein späterer Wechsel (etwa hellere Ränder) eine
   Änderung an einer Stelle bleibt und nicht wieder durch fünfzig Regeln wandert.
   ========================================================================================== */
:root {
    --feld-grund: var(--djk-black-card);   /* im hellen Schema: weiß */
    --feld-rand: #929292;
    --feld-radius: 5px;
    /* Der Pfeil der Auswahllisten. Als Variable, weil ihn drei Regeln brauchen; in der Farbe
       des Fließtexts statt im früheren Gold — das stammte aus dem dunklen Schema und stach
       auf hellem Grund als einziges Element heraus. */
    --feld-pfeil: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}

/* JEDE Auswahlliste im Projekt, nicht nur die in einem `.field`.
   Vorher galt der Satz oben nur innerhalb von `.field`; überall sonst entschied der Zufall —
   fünf verschiedene Fassungen in style.css und neun weitere direkt im `style="…"` der Seite.
   Die letzteren alle mit `background: var(--djk-black-soft)`: grauer Grund, und weil
   `background` eine Kurzform ist, nahm sie das Pfeil-Bild gleich mit (Falle 15).
   Was hier NICHT steht, ist `width` — eine Auswahlliste in einer Werkzeugleiste soll ihre
   natürliche Breite behalten; `.field select` weiter unten setzt volle Breite. */
select {
    padding: 12px 38px 12px 14px;
    background-color: var(--feld-grund);
    background-image: var(--feld-pfeil);
    background-repeat: no-repeat;
    background-position: right 12px center;
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-family: inherit;
    font-size: 0.95rem;
    max-width: 100%;
    cursor: pointer;
    transition: border-color var(--transition), box-shadow var(--transition);
    appearance: none;
    -webkit-appearance: none;
}
select:focus {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}

/* JEDES Eingabefeld im Projekt, nicht nur die in einem `.field`.
   Dieselbe Geschichte wie bei den Auswahllisten eine Regel weiter oben, nur später bemerkt:
   der Satz galt allein innerhalb von `.field`. Überall sonst — in der Massenleiste, in
   Werkzeugleisten, in Formularen ohne `.field` — stand das nackte Feld des Browsers: andere
   Höhe, anderer Rand, andere Ecken als die Auswahlliste direkt daneben. Der Wirt hat es genau
   so beschrieben: „нет стандарта для инпутов".

   Was hier NICHT steht, ist `width` — ein Feld in einer Werkzeugleiste soll seine Breite über
   `size` behalten; `.field` weiter unten setzt volle Breite.

   Nicht erfasst sind Kästchen, Radioknöpfe, Farbfelder, Schieber, Dateiwahl und Knöpfe: die
   sind keine Textfelder und haben ihre eigenen Regeln. `input:not([type])` gehört dazu, weil
   ein Feld ohne Typ ein Textfeld ist. */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
input[type="date"],
input[type="time"],
/* Monat, Woche, Datum+Uhrzeit (19.09.2026): sie fehlten hier und standen im Rahmen des Browsers da —
   2 px, eingedrueckt, schwarz (Monatsfeld der Uebergabe, eingekringelt vom Wirt). */
input[type="month"],
input[type="week"],
input[type="datetime-local"],
input[type="number"],
input[type="search"],
input[type="url"],
input:not([type]),
textarea {
    padding: 12px 14px;
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-family: inherit;
    font-size: 0.95rem;
    max-width: 100%;
    transition: border-color var(--transition), box-shadow var(--transition);
    appearance: none;
    -webkit-appearance: none;
}
/* Derselbe Fokusring wie bei den Auswahllisten — ein Feld soll nicht danach aussehen, wo es
   zufällig steht, sondern danach, was es ist. */
input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="tel"]:focus,
input[type="date"]:focus,
input[type="time"]:focus,
input[type="month"]:focus,
input[type="week"]:focus,
input[type="datetime-local"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
input:not([type]):focus,
textarea:focus {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}

.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="tel"],
.field input[type="date"],
.field input[type="time"],
.field input[type="number"],
.field input[type="search"],
.field input[type="url"],
.field select,
.field textarea {
    width: 100%;
    padding: 12px 14px;
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 0.95rem;
    transition: border-color var(--transition), box-shadow var(--transition);
    appearance: none;
    -webkit-appearance: none;
}

.field select {
    background-image: var(--feld-pfeil);
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 38px;
    cursor: pointer;
}

/* Kästchen und Radioknöpfe: die vom Browser mitgelieferten sehen auf jedem System anders aus
   und lassen sich nicht vergrößern — mit dem Finger trifft man sie schlecht. Deshalb eigene,
   in derselben Machart wie die Felder.

   `:not(.visually-hidden)` ist kein Schönheitsfehler, sondern Bedingung: die Chips und die
   Schiebeschalter blenden ihr Kästchen aus und zeichnen selbst etwas anderes. Ohne diesen
   Ausschluss holte diese Regel sie zurück auf den Schirm. Die Schiebeschalter (.toggle-switch)
   sind zusätzlich dadurch geschützt, dass ihre eigene Regel weiter unten steht und bei
   gleicher Gewichtung gewinnt. */
input[type="checkbox"]:not(.visually-hidden),
input[type="radio"]:not(.visually-hidden) {
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    width: 20px;
    height: 20px;
    margin: 0;
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), box-shadow var(--transition);
}
input[type="radio"]:not(.visually-hidden) { border-radius: 50%; }

input[type="checkbox"]:not(.visually-hidden):checked,
input[type="radio"]:not(.visually-hidden):checked {
    background-color: var(--djk-yellow);
    border-color: var(--djk-yellow);
}
/* Der Haken als Bild statt als ::before — ein Pseudo-Element kann ein <input> nicht haben. */
input[type="checkbox"]:not(.visually-hidden):checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px 14px;
}
input[type="radio"]:not(.visually-hidden):checked {
    /* Punkt in der Mitte, gezeichnet mit einem Innenschatten — spart ein zweites Bild. */
    box-shadow: inset 0 0 0 4px var(--feld-grund);
}
input[type="checkbox"]:not(.visually-hidden):disabled,
input[type="radio"]:not(.visually-hidden):disabled { opacity: .45; cursor: not-allowed; }

.field input[type="number"] {
    -moz-appearance: textfield;
}
.field input[type="number"]::-webkit-outer-spin-button,
.field input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Ein Fokusring für alle Bedienelemente — auch für die Filterleiste und die Kästchen, die
   vorher gar keinen hatten. Wer mit der Tastatur bedient, muss sehen, wo er steht. */
.field input:focus,
.field select:focus,
.field textarea:focus,
.admin-filter-bar input:focus,
.admin-filter-bar select:focus,
input[type="checkbox"]:not(.visually-hidden):focus-visible,
input[type="radio"]:not(.visually-hidden):focus-visible {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}

/* Pill-Toggle-Switch (statt Ja/Nein-Select oder einfacher Checkbox) */
/* Selektor "label.toggle-switch" statt ".toggle-switch": ".field label" (Spezifität 0,1,1) würde
   sonst bei gleicher Spezifität wie ".toggle-switch" (0,1,0) gewinnen und "display:block" erzwingen,
   wodurch die Flex-Anordnung zusammenbricht und der Schalter-Kreis den Text überlappt. */
label.toggle-switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; margin-bottom: 0; font-weight: 400; color: inherit; }
.toggle-switch input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-switch-track {
    position: relative;
    flex-shrink: 0;
    width: 42px;
    height: 24px;
    background: var(--djk-border);
    border-radius: 999px;
    transition: background var(--transition);
}
.toggle-switch-track::before {
    content: '';
    position: absolute;
    left: 3px;
    top: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    transition: transform var(--transition);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.toggle-switch input:checked + .toggle-switch-track { background: var(--djk-success); }
.toggle-switch input:checked + .toggle-switch-track::before { transform: translateX(18px); }
.toggle-switch input:focus-visible + .toggle-switch-track { outline: 2px solid var(--djk-yellow); outline-offset: 2px; }
.toggle-switch-label { font-size: 0.85rem; color: var(--djk-white); }
.field > .toggle-switch { margin-top: 4px; }

/* Collapsible Formular-Sektion (z. B. "Abweicht von Kategorie" im Produkt-Formular) —
   native <details>/<summary> statt eigenem JS-Zustand, da einfach robust und ohne
   zusätzliche Skript-Logik auskommt. */
.admin-collapsible {
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: rgba(15, 23, 42, 0.025);
}
.admin-collapsible summary {
    list-style: none;
    cursor: pointer;
    padding: 12px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--djk-yellow);
    user-select: none;
}
.admin-collapsible summary::-webkit-details-marker { display: none; }
.admin-collapsible summary .admin-collapsible-hint {
    font-weight: 400;
    font-size: 0.8rem;
    color: var(--djk-gray);
    margin-right: auto;
}
.admin-collapsible summary .admin-collapsible-chevron {
    flex-shrink: 0;
    color: var(--djk-gray);
    transition: transform var(--transition);
}
.admin-collapsible[open] summary .admin-collapsible-chevron { transform: rotate(180deg); }
.admin-collapsible-body {
    padding: 4px 14px 14px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 14px 20px;
}
.admin-collapsible-body > .field { margin-bottom: 0; }
.admin-collapsible-body > .full,
.admin-collapsible-body > .feld-voll { grid-column: 1 / -1; }

/* Ein Klappblock, dessen Inhalt untereinander läuft statt in Spalten: Schalterzeilen,
   Hinweise und Auswahllisten gemischt. Das Raster oben passt für Felder gleicher Art —
   Schalterzeilen zerfielen darin in halbe Spalten. */
.admin-collapsible.klapp-block { margin-bottom: 10px; }
.admin-collapsible.klapp-block > .admin-collapsible-body { display: block; }

/* Kopf eines Formulars: Foto und der eine Name daneben, danach volle Breite.
   Vorher lief die ganze rechte Spalte neben dem Foto — unter dem Bild blieb eine leere
   Spalte über die ganze Formularhöhe stehen (der Wirt: „очень много пустого места"). */
.form-kopf {
    display: flex;
    gap: 14px;
    align-items: flex-end;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.form-kopf-feld { flex: 1 1 200px; min-width: 0; }

/* Statische Gruppierungs-Box für zusammengehörige Formularfelder (z. B. Mitarbeiter-
   Einstellungen: "Kasse-Einstellungen" vs. "Reservierungen" vs. "Abteilungen") — wie
   .admin-collapsible, aber immer offen, ohne <details>/<summary>. */
.admin-form-section {
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: rgba(15, 23, 42, 0.025);
    padding: 14px;
    margin-bottom: 14px;
}
.admin-form-section:last-of-type { margin-bottom: 0; }
.admin-form-section > .admin-form-section-title {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--djk-yellow);
    margin-bottom: 4px;
}

/* ---------- Verwaltung: einheitliche Formular-Bausteine ----------
   Ersetzt die früher überall einzeln gesetzten style="display:flex; …"-Angaben. Steht alles an
   einer Stelle, sehen Kopfzeilen, Karten und Feldraster auf jeder Verwaltungsseite gleich aus. */
.admin-seiten-kopf {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
/*
 * Zeichen und Wort sind zwei Kinder: ohne flex faellt der Leerraum zwischen einem
 * inline-SVG und dem Text weg, und es steht „(Drucker)Drucken" da.
 *
 * NACHGEBESSERT 26.08.2026: die Regel galt nur fuer `> h2`, also fuer das DIREKTE Kind. Seit
 * ueber der Ueberschrift ein Pfad steht („Statistik & Kontrolle"), steckt die Ueberschrift
 * in einem eigenen `div` — und auf allen 15 Seiten mit Pfad klebte das Zeichen wieder am
 * Wort. Der Wirt: *„на всех страницах одно и то же — значок и текст прилипли"*.
 * Jetzt als Nachfahre: in einer Seitenkopfzeile ist jedes h2 die Ueberschrift.
 */
.admin-seiten-kopf h2 {
    margin: 0;
    text-align: left;
    display: flex;
    align-items: center;
    gap: 10px;
}
.admin-seiten-kopf-zwischen { margin-top: 28px; }
/* Das Zeichen soll auf der Schriftlinie sitzen, nicht daneben schweben: ein festes Mass,
   damit ein 24px-SVG und ein Font-Awesome-Zeichen gleich hoch sind. */
.admin-seiten-kopf h2 > .icon { flex: 0 0 auto; }
/* Das eigene SVG bringt width="24" mit — neben einer 22px-Ueberschrift wirkt es zu gross.
   Das Font-Awesome-Zeichen bekommt KEINE Breite: es ist eine Schrift, und jede Breite
   schnitte breitere Zeichen (fa-sliders-h ist 1,125 em) am gap ab. */
.admin-seiten-kopf h2 > svg.icon { width: 1.05em; height: 1.05em; }
.admin-seiten-kopf h2 > i.icon { font-size: 0.95em; line-height: 1; }

/* source/style_css/070_collapsed_filter.css - style.css part 8 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==========================================================================
   DER ZUGEKLAPPTE FILTER (26.08.2026) — filter_klapp() in includes/functions.php
   ========================================================================== */
.filter-klapp > summary {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    list-style: none;                 /* das eigene Dreieck des Browsers stoert das Bild */
    -webkit-user-select: none;
    user-select: none;
    font-weight: 700;
    /* Die Farben kommen aus dem Satz des Hauses, nicht als feste Werte: im dunklen
       Erscheinungsbild wird derselbe Satz getauscht (siehe body.thema-dunkel). Ein hart
       geschriebenes #0f172a waere dort schwarz auf schwarz. */
    color: var(--djk-white);
}
.filter-klapp > summary::-webkit-details-marker { display: none; }
.filter-klapp > summary:focus-visible { outline: 2px solid var(--djk-yellow); outline-offset: 3px; border-radius: 8px; }
.filter-klapp-wort { font-size: 0.95rem; }
/* Die Zahl sagt, dass die Liste gerade beschnitten ist — zugeklappt darf nie versteckt heissen. */
.filter-klapp-zahl {
    min-width: 20px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--djk-yellow);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 800;
    text-align: center;
}
.filter-klapp-still { font-size: 0.78rem; font-weight: 600; color: var(--djk-gray); }
.filter-klapp-pfeil { margin-left: auto; display: inline-flex; transition: transform .18s ease; }
.filter-klapp-pfeil .icon { width: 18px; height: 18px; }
.filter-klapp[open] > summary > .filter-klapp-pfeil { transform: rotate(180deg); }
.filter-klapp[open] > summary { margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--djk-border); }

.admin-karte { margin-bottom: 18px; }
/*
 * 780 px war eine Breite aus der Zeit, als die Verwaltung auf dem Telefon entstand. Auf einem
 * Bildschirm im Büro stand die Karte danach als schmale Säule in der Mitte, rechts eine
 * handbreite leere Fläche — der Wirt hat sie angestrichen. 1180 px ist immer noch eine LESBARE
 * Zeile (darüber wandert das Auge beim Zurückspringen zu weit), nutzt aber den Platz.
 */
.admin-karte-breit { max-width: 1180px; }
.admin-karte-titel { margin: 0 0 4px; font-size: 1.05rem; }
.admin-karte-text { margin: 0 0 14px; }
.admin-karte-alarm { border-left: 5px solid var(--djk-danger); }

/* Feldraster: so viele Spalten wie hineinpassen, jede mindestens 220px breit. Ein eigenes
   Raster statt .form-grid, weil dieses bewusst einspaltig bleibt (Anmelde-Formulare). */
.admin-feld-raster {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px 16px;
}
/* Genau zwei Spalten statt "so viele wie passen": nur so bleiben bewusst gebildete Paare
   (Straße/Hausnummer, PLZ/Ort) auch Paare. Bei auto-fit springt die Spaltenzahl mit der Breite,
   und am Ende steht ein einzelnes Feld mit einer leeren Lücke daneben. Bei ungerader Feldzahl
   bekommt das letzte Feld ".feld-voll" — dann ist die Zeile ebenfalls gefüllt. */
.admin-feld-raster-paare { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 560px) {
    .admin-feld-raster-paare { grid-template-columns: 1fr; }
}

.admin-feld-raster > .field { margin-bottom: 0; }
/* ".full" steht in älteren Formularen für dieselbe Sache wie ".feld-voll" — beide gelten hier. */
.admin-feld-raster > .feld-voll,
.admin-feld-raster > .full,
.field.feld-voll { grid-column: 1 / -1; }
.admin-form-section > .field.feld-voll { margin-bottom: 14px; }

/* Kopfzeile mit Pfad: darüber steht der Bereich, darunter der Reiter, auf dem man wirklich ist. */
.admin-seiten-kopf-eng { margin-bottom: 4px; align-items: flex-end; }
.admin-pfad {
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--djk-gray);
    margin-bottom: 2px;
}
.admin-kopf-zahl {
    font-size: 0.82rem;
    color: var(--djk-gray);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    padding: 6px 14px;
    text-decoration: none;
    white-space: nowrap;
}
.admin-kopf-zahl strong { color: var(--djk-white); }
.admin-kopf-zahl:hover { border-color: var(--djk-yellow); color: var(--djk-yellow-dark); }

/* Ein Schalter mit Beschriftung als eigene Zeile — statt jedes Mal ein eigenes Flex-Gerüst. */
.toggle-switch.schalter-zeile {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    margin-bottom: 10px;
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    background: var(--djk-black-soft);
}
.toggle-switch.schalter-zeile .toggle-switch-label { display: flex; flex-direction: column; gap: 2px; }
.toggle-switch.schalter-zeile .hint { margin: 0; }

/* Abgeschaltete Feldgruppe (z. B. Lieferzone ohne "Lieferung anbieten"). */
.feld-gruppe-aus { opacity: .45; pointer-events: none; }

/* Knopfzeile am Ende eines Formulars — nie mehr am Text kleben. */
.form-aktionen {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 16px;
}

/* Kompakte Mehrfachauswahl per Chip statt eines Toggle-Switches pro Option (z. B.
   Kategorien-Zuordnung bei Extras/Größen) — spart bei vielen Optionen deutlich Platz
   gegenüber einer vollbreiten Zeile pro Schalter. */
.admin-chip-select { display: flex; flex-wrap: wrap; gap: 8px; }
.admin-chip-select label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    font-size: 0.85rem;
    cursor: pointer;
    user-select: none;
    transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.admin-chip-select input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.admin-chip-select label:has(input:checked) {
    border-color: var(--djk-yellow);
    background: rgba(59, 130, 246, 0.12);
    color: var(--djk-yellow);
}
.admin-chip-select label:has(input:focus-visible) { outline: 2px solid var(--djk-yellow); outline-offset: 2px; }

/* Kategorie-Chip mit angehängtem Standard-Stern (siehe Extra-Formular: "standardmäßig in
   der Kasse ausgewählt" je Präfix+Kategorie) — Stern sitzt direkt am Chip, ohne eigenen
   Zwischenraum, wirkt so wie ein Anhängsel desselben Chips. Links davon optional ein
   Erzwingen-Schloss (siehe .chip-erzwungen-toggle) im selben Anhängsel-Stil. */
/*
 * EIN Chip, nicht drei aneinandergeklebte Kästchen.
 *
 * Vorher trug jeder Teil seinen eigenen Rahmen, und der Stern hatte einen fest getippten roten
 * Grund (`#f9000099`) — daher die rosa Klötze neben jedem Namen. Drei Rahmen nebeneinander
 * lesen sich als drei Dinge, obwohl es eine Angabe ist.
 *
 * Jetzt: der Rahmen gehört der HÜLLE, die Zeichen darin sind rahmenlos und im Ruhezustand blass.
 * Wer eingeschaltet ist, färbt sich — Stern bernstein (er ist eine Auszeichnung, keine
 * Zustandsangabe), Schloss und Textzeichen in der Menüfarbe.
 */
/* Ein Extra, das an der Kategorie mit dem Schloss festgemacht ist: es steht hier fest und
   laesst sich nur beim Extra selbst loesen. Sichtbar gedaempft statt heimlich wirkungslos. */
.admin-chip-gesperrt { opacity: .75; }
.admin-chip-gesperrt label { cursor: not-allowed; }
.admin-chip-gesperrt .icon { width: 14px; height: 14px; vertical-align: -2px; margin-left: 4px; }

.admin-chip-with-default {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--feld-rand);
    border-radius: 999px;
    background: var(--feld-grund);
    overflow: hidden;
    transition: border-color var(--transition), background var(--transition);
}
.admin-chip-with-default:has(.chip-kat-check:checked),
.admin-chip-with-default:has(.chip-extra-check:checked) {
    border-color: var(--djk-yellow);
    background: rgba(59, 130, 246, 0.10);
}
.admin-chip-with-default label {
    border: 0;
    border-radius: 0;
    background: none;
    padding: 7px 13px;
}
.admin-chip-with-default label:has(input:checked) {
    background: none;
    color: var(--djk-yellow);
    font-weight: 700;
}

/* Die drei Zeichen im Chip — gleiche Machart, damit keines wichtiger aussieht als es ist. */
.chip-default-star,
.admin-chip-with-default .chip-erzwungen-toggle,
.admin-chip-with-default .chip-text-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 9px;
    border: 0;
    background: none;
    /* Aus: da, aber leise — man soll den Namen lesen, nicht die Zeichen. */
    color: rgba(15, 23, 42, .22);
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    height: auto;
    transition: color var(--transition);
}
.chip-default-star:disabled,
.admin-chip-with-default .chip-erzwungen-toggle:disabled,
.admin-chip-with-default .chip-text-toggle:disabled { opacity: .35; cursor: not-allowed; }
.chip-default-star:hover:not(:disabled),
.admin-chip-with-default .chip-erzwungen-toggle:hover:not(:disabled),
.admin-chip-with-default .chip-text-toggle:hover:not(:disabled) { color: var(--djk-gray); }
.chip-default-star.active { color: #f59e0b; background: none; }
.admin-chip-with-default .chip-erzwungen-toggle.active,
.admin-chip-with-default .chip-text-toggle.active {
    color: var(--djk-yellow);
    background: none;
    border: 0;
}

/* Erzwingen-Schloss: macht ein Extra für diese Kategorie+Präfix unabänderlich — es bleibt
   angeboten, selbst wenn ein Produkt seine Extras eigens übersteuert (siehe
   resolve_produkt_extras() in includes/functions.php). Eigene Farbe (Blau statt Gelb), damit
   es sich klar vom Standard-Stern unterscheidet. */
.chip-erzwungen-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 10px;
    border: 1px solid var(--djk-border);
    border-right: none;
    background: transparent;
    color: var(--djk-gray);
    cursor: pointer;
    line-height: 1;
    height: 37px;
}
.chip-erzwungen-toggle .icon { width: 13px; height: 13px; }
.chip-erzwungen-toggle:disabled { opacity: 0.25; cursor: not-allowed; }
.chip-erzwungen-toggle.active { color: var(--djk-blue-light); border-color: var(--djk-blue); background: rgba(139, 92, 246, 0.14); }

/* Reiter-Umschalter statt gestapelter Blöcke, wenn es pro Option (z. B. pro Präfix) einen
   eigenen Kategorien-Chip-Select braucht — sonst wird das Formular bei vielen Optionen sehr lang. */
.praefix-kat-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.praefix-kat-tab {
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
}
.praefix-kat-tab.active { border-color: var(--djk-yellow); color: var(--djk-yellow); background: rgba(59, 130, 246, 0.12); }
.praefix-kat-tab-count { opacity: 0.75; font-weight: 400; }

/* Formular-Unterüberschrift zur reinen Gruppierung von Feldern innerhalb eines
   Modals (z. B. "Anzeige" vs. "Küchen-Verhalten") — kein neues Feld, keine neue
   Seite, nur visuelle Struktur. */
.admin-form-subheading {
    grid-column: 1 / -1;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--djk-gray);
    margin: 6px 0 -4px;
    padding-top: 10px;
    border-top: 1px solid var(--djk-border);
}
.admin-form-subheading:first-child { margin: 0 0 5px 0; padding-top: 0; border-top: none; }

/* Stop the browser's autofill from painting inputs white */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--djk-white) !important;
    -webkit-box-shadow: 0 0 0 1000px var(--djk-black-soft) inset !important;
    box-shadow: 0 0 0 1000px var(--djk-black-soft) inset !important;
    caret-color: var(--djk-white);
    border-color: var(--djk-border) !important;
    transition: background-color 9999s ease-in-out 0s, color 9999s ease-in-out 0s;
}

input:-webkit-autofill:focus {
    border-color: var(--djk-yellow) !important;
}

.admin-toolbar input:-webkit-autofill,
.admin-toolbar select:-webkit-autofill {
    -webkit-box-shadow: 0 0 0 1000px var(--djk-black-card) inset !important;
    box-shadow: 0 0 0 1000px var(--djk-black-card) inset !important;
}

.field .hint {
    font-size: 0.78rem;
    color: var(--djk-black);
    margin-top: 4px;
}

.field .error {
    font-size: 0.8rem;
    color: var(--djk-danger);
    margin-top: 4px;
}

.checkbox-row {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 14px;
}

.checkbox-row input { width: 18px; height: 18px; accent-color: var(--djk-yellow); }

.category-select {
    display: none;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-top: 12px;
}

.category-select.active { display: grid; }

@media (max-width: 640px) {
    .category-select { grid-template-columns: repeat(2, 1fr); }
}

.category-option {
    position: relative;
}

.category-option input {
    position: absolute;
    opacity: 0;
    inset: 0;
    cursor: pointer;
}

.category-option label {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 14px 8px;
    border: 2px solid var(--djk-border);
    border-radius: 5px;
    text-align: center;
    font-weight: 600;
    font-size: 0.82rem;
    color: var(--djk-white);
    cursor: pointer;
    transition: all var(--transition);
}

.category-option label .icon { width: 22px; height: 22px; }

.category-option input:checked + label {
    border-color: var(--djk-yellow);
    background: rgba(59, 130, 246, 0.12);
    color: var(--djk-yellow);
}

/* Address autocomplete */
.address-autocomplete { position: relative; }

.address-results {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-yellow);
    border-radius: 5px;
    max-height: 240px;
    overflow-y: auto;
    z-index: 20;
    display: none;
    box-shadow: var(--shadow);
}

.address-results.active { display: block; }

/* source/style_css/075_collapsed_filter_continued.css - style.css: collapsed filter continued, part 9 of 78 (built by werkzeuge/parts_build.php) */
.address-results div {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 0.88rem;
    border-bottom: 1px solid var(--djk-border);
}

.address-results div:last-child { border-bottom: none; }
.address-results div:hover { background: rgba(59, 130, 246, 0.12); }

/* Photo upload */
.photo-upload-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
}

.photo-circle-wrap {
    position: relative;
    display: inline-block;
}

.photo-circle {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    background: var(--djk-black-soft);
    border: 2px dashed var(--djk-border);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
    transition: border-color var(--transition), transform var(--transition);
}

.photo-circle:hover,
.photo-circle:focus-visible {
    border-color: var(--djk-yellow);
    transform: scale(1.03);
}

.photo-circle img { width: 100%; height: 100%; object-fit: cover; }

.photo-circle-icon { color: var(--djk-gray); display: flex; }
.photo-circle-icon .icon { width: 34px; height: 34px; }

/* source/style_css/080_modal_head_staff_product_forms.css - style.css part 10 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
.photo-circle-initials {
    font-size: 2.1rem;
    font-weight: 800;
    color: var(--djk-yellow);
    letter-spacing: 1px;
}

.photo-badge {
    position: absolute;
    bottom: 2px;
    right: 2px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--djk-yellow);
    color: var(--djk-black);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--djk-black-card);
    pointer-events: none;
}

.photo-badge .icon { width: 16px; height: 16px; }

.photo-square-wrap { width: 140px; margin: 0 auto; }

.photo-square {
    width: 140px;
    height: 140px;
    border-radius: 5px;
    background: var(--djk-black-soft);
    border: 2px dashed var(--djk-border);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
    transition: border-color var(--transition);
}

.photo-square:hover, .photo-square:focus-visible { border-color: var(--djk-yellow); }
.photo-square img { width: 100%; height: 100%; object-fit: cover; }
.photo-square-icon { color: var(--djk-gray); display: flex; }
.photo-square-icon .icon { width: 32px; height: 32px; }

.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* SVG icon base */
.icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    stroke: currentColor;
    fill: none;
}

.icon-sm { width: 14px; height: 14px; }
.icon-md { width: 22px; height: 22px; }
.icon-lg { width: 28px; height: 28px; }
.icon-xl { width: 40px; height: 40px; }

/* Input icons */
.input-icon { position: relative; }

.input-icon-glyph {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    color: var(--djk-gray);
    opacity: 0.9;
    pointer-events: none;
    line-height: 1;
}

.field .input-icon input,
.field .input-icon select {
    padding-left: 42px;
}

.input-icon.has-toggle input { padding-right: 42px; }

.password-toggle {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    padding: 8px;
    line-height: 1;
    color: var(--djk-gray);
    opacity: 0.8;
    transition: opacity var(--transition), color var(--transition);
}

.password-toggle:hover { opacity: 1; color: var(--djk-yellow); }

/* Datums- und Zeitfelder.
   Vorher standen sie in 1,3rem fett mit 54px Höhe und einem gelb eingefärbten Kalendersymbol —
   damit sprangen sie aus jeder Formularzeile heraus, und der leere Platzhalter "tt.mm.jjjj" las
   sich wie ein echter Wert. Jetzt sind sie genauso groß wie jedes andere Feld daneben; nur die
   Ziffern laufen tabellarisch, damit die Breite beim Tippen nicht springt. */
.field input[type="date"],
.field input[type="time"] {
    font-family: inherit;
    font-variant-numeric: tabular-nums;
    letter-spacing: .01em;
    /* Die eingebaute Datums-Anzeige baut etwas höher als reiner Text — mit diesen Werten steht
       das Feld exakt so hoch wie ein Textfeld daneben (nachgemessen: 43,6 zu 43,2 px). */
    padding-top: 11px;
    padding-bottom: 11px;
    line-height: 1.15;
}
.field input[type="date"]::-webkit-datetime-edit,
.field input[type="time"]::-webkit-datetime-edit { padding: 0; }

/* Solange nichts eingetragen ist, steht der Platzhalter grau wie ein echter Platzhalter.
   Greift bei Pflichtfeldern (leer = :invalid); optionale Felder bleiben unauffällig normal. */
.field input[type="date"]:invalid::-webkit-datetime-edit,
.field input[type="time"]:invalid::-webkit-datetime-edit { color: var(--djk-gray); }

.field input[type="date"]::-webkit-datetime-edit-text,
.field input[type="date"]::-webkit-datetime-edit-day-field,
.field input[type="date"]::-webkit-datetime-edit-month-field,
.field input[type="date"]::-webkit-datetime-edit-year-field,
.field input[type="time"]::-webkit-datetime-edit-text,
.field input[type="time"]::-webkit-datetime-edit-hour-field,
.field input[type="time"]::-webkit-datetime-edit-minute-field {
    color: inherit;
}
.field input[type="date"]::-webkit-datetime-edit-day-field:focus,
.field input[type="date"]::-webkit-datetime-edit-month-field:focus,
.field input[type="date"]::-webkit-datetime-edit-year-field:focus,
.field input[type="time"]::-webkit-datetime-edit-hour-field:focus,
.field input[type="time"]::-webkit-datetime-edit-minute-field:focus {
    background: var(--djk-sidebar-bg-active);
    color: var(--djk-yellow-dark);
    border-radius: 3px;
    outline: none;
}

/* Eigenes Kalendersymbol: das eingebaute lässt sich nur über Filter einfärben (daher vorher
   das Gelb) — als Hintergrundbild ist es sauber grau und passt zur restlichen Symbolik. */
.field input[type="date"]::-webkit-calendar-picker-indicator,
.field input[type="time"]::-webkit-calendar-picker-indicator {
    width: 20px;
    height: 20px;
    margin: 0;
    padding: 0;
    cursor: pointer;
    opacity: .6;
    background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E") center / 20px no-repeat;
    transition: opacity var(--transition);
}
.field input[type="date"]:hover::-webkit-calendar-picker-indicator,
.field input[type="time"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }

/* ---------- Modal-Kopf und Personal-/Produktformulare ---------- */
.admin-modal-kopf,
.mitarbeiter-modal-kopf { margin-bottom: 14px; }
.admin-modal-kopf h2,
.admin-modal-kopf h3,
.mitarbeiter-modal-kopf h3 { margin: 0 0 2px; }
.admin-modal-kopf .hint,
.mitarbeiter-modal-kopf .hint { display: block; }

/* Produkt-Karte: Foto links, daneben Name/Nummer/Preis/Kategorie. Die kurzen Felder stehen
   nebeneinander — vollbreite Zeilen für eine dreistellige Nummer sahen verloren aus.
   (Die Breite des Kastens steht bei .modal-box-wide — dort, wo .modal-box selbst definiert ist,
   sonst gewinnt dessen späteres max-width bei gleicher Spezifität.) */
.produkt-kopf {
    display: grid;
    grid-template-columns: 168px minmax(0, 1fr);
    gap: 16px 22px;
    align-items: start;
    margin-bottom: 18px;
    padding-bottom: 18px;
    border-bottom: 1px solid var(--djk-border);
}
.produkt-kopf-foto { margin-bottom: 0; }
.produkt-kopf-foto .photo-square-wrap,
.produkt-kopf-foto .photo-square { width: 168px; }
.produkt-kopf-foto .photo-square { height: 168px; }
.produkt-kopf-foto .hint { display: block; margin-top: 8px; }
.produkt-kopf-felder {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px 16px;
}
.produkt-kopf-felder > .field { margin-bottom: 0; }
.produkt-kopf-felder > .feld-voll { grid-column: 1 / -1; }
/*
 * Alles UNTER der ersten Zeile geht ueber die ganze Breite.
 *
 * Das Raster hat zwei Spalten: links das Foto (168 px), rechts die Felder. Weitere Bloecke —
 * Mehrwertsteuer, Groessen, "Auf der Kachel", "Rezept", die Fusszeile — flossen ohne diese
 * Regel abwechselnd in die LINKE Spalte und wurden dort auf 168 px zusammengequetscht: die
 * Steuer-Knoepfe brachen auf zwei Reihen um, und "Auf der Kachel / wie die Kategorie" stand
 * als schmaler Turm. Gemessen im Browser: das Kind war 218 px breit in einer 166 px breiten
 * Spalte.
 *
 * Sie gehoeren nicht neben das Foto, sondern darunter — jeder Block eine eigene Zeile.
 */
.produkt-kopf > *:not(.produkt-kopf-foto):not(.produkt-kopf-felder) { grid-column: 1 / -1; }

/* Das freie MwSt-Feld ist absichtlich schmal. ".field input[type=text]" zählt als (0,2,1) —
   ein Attribut wiegt so viel wie eine Klasse — und schlägt damit sowohl ".mwst-input" als auch
   ".field .mwst-input". Erst mit drei Klassen plus Element gewinnt die schmale Breite. */
.field .mwst-row input.mwst-input { width: 92px; }

.farb-zeile { display: flex; align-items: center; gap: 8px; }
.farb-zeile input[type="color"] {
    width: 44px;
    height: 38px;
    padding: 2px;
    background: var(--djk-black-soft);
    border: 1px solid #929292;
    border-radius: 5px;
    cursor: pointer;
}
.farb-zeile input[type="color"]:disabled { opacity: .45; cursor: default; }

/* Zeilenlisten (Größen, Zutaten): früher stand jede Breite und Farbe einzeln im style-Attribut. */
.zeilen-liste { display: flex; flex-direction: column; gap: 8px; }
.groesse-row { align-items: center; gap: 10px; cursor: pointer; }
.groesse-row .groesse-name { flex: 1; min-width: 0; }
.zutat-row { display: flex; align-items: center; gap: 8px; }
/* Nur was diese Zeile ausmacht: schmal und knapp. Grund, Rand, Ecken und Fokus kommen aus der
   Grundregel für Textfelder (Abschnitt BEDIENELEMENTE) — sie standen hier mit eigenem grauen
   Grund und hart getipptem #929292 noch einmal, und damit sah dieses Feld anders aus als das
   daneben. */
.zeilen-liste input[type="text"] {
    padding: 8px 10px;
    font-size: 0.9rem;
    min-width: 0;
}
/* Schmale Zeile, sonst wie jede andere Auswahlliste. `background-COLOR`, nie die Kurzform:
   die naehme den Pfeil mit (Falle 15). Der Pfeil rueckt mit dem kleineren Innenabstand nach. */
.zeilen-liste select {
    padding: 8px 28px 8px 10px;
    background-position: right 8px center;
    font-size: 0.9rem;
    min-width: 0;
}
.zeilen-liste input[type="text"]:focus,
.zeilen-liste select:focus {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}
.groesse-row .groesse-preis-input { flex: 0 0 100px; text-align: right; }
.zutat-row input[name="zutat_bezeichnung[]"] { flex: 2; }
.zutat-row input[name="zutat_menge[]"] { flex: 0 0 76px; }
.zutat-row select { flex: 0 0 86px; }
.zutat-row input[name="zutat_preis[]"] { flex: 0 0 88px; text-align: right; }

.produkt-form-fuss {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    position: sticky;
    bottom: 0;
    margin-top: 18px;
    padding: 14px 0 2px;
    /* Das Modal ist lang — ohne mitlaufenden Balken müsste man zum Speichern jedes Mal ganz
       nach unten scrollen. */
    background: linear-gradient(to bottom, transparent, var(--djk-black-card) 45%);
}

@media (max-width: 640px) {
    .produkt-kopf { grid-template-columns: 1fr; }
    .produkt-kopf-felder { grid-template-columns: 1fr; }
    .produkt-kopf-foto .photo-square-wrap { margin: 0 auto; }
    .zutat-row { flex-wrap: wrap; }
    .zutat-row input[name="zutat_bezeichnung[]"] { flex: 1 1 100%; }
}

.mitarbeiter-profil .admin-form-section { margin-bottom: 12px; }
.mitarbeiter-profil-aktionen {
    display: flex;
    align-items: center;
    gap: 10px;
    position: sticky;
    bottom: 0;
    /* Das Modal scrollt; ohne den mitlaufenden Balken müsste man für "Speichern" jedes Mal
       bis ganz nach unten wischen. */
    padding: 12px 0 2px;
    background: linear-gradient(to bottom, transparent, var(--djk-black-card) 40%);
}
.mitarbeiter-profil input[readonly] { background: var(--djk-black); color: var(--djk-gray); cursor: default; }

/* Adress-Vorschläge der Live-Suche */
.adress-suche-feld { position: relative; }
.adress-vorschlaege {
    position: absolute;
    z-index: 30;
    left: 0;
    right: 0;
    top: 100%;
    margin-top: 4px;
    max-height: 240px;
    overflow-y: auto;
    background: var(--djk-black-card);
    border: 1px solid #929292;
    border-radius: 5px;
    box-shadow: 0 10px 24px rgba(15, 23, 42, .14);
}
.adress-vorschlag {
    display: block;
    width: 100%;
    text-align: left;
    padding: 9px 12px;
    border: 0;
    border-bottom: 1px solid var(--djk-border);
    background: transparent;
    color: var(--djk-white);
    font-size: 0.85rem;
    line-height: 1.35;
    cursor: pointer;
}
.adress-vorschlag:last-child { border-bottom: 0; }
.adress-vorschlag:hover { background: var(--djk-sidebar-bg-active); }

/* Hinweistexte der Sperrseite: Haken, Text und Entfernen in einer sauberen Zeile. */
.sperr-nachrichten { display: flex; flex-direction: column; gap: 8px; }
.sperr-nachricht-zeile { display: flex; align-items: center; gap: 10px; }
/* Die Eingabe steckt in einem .input-icon-Rahmen — der muss die Zeile ausfüllen, nicht das
   nackte Feld darin. */
.sperr-nachricht-eingabe { flex: 1; min-width: 0; display: block; }
.sperr-nachricht-zeile input[type="text"] {
    width: 100%;
    min-width: 0;
    padding: 10px 12px 10px 40px;   /* links Platz für das Symbol */
    font-size: 0.9rem;
}
.sperr-nachricht-haken {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    padding: 8px 11px;
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    font-size: 0.78rem;
    color: var(--djk-gray);
    cursor: pointer;
    user-select: none;
}
.sperr-nachricht-haken input { width: 16px; height: 16px; margin: 0; accent-color: var(--djk-yellow-dark); }
.sperr-nachricht-haken:has(input:checked) { border-color: var(--djk-yellow-dark); color: var(--djk-yellow-dark); font-weight: 600; }
.sperr-nachricht-weg {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: transparent;
    color: var(--djk-gray);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}
.sperr-nachricht-weg:hover { border-color: var(--djk-danger); color: var(--djk-danger); }

/* Code-Spalte der Mitarbeiterliste: Zahl und "Neu" auf einer Linie, gleiche Breite je Zeile. */
.code-zelle { display: flex; align-items: center; gap: 10px; }
.code-zelle .code-zahl {
    min-width: 3ch;
    font-variant-numeric: tabular-nums;
    letter-spacing: .04em;
}

/* source/style_css/085_modal_head_staff_product_forms_continued.css - style.css: modal head staff product forms continued, part 11 of 78 (built by werkzeuge/parts_build.php) */
.abteilung-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.abteilung-chip {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 6px 6px 14px;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
}
.abteilung-chip-haupt { border-color: var(--djk-yellow); }
.abteilung-chip > a { font-size: 0.85rem; font-weight: 600; color: var(--djk-white); text-decoration: none; }
.abteilung-chip-stern { color: var(--djk-yellow); }

.abteilung-form .toggle-switch { width: 100%; margin-bottom: 12px; }

@media (max-width: 560px) {
    .sperr-nachricht-zeile { flex-wrap: wrap; }
    .sperr-nachricht-eingabe { order: -1; flex-basis: 100%; }
}

/* source/style_css/090_opening_hours_statistics.css - style.css part 12 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Öffnungszeiten: Wochenplan ----------
   Eine Zeile je Wochentag statt einer Stapelung aus Überschrift und loser Eingabezeile: der Name
   steht in einer festen Spalte links, rechts die gebuchten Fenster und darunter das Formular für
   ein weiteres. So liest sich der Plan wie ein Aushang. */
.woche-plan { border: 1px solid var(--djk-border); border-radius: 8px; overflow: hidden; }
.woche-tag {
    display: grid;
    grid-template-columns: 132px minmax(0, 1fr);
    gap: 12px;
    align-items: start;
    padding: 12px 14px;
    border-bottom: 1px solid var(--djk-border);
}
.woche-tag:last-child { border-bottom: 0; }
.woche-tag:nth-child(even) { background: var(--djk-black-soft); }
.woche-tag-heute { box-shadow: inset 3px 0 0 var(--djk-yellow-dark); }
.woche-tag-name {
    font-weight: 700;
    font-size: 0.9rem;
    padding-top: 7px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.woche-heute-marke {
    align-self: flex-start;
    font-size: 0.66rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--djk-yellow-dark);
    background: var(--djk-sidebar-bg-active);
    border-radius: 999px;
    padding: 2px 8px;
}
.woche-tag-inhalt { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.woche-fenster { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

.zeit-fenster-liste { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.zeit-fenster {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 6px 6px 12px;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    font-weight: 700;
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
    color: var(--djk-white);
}
.zeit-fenster .icon { color: var(--djk-gray); }
.zeit-fenster a { color: inherit; text-decoration: none; }
.zeit-fenster form { margin: 0; }
/* Die warme Kueche sitzt IM Fenster-Chip: kleines Wort, kleines Feld, sonst sprengt sie ihn. */
.zeit-warm { display: inline-flex; align-items: center; gap: 6px; }
.zeit-warm-wort { font-size: 0.74rem; font-weight: 600; color: var(--djk-gray); white-space: nowrap; }
.zeit-warm input[type="time"] {
    width: 96px;
    padding: 4px 8px;
    font-variant-numeric: tabular-nums;
}
.zeit-geschlossen {
    font-size: 0.82rem;
    color: var(--djk-gray);
    padding: 6px 0;
}

.woche-neu { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; }
.woche-neu input[type="time"] {
    width: 118px;
    padding: 7px 10px;
    /* Ziffern gleicher Breite: sonst wackelt die Uhrzeit beim Tippen. */
    font-variant-numeric: tabular-nums;
}
.woche-bis { font-size: 0.82rem; color: var(--djk-gray); }

/* Feiertage & Urlaub */
.oz-aus-liste { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.oz-aus-karte {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    padding: 10px 12px 10px 14px;
}
.oz-aus-datum { font-weight: 700; font-size: 0.9rem; color: var(--djk-white); font-variant-numeric: tabular-nums; }
.oz-aus-name { font-size: 0.82rem; color: var(--djk-gray); }
.oz-aus-badge { font-size: 0.74rem; font-weight: 800; border-radius: 999px; padding: 4px 12px; }
.oz-aus-badge.zu { background: rgba(239, 68, 68, 0.12); color: var(--djk-danger); }
.oz-aus-badge.zeit { background: rgba(16, 185, 129, 0.14); color: #0f7a5a; }
.oz-aus-karte form { margin: 0 0 0 auto; }
/* Der Schalter steht ganz vorne und darf NICHT von der Regel darüber nach rechts geschoben
   werden. Zwei Stufen im Selektor sind dafür nötig: ".oz-aus-schalter-form" allein wöge
   weniger als ".oz-aus-karte form" und bliebe wirkungslos. */
.oz-aus-karte .oz-aus-schalter-form { margin: 0; flex: none; }
.oz-aus-schalter {
    width: 42px;
    height: 24px;
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    background: rgba(120, 120, 120, .18);
    position: relative;
    cursor: pointer;
    padding: 0;
}
.oz-aus-schalter > span {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
    transition: left .15s ease;
}
.oz-aus-schalter.an { background: var(--djk-success, #3f8f5c); border-color: transparent; }
.oz-aus-schalter.an > span { left: 21px; }
/* Ausgesetzt: blass, aber lesbar — der Eintrag soll ja wiedergefunden werden. */
.oz-aus-karte.ist-aus .oz-aus-datum,
.oz-aus-karte.ist-aus .oz-aus-name,
.oz-aus-karte.ist-aus .oz-aus-badge.zu,
.oz-aus-karte.ist-aus .oz-aus-badge.zeit { opacity: .5; }
.oz-aus-badge.aus { background: rgba(120, 120, 120, .18); color: var(--djk-gray); }
.oz-aus-form {
    display: none;
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    background: var(--djk-black-soft);
    padding: 14px;
    margin-top: 12px;
}
.oz-aus-form.offen { display: block; }

/* Schlüssel und Adressen: Ziffern und Buchstaben gleich breit, damit sich Zeichen prüfen lassen. */
.schluessel-feld { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 0.84rem; }

@media (max-width: 560px) {
    .woche-tag { grid-template-columns: 1fr; }
    .woche-tag-name { padding-top: 0; flex-direction: row; align-items: center; gap: 8px; }
}

/* Beschreibung und Allergene auf der Produktkachel — bewusst klein, sie sollen den Namen
   nicht überlagern, aber ohne Öffnen des Formulars lesbar sein. */
.admin-produkt-beschreibung {
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--djk-gray);
    margin: 2px 0 4px;
}
.admin-produkt-allergene {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--djk-gray);
    margin-bottom: 4px;
}

/* Allergen-Auswahl: 14 feste Angaben, deshalb schmalere Kacheln als bei den Rabatt-Zielen. */
.allergen-chips { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.allergen-chips .rabatt-chip-name { font-weight: 500; font-size: 0.82rem; }

/* Zugeklappt zeigt die Kopfzeile die gewählten Kennungen — deshalb dürfen sie dort nicht
   abgeschnitten werden wie ein gewöhnlicher Hinweistext. */
.allergen-block { margin-bottom: 16px; }
.allergen-block > summary > .admin-collapsible-hint {
    font-weight: 700;
    letter-spacing: .04em;
    color: var(--djk-yellow-dark);
    white-space: normal;
}

/* Der dritte Umschalter am Kategorie-Chip eines Extras: "steht in der Beschreibung". */
.chip-text-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--djk-gray);
    padding: 4px 6px;
    cursor: pointer;
    opacity: .45;
}
.chip-text-toggle .icon { width: 15px; height: 15px; }
.chip-text-toggle:hover:not(:disabled) { opacity: .8; }
.chip-text-toggle.active { opacity: 1; color: var(--djk-yellow-dark); }
.chip-text-toggle:disabled { opacity: .18; cursor: default; }

/* ---------- Statistik & Kontrolle: Online-Verkäufe und Diagramme ---------- */
.ov-filterleiste { padding-bottom: 14px; }
.ov-suchfeld { margin-bottom: 14px; }
/* Seit 19.09.2026 steht der Zeitraum als Knopfreihe der Finanzen UEBER dem Filterkasten
   (ov_filterleiste); Suche und Kasten folgen mit dem Abstand der Finanzen. */
.ov-filterleiste.finanz-kopf .ov-suchfeld { margin-bottom: 0; }
.ov-filterleiste.finanz-kopf > .filter-klapp { margin-top: 12px; }
/* Die Telefonnummer in der Liste: jede Zifferngruppe bleibt beisammen, umgebrochen wird nur
   zwischen den Gruppen — die Zelle darf schmal werden, ohne „2345|678" zu zerreissen. */
.ov-telefon-teil { white-space: nowrap; }
/* Die Huelle einer Zelle mit zwei Zeilen (Name + Nummer, Summe + Rabatt): am Telefon ist sie
   EIN Flex-Kind der Karte, darf schmal werden und stapelt ihren Inhalt untereinander. */
.ov-zelle { min-width: 0; }
.ov-filter-raster { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.ov-filter-fuss {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--djk-border);
}
.ov-filter-fuss .toggle-switch { margin: 0; }
.ov-stand { margin-left: auto; font-variant-numeric: tabular-nums; }

/* Der Punkt blinkt kurz auf, sobald wieder abgefragt wurde — so ist zu sehen, dass die
   Liste wirklich lebt und nicht seit zehn Minuten steht. */
.ov-live {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--djk-gray);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    padding: 6px 14px;
}
.ov-live-punkt {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--djk-success);
    transition: transform .3s ease, box-shadow .3s ease;
}
.ov-live-aktiv .ov-live-punkt { transform: scale(1.6); box-shadow: 0 0 0 4px rgba(16, 185, 129, .18); }

.ov-kennzahlen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 12px;
    margin-bottom: 18px;
}
.ov-kennzahlen-breit { grid-template-columns: repeat(auto-fit, minmax(135px, 1fr)); }
.ov-kennzahl {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    padding: 14px 16px;
}
.ov-kennzahl-wert {
    display: block;
    font-size: 1.35rem;
    font-weight: 800;
    color: var(--djk-white);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.ov-kennzahl-text { display: block; margin-top: 2px; font-size: 0.78rem; color: var(--djk-gray); }

/* Neu hereingekommene Bestellungen leuchten einmal auf und beruhigen sich dann wieder. */
@keyframes ov-neu-leuchten {
    from { background: rgba(16, 185, 129, .22); }
    to { background: transparent; }
}
/* Ohne `forwards`: sonst hielte die Animation den Endwert "transparent" fest und übermalte
   danach dauerhaft die eigene Hintergrundfarbe der Zeile (siehe .rv-zeile-offen). So fällt
   die Zeile nach dem Aufleuchten auf ihre normale Farbe zurück. */
.ov-zeile-neu > td { animation: ov-neu-leuchten 4s ease-out; }
.ov-tabelle td { vertical-align: top; }
.ov-rabatt { color: var(--djk-danger); }

.ov-marke {
    display: inline-block;
    font-size: 0.74rem;
    font-weight: 800;
    border-radius: 999px;
    padding: 4px 11px;
    white-space: nowrap;
    background: var(--djk-black-soft);
    color: var(--djk-gray);
}
.ov-status-neu { background: rgba(59, 130, 246, .14); color: var(--djk-yellow-dark); }
.ov-status-abgeschlossen { background: rgba(16, 185, 129, .16); color: #0f7a5a; }
.ov-status-storniert { background: rgba(239, 68, 68, .14); color: var(--djk-danger); }
/* Vorbestellung fuer einen anderen Tag, noch nicht in der Kueche (13.09.2026). */
.ov-status-geplant { background: rgba(168, 85, 247, .14); color: #7e3fbf; }

/*
 * ═══ DIE KARTE DER VORBESTELLUNGEN (13.09.2026) ═══
 *
 * Steht in der Verwaltung ueber „Online-Verkäufe" und an der Kasse ueber „Online-Bestellungen"
 * (includes/vorbestellung_ansicht.php). Eine Zeile je Bestellung: Tag, Gast, Summe, Knoepfe —
 * auf dem Telefon untereinander, auf dem Bildschirm nebeneinander.
 */
.vorb-karte {
    border: 1px solid var(--djk-border);
    border-left: 4px solid var(--djk-yellow);
    border-radius: 10px;
    background: var(--djk-black-soft);
    padding: 14px 16px;
    margin: 0 0 18px;
}
.vorb-titel { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; font-size: 1.05rem; }
.vorb-titel .icon { font-size: 1.1rem; }
.vorb-text { margin: 0 0 10px; }
.vorb-zeile {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.4fr) auto;
    gap: 6px 16px;
    align-items: center;
    padding: 10px 0;
    border-top: 1px solid var(--djk-border);
}
.vorb-termin, .vorb-gast, .vorb-summe { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vorb-gast .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vorb-telefon { display: inline-flex; align-items: center; gap: 4px; font-size: .9rem; }
.vorb-telefon .icon { width: 14px; height: 14px; }
.vorb-summe { align-items: flex-end; text-align: right; }
.vorb-marke { font-size: .75rem; font-weight: 700; border-radius: 999px; padding: 2px 8px; }
.vorb-marke-ok { background: rgba(16, 185, 129, .16); color: #0f7a5a; }
.vorb-marke-offen { background: rgba(245, 158, 11, .16); color: #a16207; }
.vorb-aktionen { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.vorb-form { margin: 0; }
.vorb-aktionen .btn .icon { width: 15px; height: 15px; }
.vorb-einstellung-felder { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px 18px; }
.vorb-nicht-bereit { color: var(--djk-danger); }
@media (max-width: 640px) {
    /* Auf dem Telefon: der Tag ueber die ganze Breite, darunter Gast und Summe nebeneinander. */
    .vorb-zeile { grid-template-columns: minmax(0, 1fr) auto; }
    .vorb-termin { grid-column: 1 / -1; grid-row: 1; }
    .vorb-gast { grid-column: 1; grid-row: 2; }
    .vorb-summe { grid-column: 2; grid-row: 2; }
    .vorb-aktionen { justify-content: stretch; }
    .vorb-aktionen .vorb-form { flex: 1 1 auto; }
    .vorb-aktionen .btn { width: 100%; justify-content: center; }
}
.ov-kueche-offen { background: rgba(245, 158, 11, .16); color: #a45c00; }
.ov-kueche-bestaetigt { background: rgba(59, 130, 246, .14); color: var(--djk-yellow-dark); }
.ov-kueche-fertig { background: rgba(16, 185, 129, .16); color: #0f7a5a; }
.ov-kueche-unterwegs { background: rgba(139, 92, 246, .16); color: #6d3fc4; }

/* Reservierungen: dieselben Marken, eigene Bedeutungen. */
.rv-status-aktiv { background: rgba(16, 185, 129, .16); color: #0f7a5a; }
.rv-status-unbestaetigt { background: rgba(245, 158, 11, .16); color: #a45c00; }
.rv-status-abgesagt { background: rgba(239, 68, 68, .14); color: var(--djk-danger); }
.rv-herkunft-oeffentlich { background: rgba(59, 130, 246, .14); color: var(--djk-yellow-dark); }
.rv-herkunft-personal { background: var(--djk-black-soft); color: var(--djk-gray); }
.rv-nachricht {
    margin: 0;
    padding: 10px 12px;
    background: var(--djk-black-soft);
    border-radius: 6px;
    font-size: 0.88rem;
    line-height: 1.5;
    white-space: pre-line;
}
.rv-qr { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.rv-qr img { width: 130px; height: 130px; background: #fff; border: 1px solid var(--djk-border); border-radius: 8px; padding: 6px; }
.rv-qr .hint { flex: 1; min-width: 180px; margin: 0; }

/* Was auf Bestätigung wartet, ist offene Arbeit — die ganze Zeile trägt den Farbton der
   Status-Marke, damit man es beim Überfliegen der Liste nicht übersieht. Abgesagtes tritt
   umgekehrt zurück: es steht nur noch zum Nachschlagen da. */
.rv-zeile-offen > td { background: rgba(245, 158, 11, .10); }
.rv-zeile-offen > td:first-child { box-shadow: inset 3px 0 0 #f59e0b; }
.rv-zeile-abgesagt > td { opacity: .62; }

/* source/style_css/100_foldout_blocks_time_clock_dashboard.css - style.css part 13 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Aufklappbare Blöcke in den Karteikarten ----------
   Gast, Termin, Ablauf, Beleg … untereinander ausgeklappt füllten sie mehrere Bildschirm-
   höhen. Jetzt liegen je zwei nebeneinander, und die selten gebrauchten starten zu.
   Aufgebaut auf <details>/<summary>: Aufklappen, Tastatur und Vorlesen kann der Browser
   selbst, dafür braucht es kein eigenes JavaScript. */
.admin-klapp-paar {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 14px;
    align-items: start;
}
.admin-klapp {
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: rgba(15, 23, 42, 0.025);
    margin-bottom: 14px;
}
.admin-klapp-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 11px 14px;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
/* Das Standard-Dreieck beider Engines entfernen — es sitzt links und lässt sich nicht
   gestalten; stattdessen der eigene Pfeil rechts (siehe ::after). */
.admin-klapp-kopf::-webkit-details-marker { display: none; }
.admin-klapp-titel {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--djk-yellow);
}
/* Die Kurzfassung: was drinsteht, ohne aufzuklappen. */
.admin-klapp-kurz {
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--djk-gray);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.admin-klapp-kopf::after {
    content: '';
    flex: none;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--djk-gray);
    border-bottom: 2px solid var(--djk-gray);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .15s ease;
}
.admin-klapp[open] > .admin-klapp-kopf::after { transform: rotate(-135deg) translate(-2px, -2px); }
.admin-klapp[open] > .admin-klapp-kopf { padding-bottom: 2px; }
.admin-klapp-inhalt { padding: 0 14px 12px; }
/* .info-list bringt 16px Abstand mit, gedacht für den Einsatz unter einer Überschrift —
   hier steht die Kopfzeile schon direkt darüber. */
.admin-klapp-inhalt > .info-list { margin-top: 0; }
.admin-klapp-inhalt > .info-list li:last-child { border-bottom: 0; padding-bottom: 0; }

@media (max-width: 720px) {
    .admin-klapp-paar { grid-template-columns: minmax(0, 1fr); }
}

/* Karteikarte einer Bestellung */
.ov-adresse { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ov-adresse-text { flex: 1; min-width: 200px; font-weight: 600; }
.ov-adresse-knoepfe { display: flex; gap: 8px; flex-wrap: wrap; }
.ov-positionen td { vertical-align: top; }
.ov-kommentar { font-style: italic; }
.ov-summenzeile {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--djk-border);
    font-size: 1.05rem;
}

.ov-zeitachse { list-style: none; margin: 0; padding: 0 0 0 20px; border-left: 2px solid var(--djk-border); }
.ov-zeitachse li { position: relative; padding: 0 0 16px 14px; }
.ov-zeitachse li:last-child { padding-bottom: 0; }
.ov-zeitachse li::before {
    content: '';
    position: absolute;
    left: -25px;
    top: 5px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--djk-yellow-dark);
    box-shadow: 0 0 0 3px var(--djk-black-card);
}
.ov-zeitachse-zeit { display: block; font-size: 0.76rem; color: var(--djk-gray); font-variant-numeric: tabular-nums; }
.ov-zeitachse-titel { display: block; font-weight: 700; font-size: 0.9rem; }
.ov-zeitachse-text { display: block; font-size: 0.82rem; color: var(--djk-gray); }

/* Diagramme */
.ov-diagramm-kopf { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ov-diagramm { margin-top: 12px; }
.ov-diagramm-paar { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 18px; }
.ov-svg { width: 100%; height: auto; display: block; overflow: visible; }
.ov-raster { stroke: var(--djk-border); stroke-width: 1; }
.ov-achse { fill: var(--djk-gray); font-size: 11px; }
.ov-linie { fill: none; stroke: var(--djk-yellow-dark); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.ov-flaeche { fill: rgba(59, 130, 246, .14); stroke: none; }
.ov-punkt { fill: var(--djk-yellow-dark); }
.ov-punkt:hover { r: 5; }
.ov-balken { fill: var(--djk-yellow-dark); opacity: .85; }
.ov-balken:hover { opacity: 1; }

.ov-schalter { display: inline-flex; border: 1px solid var(--djk-border); border-radius: 999px; overflow: hidden; }
.ov-schalter-knopf {
    border: 0;
    background: transparent;
    color: var(--djk-gray);
    font-size: 0.78rem;
    font-weight: 700;
    padding: 6px 14px;
    cursor: pointer;
}
.ov-schalter-knopf.active { background: var(--djk-yellow-dark); color: #fff; }

.ov-balkenliste { display: flex; flex-direction: column; gap: 9px; }
.ov-balken-zeile { display: grid; grid-template-columns: minmax(90px, 1.3fr) 2fr auto; align-items: center; gap: 10px; }
.ov-balken-name { font-size: 0.84rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-balken-spur { height: 10px; border-radius: 999px; background: var(--djk-black-soft); overflow: hidden; }
.ov-balken-fuellung { display: block; height: 100%; border-radius: 999px; background: var(--djk-yellow-dark); }
.ov-balken-wert { font-size: 0.82rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

.ov-anteil { display: block; height: 8px; width: 100%; max-width: 140px; border-radius: 999px; background: var(--djk-black-soft); overflow: hidden; margin-bottom: 3px; }
.ov-anteil-fuellung { display: block; height: 100%; background: var(--djk-yellow-dark); }

@media (max-width: 620px) {
    .ov-stand { margin-left: 0; flex-basis: 100%; }
    .ov-balken-zeile { grid-template-columns: minmax(70px, 1fr) 1.4fr auto; }
}

/* Ziffernblock (Dial-Pad) für PIN-/Code-Felder in der Personal-Anmeldung */
.field.dial-target-active .input-icon {
    border-radius: var(--radius);
    box-shadow: 0 0 0 2px var(--djk-yellow);
}

.field.dial-target-active .input-icon input {
    border-color: var(--djk-yellow);
}

.dial-input {
    letter-spacing: 6px;
    font-size: 1.1rem;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
}

.dial-pad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin: 4px 0 20px;
}

.dial-pad-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 14px 0;
    min-height: 52px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    color: var(--djk-white);
    font-size: 1.15rem;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
    user-select: none;
    -webkit-user-select: none;
}

.dial-pad-btn:hover { border-color: var(--djk-yellow); }
.dial-pad-btn:active { background: rgba(59, 130, 246, 0.15); transform: scale(0.96); }

.dial-pad-btn-muted { color: var(--djk-gray); font-size: 0.95rem; }
.dial-pad-btn-muted .icon { width: 20px; height: 20px; }

/* ---------- Die Stempeluhr (personal/stempeln.php, 18.09.2026) ----------
   Dieselbe Karte und dieselben Tasten wie die Anmeldung; neu sind nur der Stand und die
   Pausenwahl. Die Pausen sehen aus wie die Tasten darueber — ein Tipp, kein Aufklappmenue. */
.az-karte h2 { display: flex; align-items: center; gap: 8px; }
/* `.btn` setzt `display: inline-flex` und schlaegt damit das `hidden` des Browsers — ohne
   diese Zeile stuenden „Kommen" und „Gehen" nebeneinander (siehe Handbuch: hidden gegen display). */
.az-karte [hidden] { display: none !important; }
.az-hallo { font-size: 1.15rem; font-weight: 700; margin: 0 0 4px; color: var(--djk-white); }
.az-zustand { margin: 0 0 18px; color: var(--djk-gray); }
/* Eigene Klasse statt `.hint`: `.field .hint` faerbt mit `--djk-black`, und das ist in diesem
   Namensschema die Farbe des GRUNDES — gemessen rgb(22, 24, 29) auf rgb(22, 24, 29). */
.az-regel { margin: 6px 0 0; font-size: 0.78rem; line-height: 1.4; color: var(--djk-gray); }
.az-pausen {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
}
.az-pause { position: relative; margin: 0; }
.az-pause input { position: absolute; opacity: 0; pointer-events: none; }
.az-pause span {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    color: var(--djk-white);
    font-weight: 700;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}
.az-pause input:checked + span { background: var(--djk-yellow); border-color: var(--djk-yellow); color: #fff; }
.az-pause input:focus-visible + span { outline: 2px solid var(--djk-yellow); outline-offset: 2px; }
.az-abbrechen { margin-top: 10px; }
.az-ergebnis { font-size: 1.15rem; font-weight: 700; margin: 0 0 12px; color: var(--djk-white); }
.az-warnung { margin: 0 0 16px; color: var(--djk-copper); }
.az-link { margin: 18px 0 0; text-align: center; font-size: 0.9rem; }
.az-link a { color: var(--djk-gray); }

/* Verwaltung → Arbeitszeiten (admin/arbeitszeiten.php). EIN Formular fuer drei Zwecke; was
   zum gewaehlten Zweck nicht gehoert, ist weg — und das Skript nimmt ihm auch das Pflicht. */
.az-formular[data-modus="berichtigen"] .az-nur-nachtrag,
.az-formular[data-modus="stornieren"] .az-nur-nachtrag,
.az-formular[data-modus="stornieren"] .az-nicht-storno { display: none; }
.az-uebersicht { margin-bottom: 18px; }
.az-auffaellig { color: var(--djk-copper); font-weight: 700; }
.az-mensch { margin-top: 16px; }
.az-marke {
    display: inline-block;
    margin: 0 4px 3px 0;
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid var(--djk-border);
    font-size: 0.75rem;
    color: var(--djk-gray);
    white-space: nowrap;
}
.az-marke-warn { border-color: var(--djk-copper); color: var(--djk-copper); }
.az-marke-ruhig { border-color: var(--djk-success); color: var(--djk-success); }
.az-storniert td { color: var(--djk-gray); }
.az-storniert td:not(:nth-last-child(-n+2)) { text-decoration: line-through; }
.az-verlauf { margin-top: 4px; font-size: 0.78rem; color: var(--djk-gray); }
.az-verlauf summary { cursor: pointer; }
.az-verlauf ul { margin: 6px 0 0; padding-left: 16px; }
.az-verlauf li { margin-bottom: 6px; }
.az-griffe { white-space: nowrap; text-align: right; }
.az-griffe .btn + .btn { margin-left: 4px; }
/* Das Blatt fuers Lohnbuero — Titel und Ausfuhr in einer Zeile, darunter der Satz dazu. */
.az-lohnblatt { margin-bottom: 16px; }
.az-lohnblatt-kopf { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.az-lohnblatt-kopf .admin-karte-titel { margin: 0; }
.az-lohnblatt-satz { margin: 8px 0 12px; font-size: 0.85rem; line-height: 1.45; color: var(--djk-gray); }

/* Avatar fallback (initials) */
.table-avatar-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: 0.72rem;
    color: var(--djk-yellow);
}

/* ---------- Alerts ---------- */
.alert {
    padding: 14px 18px;
    border-radius: 5px;
    margin-bottom: 18px;
    font-size: 0.9rem;
}

.alert-error { background: rgba(255, 85, 85, 0.14); border: 1px solid var(--djk-danger); color: #b91c1c; }
.alert-success { background: rgba(76, 175, 80, 0.14); border: 1px solid var(--djk-success); color: #15803d; }
/* Hinweis, der weder Fehler noch Erfolg ist — ein Rat, bevor etwas schiefgeht. */
.alert-info { background: rgba(59, 130, 246, 0.12); border: 1px solid var(--djk-blue, #3b82f6); color: #1d4ed8; }

/* ---------- Dashboard / Kabinett ---------- */
.dashboard-grid {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 24px;
}

@media (max-width: 780px) {
    .dashboard-grid { grid-template-columns: 1fr; }
}

.profile-card {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 24px;
    text-align: center;
    height: fit-content;
}

.profile-photo {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--djk-yellow);
    margin: 0 auto 16px;
    background: var(--djk-black-soft);
}

.profile-photo-placeholder {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    margin: 0 auto 16px;
    background: var(--djk-black-soft);
    border: 3px solid var(--djk-yellow);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.1rem;
    font-weight: 800;
    letter-spacing: 1px;
    color: var(--djk-yellow);
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 14px;
    border-radius: 5px;
    background: var(--djk-yellow);
    color: var(--djk-black);
    font-weight: 700;
    font-size: 0.78rem;
    letter-spacing: 0.3px;
}

/* Die NEBEN-Sparten eines Mitglieds (09.09.2026).

   Ein Mensch gehoert mehreren Abteilungen an, aber unter EINER laeuft er im Haus — sie steht
   in Kueche und Bar auf dem Zettel. Deshalb traegt sie das volle Abzeichen und die anderen ein
   blasses: gleich gross, gleich lesbar, nur nicht gleich laut.

   Ohne diese Regel sahen alle gleich aus. Gefunden vom Aussehen-Pruefer: der Code setzte die
   Klasse `muted`, es gab sie fuer `.badge` nur nicht — `.tag.muted` ist eine andere Kachel. */
.badge.muted {
    background: transparent;
    color: var(--djk-gray);
    border: 1px solid var(--djk-border);
    font-weight: 600;
}

.code-display {
    font-size: 1.8rem;
    font-weight: 900;
    letter-spacing: 6px;
    color: var(--djk-yellow);
    margin: 10px 0;
}

.info-list { list-style: none; padding: 0; margin: 16px 0 0; text-align: left; }
.info-list li {
    display: flex;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid var(--djk-border);
    font-size: 0.88rem;
}
.info-list li span:first-child { color: var(--djk-gray); }

.notes-card {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 24px;
}

.note-item {
    background: var(--djk-black-soft);
    border-left: 3px solid var(--djk-yellow);
    border-radius: 5px;
    padding: 14px 16px;
    margin-bottom: 12px;
}

.note-item time { display: block; font-size: 0.75rem; color: var(--djk-gray); margin-top: 6px; }

/* source/style_css/110_admin_table_modal_footer.css - style.css part 14 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Admin table ---------- */
.admin-toolbar {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    align-items: center;
}

/* Die Auswahlliste stand hier mit eigenem Rand und ohne Pfeil — sie folgt jetzt der Grundregel. */
.admin-toolbar input { padding: 11px 14px; }

.admin-toolbar input[type="search"] { flex: 1; min-width: 200px; }

.admin-toolbar .toolbar-search { flex: 1; min-width: 200px; }
.admin-toolbar .toolbar-search input { width: 100%; }
.admin-toolbar .toolbar-filter select { min-width: 170px; }
.admin-toolbar .input-icon input,
.admin-toolbar .input-icon select { padding-left: 42px; }

.stats-row {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 22px;
}

.stat-pill {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 14px 20px;
    min-width: 110px;
}

.stat-pill .num { font-size: 1.5rem; font-weight: 800; color: var(--djk-yellow); }
.stat-pill .label { font-size: 0.75rem; color: var(--djk-gray); }

.table-wrap {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    overflow-x: auto;
}



table.clients-table {
    width: 100%;
    border-collapse: collapse;
    min-width: 720px;
}

.clients-table th, .clients-table td {
    padding: 13px 16px;
    text-align: left;
    border-bottom: 1px solid var(--djk-border);
    font-size: 0.88rem;
    white-space: nowrap;
}

/*
 * Eine Spalte, die einen SATZ trägt, darf umbrechen.
 *
 * Tabellenzellen stehen hier auf `nowrap` — bei Zahlen, Uhrzeiten und Knöpfen ist das richtig,
 * die sollen nicht mitten im Betrag brechen. Sobald aber ein Satz in der Zelle steht („alles,
 * was keiner anderen Station zugeordnet ist" oder eine Liste von acht Kategorien), schiebt
 * dieselbe Regel die Tabelle über den Bildschirm hinaus: eine Bahn von 1530 px in einer Hülle
 * von 716 px, darunter ein Querlauf-Balken. Der Wirt hat ihn angestrichen — zu Recht: was man
 * schieben muss, sieht man nicht.
 */
.clients-table th.zelle-umbruch,
.clients-table td.zelle-umbruch { white-space: normal; overflow-wrap: anywhere; min-width: 7rem; }
/* Spalten, die nur ein Häkchen oder eine Adresse tragen: sie sollen umbrechen dürfen, aber
   keinen Platz beanspruchen, den der Satz daneben besser gebrauchen kann. */
.clients-table th.zelle-schmal,
.clients-table td.zelle-schmal { min-width: 0; }
/* Eine Tabelle, deren Spalten umbrechen dürfen, braucht keine Mindestbreite mehr — die 720 px
   von oben stammen aus der Zeit, als jede Zelle auf einer Zeile bleiben musste. */
table.clients-table.tabelle-fluid { min-width: 0; }

.clients-table th {
    color: var(--djk-yellow);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.clients-table tbody tr { cursor: pointer; transition: background var(--transition); }
.clients-table tbody tr:hover { background: rgba(59, 130, 246, 0.08); }

.table-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--djk-black-soft);
}

.tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 5px;
    font-size: 0.72rem;
    font-weight: 700;
    background: rgba(59, 130, 246, 0.15);
    color: var(--djk-yellow);
}

.tag.muted { background: var(--djk-black-soft); color: var(--djk-gray); }

.tag .icon, .badge .icon { flex-shrink: 0; }

.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--djk-gray);
}

/* ---------- Modal ---------- */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding: 40px 16px;
    overflow-y: auto;
    z-index: 100;
}

.modal-overlay.active { display: flex; }

/* border-radius, max-width, width und padding werden auf dem Handy (<=640px) für #itemModal und
   #payModal bewusst überschrieben — dort ist der Dialog ein Blatt, das von unten hochfährt
   (siehe die Regel bei @media (max-width: 640px)). Deshalb stehen sie in den Entwicklerwerkzeugen
   durchgestrichen; hier gelten sie weiterhin für alle anderen Fenster und für breite Bildschirme. */
.modal-box {
    background: #ffffff;
    /*
     * NUR OBEN EINE KANTE — nur oben eine Kante (28.08.2026).
     *
     * Der Wirt: „боковых линии нет", und dazu wortwoertlich `border-top: 1px solid #60a5fa`.
     * Der Rahmen ringsum zog auf dem Telefon eine Linie um das halbe Bild und machte das Fenster
     * zu einem Kasten IM Bild. Ein einzelner Strich oben sagt dasselbe — „hier faengt das
     * Fenster an" — und laesst dem Inhalt die ganze Breite.
     *
     * Die FARBE steht bewusst weiter als `var(--djk-yellow)` da und nicht als `#60a5fa`: im
     * dunklen Erscheinungsbild IST diese Variable genau dieses Blau (siehe den getauschten
     * Variablensatz bei `body.thema-dunkel`). Den Wert fest einzutragen hiesse, im hellen
     * Erscheinungsbild eine blaue Linie an ein sonst gelbes Fenster zu setzen.
     */
    border: 0;
    border-top: 1px solid var(--djk-yellow);
    border-radius: var(--radius);
    max-width: 560px;
    width: 100%;
    padding: 28px;
    box-shadow: var(--shadow);
    position: relative;
}

.modal-box-wide { max-width: 720px; }
/* Produktformular: Foto links neben den Feldern — dafür braucht der Kasten mehr Breite. */
.modal-box-produkt { max-width: 880px; }

/* Mitarbeiter-Detail: Profil/Historie/Einstellungen */
.aktivitaet-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; }
.aktivitaet-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    cursor: pointer;
}
.aktivitaet-row-top { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.aktivitaet-typ {
    font-size: 0.65rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 8px;
    border-radius: 5px;
    background: var(--djk-black-card);
    color: var(--djk-yellow);
    flex-shrink: 0;
}
.aktivitaet-zeit { font-size: 0.72rem; color: var(--djk-gray); flex-shrink: 0; white-space: nowrap; }
.aktivitaet-text { font-size: 0.85rem; color: var(--djk-white); }
.aktivitaet-details {
    display: none;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px dashed var(--djk-border);
    font-size: 0.78rem;
    color: var(--djk-gray);
}
.aktivitaet-details.active { display: block; }
.aktivitaet-details div { padding: 2px 0; }
.aktivitaet-details b { color: var(--djk-white); }

/* Mitarbeiter-Detail: Reiter „Verlauf" — Bedienschritte (19.09.2026, siehe mitarbeiter.js) */
.ks-favoriten { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 12px 18px; margin-bottom: 12px; }
.ks-rang-titel { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--djk-gray); margin: 4px 0 6px; }
.ks-rang-zeile { display: grid; grid-template-columns: minmax(0, 1fr) 70px auto; gap: 8px; align-items: center; font-size: 0.85rem; padding: 2px 0; }
.ks-rang-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--djk-white); }
.ks-rang-balken { height: 6px; border-radius: 3px; background: var(--djk-black-soft); overflow: hidden; }
.ks-rang-balken > span { display: block; height: 100%; background: var(--djk-yellow); border-radius: 3px; }
.ks-rang-zahl { font-variant-numeric: tabular-nums; color: var(--djk-gray); min-width: 2.5em; text-align: right; }
.ks-stunden { display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); gap: 2px; height: 64px; align-items: end; margin-bottom: 18px; }
.ks-stunde { position: relative; height: 100%; display: flex; align-items: flex-end; }
.ks-stunde-saeule { display: block; width: 100%; background: var(--djk-yellow); border-radius: 2px 2px 0 0; }
.ks-stunde-zahl { position: absolute; top: 100%; left: 0; font-size: 0.65rem; color: var(--djk-gray); line-height: 1.4; }
.ks-filter { max-width: 320px; }
.ks-tag { padding: 10px 12px; border-radius: 5px; border: 1px solid var(--djk-border); background: var(--djk-black-soft); margin-bottom: 8px; }
.ks-tag-kopf { font-size: 0.78rem; font-weight: 700; color: var(--djk-yellow); margin-bottom: 4px; }
.ks-zeile { font-size: 0.85rem; color: var(--djk-white); padding: 3px 0; line-height: 1.5; overflow-wrap: anywhere; }
.ks-zeile + .ks-zeile { border-top: 1px dashed var(--djk-border); }
.ks-uhr { color: var(--djk-gray); font-variant-numeric: tabular-nums; }
.ks-trenner { color: var(--djk-gray); }
.ks-art-buchen, .ks-art-bezahlen { font-weight: 600; }
.ks-art-storno { color: var(--djk-danger); }
#ksMehr { margin-top: 4px; }
.ks-hinweis { margin: 12px 0 0; text-align: center; font-size: 0.8rem; }

.modal-close {
    position: absolute;
    top: 16px;
    right: 16px;
    background: none;
    border: none;
    color: var(--djk-gray);
    font-size: 1.4rem;
    cursor: pointer;
}

/* Ersatz für alert() — siehe showAlertModal() in common.js. */
.djk-alert-box { max-width: 380px; text-align: center; }
.djk-alert-icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 14px;
    font-size: 1.6rem;
    font-weight: 800;
}
.djk-alert-box-error .djk-alert-icon { background: rgba(255, 107, 107, 0.15); color: var(--djk-danger); }
.djk-alert-box-success .djk-alert-icon { background: rgba(76, 175, 80, 0.15); color: var(--djk-success); }
.djk-alert-box-info .djk-alert-icon { background: rgba(59, 130, 246, 0.15); color: var(--djk-yellow); }
.djk-alert-title { margin: 0 0 8px; font-size: 1.15rem; }
.djk-alert-message { margin: 0 0 22px; color: var(--djk-gray); font-size: 0.9rem; line-height: 1.5; white-space: pre-line; }
.djk-alert-box .djk-alert-ok { width: 100%; }

.modal-header {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 20px;
}

.modal-header img, .modal-header .profile-photo-placeholder {
    width: 72px;
    height: 72px;
    margin: 0;
    font-size: 1.3rem;
}

/* ---------- Footer ---------- */
.site-footer {
    text-align: center;
    padding: 32px 20px;
    color: var(--djk-gray);
    font-size: 0.82rem;
    border-top: 1px solid var(--djk-border);
    margin-top: 40px;
}

.djk-toast {
    position: fixed;
    left: 50%;
    top: 24px;
    transform: translateX(-50%) translateY(-20px);
    background: var(--djk-black-card);
    border: 1px solid var(--djk-yellow);
    color: var(--djk-white);
    padding: 12px 20px;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    box-shadow: var(--shadow);
    z-index: 200;
    opacity: 0;
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
    max-width: 90vw;
    text-align: center;
}

.djk-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

@media (max-width: 780px) {
    .djk-toast { top: calc(16px + env(safe-area-inset-top, 0px)); }
}

.center-page {
    min-height: calc(100vh - 68px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 16px;
}

/* source/style_css/120_auth_split_screen.css - style.css part 15 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Auth: Split-Screen-Layout (Login / Registrieren) ---------- */
.auth-split {
    display: flex;
    min-height: 100vh;
}

.auth-split-left {
    flex: 1;
    background: #171717;
    color: var(--djk-white);
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 64px 56px;
    position: relative;
}

.auth-split-back {
    position: absolute;
    top: 32px;
    left: 56px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--djk-gray);
    font-size: 0.88rem;
}
.auth-split-back:hover { color: var(--djk-white); text-decoration: none; }
.auth-split-back .icon { width: 16px; height: 16px; }

.auth-split-left h1 {
    font-size: 2.1rem;
    font-weight: 900;
    line-height: 1.2;
    margin: 0 0 26px;
    max-width: 420px;
}

.auth-split-checklist {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.auth-split-checklist li {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 1rem;
    color: var(--djk-gray);
}

.auth-split-checklist .icon {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    color: var(--djk-yellow);
}

.auth-split-right {
    flex: 1;
    background: #e2a923;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 24px;
    overflow-y: auto;
    --djk-black-soft: #f4f6f9;
    --djk-black-card: #ffffff;
    --djk-white: #1a2233;
    --djk-gray: #6b7684;
    --djk-border: #e4e8ef;
    --djk-yellow-dark: #96690a;
    color: var(--djk-white);
}

.auth-split-right .field label { color: var(--djk-white); }
.auth-split-right .field input,
.auth-split-right .field select,
.auth-split-right .field textarea { border-radius: 5px; }

.auth-split-form-wrap { width: 100%; max-width: 400px; }
.auth-split-form-wrap.wide { max-width: 640px; }
.auth-split-form-wrap h2 { font-size: 1.7rem; margin: 0 0 6px; }
.auth-split-switch { color: #000000; font-size: 0.92rem; margin: 0 0 28px; }
.auth-split-switch a { color: #ffffff; font-weight: 700; }

.auth-hero-mobile { display: none; }

@media (max-width: 860px) {
    .auth-split-left { display: none; }
    .auth-split-right { padding: 0; min-height: 100vh; align-items: stretch; display: block; }

    .auth-hero-mobile {
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        height: 190px;
        background: linear-gradient(160deg, var(--djk-black) 0%, #081729 100%);
        border-radius: 0 0 32px 32px;
        overflow: hidden;
    }
    .auth-hero-back {
        position: absolute;
        top: 20px;
        left: 20px;
        display: inline-flex;
        align-items: center;
        gap: 6px;
        color: var(--djk-gray);
        font-size: 0.82rem;
        z-index: 2;
    }
    .auth-hero-back:hover { color: var(--djk-white); text-decoration: none; }
    .auth-hero-back .icon { width: 15px; height: 15px; }
    .auth-hero-badge {
        width: 68px;
        height: 68px;
        border-radius: 50%;
        background: var(--djk-yellow);
        color: var(--djk-black);
        display: flex;
        align-items: center;
        justify-content: center;
        font-weight: 900;
        font-size: 1.3rem;
        letter-spacing: 0.02em;
        box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4);
        z-index: 2;
    }
    .auth-hero-deco span { position: absolute; border-radius: 50%; background: rgba(59, 130, 246, 0.14); }
    .auth-hero-deco span:nth-child(1) { width: 100px; height: 100px; top: -30px; left: -30px; }
    .auth-hero-deco span:nth-child(2) { width: 60px; height: 60px; bottom: -14px; right: 30px; background: rgba(255, 255, 255, 0.06); }
    .auth-hero-deco span:nth-child(3) { width: 24px; height: 24px; top: 26px; right: 56px; background: rgba(255, 255, 255, 0.08); }

    .auth-split-form-wrap {
        max-width: none;
        margin: -26px auto 0;
        background: #fff;
        border-radius: 26px 26px 0 0;
        padding: 30px 22px 40px;
        position: relative;
        box-shadow: 0 -12px 24px rgba(0, 0, 0, 0.05);
    }
    .auth-split-form-wrap.wide { max-width: none; }

    .auth-split-right .field .input-icon input,
    .auth-split-right .field .input-icon select { border-radius: 999px; }
    .auth-split-right .btn-block { border-radius: 999px; }
}

/* source/style_css/130_register_pos.css - style.css part 16 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Kasse (POS) ---------- */
/* Alle Kasse-Dialoge (#itemModal Produkt-/Extra-Auswahl, #payModal Bezahlen/Storno/Gutschein)
   auf dem Handy als Bottom-Sheet, wie im Bestellshop (siehe bestellungen/assets/css/shop.css
   .shop-modal-overlay/.shop-modal-box) — reines Positionierungs-Update, Farben/Dark-Theme
   bleiben unverändert. Ab 640px bleibt der normale zentrierte Dialog (siehe
   .modal-overlay/.modal-box weiter unten). */
@media (max-width: 640px) {
    #itemModal, #payModal {
        align-items: flex-end;
        padding: 0;
    }
    #itemModal .modal-box, #payModal .modal-box {
        width: 100%;
        max-width: none;
        max-height: 88vh;
        overflow-y: auto;
        border-radius: 0;
        padding: 20px 16px 24px;
        /* Eigener dunkler Grund: auf dem Handy füllen diese beiden Fenster den ganzen
           Bildschirm — sie sind damit die Umgebung, nicht mehr ein Kästchen darin. */
        background: #20201f;
    }
}

.kasse-layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    align-items: start;
}

@media (max-width: 780px) {
    .kasse-layout { grid-template-columns: 1fr; }
}

.cart-list {
    list-style: none;
    padding: 0;
    margin: 0 0 16px;
    max-height: 340px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Neu hinzugefügte, aber noch nicht "Auf Tisch buchen" gedrückte Position — gleiche Zeilenform
   wie eine bereits gebuchte (siehe .cart-line), nur mit Akzentfarbe als Hinweis "noch offen". */
.cart-line.cart-line-pending {
    background: rgba(59, 130, 246, 0.12);
    /* Links blau = ziehen zum Bearbeiten, rechts rot = ziehen zum Löschen. Die Ränder sagen
       dasselbe wie die Knöpfe dahinter. */
    border-left: 3px solid var(--djk-yellow);
    border-right: 3px solid var(--djk-danger);
    padding-left: 8px;
}
/* Ohne Netz gebucht: liegt auf diesem Gerät und geht raus, sobald wieder Verbindung da ist.
   Gestrichelter roter Rand statt der durchgezogenen Ränder der Warenkorbzeile — es gibt hier
   nichts zu wischen, nichts zu löschen und nichts zu kassieren, nur zu warten. */
.cart-list li.cart-line.cart-line-wartend {
    background: rgba(239, 68, 68, 0.10);
    border-left: 3px dashed var(--djk-danger);
    border-right: 3px dashed var(--djk-danger);
    padding: 10px 14px;
    opacity: 0.92;
}
.cart-item-wartend {
    color: var(--djk-danger);
    font-weight: 700;
}

/* Jede Position ist ein eigener Block mit Abstand dazwischen — als durchgehende Liste mit
   Trennstrich verschwammen Gericht, Extras und Preise zu einer Wand aus Zeilen. */
.cart-list li.cart-line {
    margin-bottom: 10px;
    border-bottom: 0;
    border-radius: 0;
    overflow: hidden;
}
.cart-list li.cart-line:last-child { margin-bottom: 0; }
/* Die bereits gebuchten Positionen brauchen dieselbe Blockwirkung — ohne Trennstrich hätten sie
   sonst gar keine Abgrenzung mehr. */
.cart-list li.cart-line:not(.cart-line-pending) {
    background: var(--djk-black-soft);
    padding: 10px 14px;
}

/* Schlanke, moderne Scrollbar statt der klobigen Browser-Standardleiste — überall in der
   Kasse: Warenkorb, Kategorien- und Tisch-Übersicht, Produktliste auf dem großen Bildschirm. */
.cart-list,
.kategorie-overlay,
#kasseProductsSection,
#tischOverlayGrid {
    scrollbar-width: thin;
    scrollbar-color: rgba(59, 130, 246, 0.35) transparent;
}
.cart-list::-webkit-scrollbar,
.kategorie-overlay::-webkit-scrollbar,
#kasseProductsSection::-webkit-scrollbar,
#tischOverlayGrid::-webkit-scrollbar {
    width: 6px;
}
.cart-list::-webkit-scrollbar-track,
.kategorie-overlay::-webkit-scrollbar-track,
#kasseProductsSection::-webkit-scrollbar-track,
#tischOverlayGrid::-webkit-scrollbar-track {
    background: transparent;
}
.cart-list::-webkit-scrollbar-thumb,
.kategorie-overlay::-webkit-scrollbar-thumb,
#kasseProductsSection::-webkit-scrollbar-thumb,
#tischOverlayGrid::-webkit-scrollbar-thumb {
    background: rgba(59, 130, 246, 0.35);
    border-radius: 999px;
}
.cart-list::-webkit-scrollbar-thumb:hover,
.kategorie-overlay::-webkit-scrollbar-thumb:hover,
#kasseProductsSection::-webkit-scrollbar-thumb:hover,
#tischOverlayGrid::-webkit-scrollbar-thumb:hover {
    background: rgba(59, 130, 246, 0.55);
}

.cart-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    /* Rundum, nicht nur oben und unten: der Name klebte sonst am Rand.
       Der Wirt hat den Wert selbst genannt. */
    padding: 10px;
    border-bottom: 1px solid var(--djk-border);
    font-size: 0.9rem;
}

.cart-item-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* .cart-list li defaults to a flex row (single-line items elsewhere in the app);
   multi-line Kasse cart entries (name row + Beilagen/Extras/comment/total sub-rows)
   must stack vertically instead, or the sub-rows get shoved into the flex gap. */
.cart-list li.cart-line {
    display: block;
}

.cart-item-price {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.cart-item-remove {
    background: none;
    border: none;
    color: var(--djk-danger);
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
    padding: 2px 6px;
}

.cart-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-weight: 800;
    font-size: 1.35rem;
    padding: 14px 0;
    border-top: 2px solid var(--djk-border);
    margin-bottom: 16px;
    color: var(--djk-yellow);
}

.pay-methods {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
}

/* TRINKGELD (16.09.2026): eine Zeile ueber den Zahlarten — Wort, drei Knoepfe, die Summe.
   Am Telefon bricht sie um, die Knoepfe teilen sich die Breite. */
.pay-trinkgeld {
    display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px;
    margin-top: 14px; padding: 10px 12px;
    border: 1px solid var(--djk-border); border-radius: 12px;
}
.pay-trinkgeld-wort { font-weight: 700; font-size: .92rem; }
.pay-trinkgeld-knoepfe { display: flex; gap: 6px; flex: 1 1 200px; }
.pay-trinkgeld .tg-btn {
    flex: 1 1 auto; min-height: 40px; padding: 8px 10px;
    border: 1px solid var(--djk-border); border-radius: 10px;
    background: transparent; color: inherit; font-weight: 700; font-size: .9rem; cursor: pointer;
}
.pay-trinkgeld .tg-btn.ist-gewaehlt { border-color: var(--djk-yellow); color: var(--djk-yellow); }
.pay-trinkgeld-summe { flex: 0 0 auto; font-size: .95rem; }

/* HIER STAND EINE REGEL, DIE NIE GEGOLTEN HAT (geloescht 02.09.2026).

       @media (max-width: 480px) {
           .pay-methods { gap: 6px; }
           .pay-method-btn { flex: 1 1 calc(50% - 3px); padding: 18px 4px; font-size: .85rem; }
       }

   Sie stand VOR der Grundregel darunter. Beide haben dasselbe Gewicht, also gewinnt die
   spaetere — auf jeder Breite. Gemessen an der laufenden Kasse auf 360 Punkten galt immer
   `calc(33.333% - 7px)`: DREI Kacheln je Reihe, die Woerter brechen um statt abzuschneiden.

   Sie hat einmal Geld gekostet: beim Abgleich mit dem Kellner-Programm wurde sie gelesen,
   fuer wahr genommen und das Programm auf zwei je Reihe umgebaut — es zeigte danach etwas,
   das der Browser nie gezeigt hat.

   Geloescht und nicht verschoben: verschoben WUERDE sie wirken, und das waere eine
   Aenderung am Aussehen, die niemand bestellt hat. Wer zwei je Reihe will, sagt es. */

/*
 * ALLE KACHELN GLEICH GROSS (08.09.2026, Foto 1 des Wirts: er hat die ganze Tafel
 * eingekringelt).
 *
 * Die `1` in der Mitte von `flex: 1 1 …` hiess: waechst, wenn Platz da ist. In der letzten
 * Reihe steht oft EINE Kachel allein — „Personalessen" — und die nahm damit die ganze Breite,
 * waehrend die sechs darueber ein Drittel breit sind. Sieben Kacheln, zwei Groessen.
 *
 * Jetzt `0 0`: jede Kachel bleibt ein Drittel, auch allein in ihrer Reihe. Die Hoehen waren
 * schon immer gleich (`align-items: stretch` ist die Vorgabe einer Flex-Zeile) — das
 * Programm hat es nachgezogen.
 */
.pay-method-btn {
    flex: 0 0 calc(33.333% - 7px);
    min-width: 96px;
    padding: 26px 12px;
    border-radius: 5px;
    border: 2px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font-weight: 700;
    font-size: 0.95rem;
    transition: border-color var(--transition), transform var(--transition);
}

/*
 * JEDE ZAHLUNGSART IHRE FARBE (05.09.2026, Ansage des Wirts: *„сделай разные цвета плиток,
 * очень монотонно"*).
 *
 * Sieben gleich aussehende Kacheln zwingen zum LESEN; im Betrieb greift der Daumen aber nach
 * der Stelle und der Farbe. Genau dafuer traegt die Kopfleiste der Kasse seit je verschiedene
 * Akzente (`#kuecheBellBtn`, `#barBellBtn`, `#reservierungenBtn` weiter oben) — dasselbe
 * Mittel, derselbe Bauplan: dunkle Flaeche, farbige Kante, farbiges Zeichen. Der TEXT bleibt
 * weiss; sieben farbige Woerter waeren wieder ein Bild zum Lesen.
 *
 * Die Farbe kommt als `--pm-akzent` aus dem Programmcode (siehe farbeFuerZahlart in
 * kasse.js), damit sie fuer eine hausgemachte Zahlungsart mitwaechst. Ohne sie bleibt alles
 * wie bisher.
 */
/*
 * ZWEI ZEILEN PLATZ FUER DAS WORT — damit ALLE Kacheln gleich hoch sind (08.09.2026).
 *
 * Die Hoehe einer Kachel haengt sonst daran, ob ihr Wort umbricht: „Bar" ist einzeilig,
 * „Promo-Code" auf einem schmalen Telefon zweizeilig. Innerhalb einer Reihe gleicht der
 * Flex-Kasten das aus — zwischen den Reihen nicht, und dann stehen sieben Kacheln in zwei
 * Hoehen da. Der Wirt hat genau diese Tafel eingekringelt.
 *
 * Kein festes Mass: zwei Zeilen sind `2 x line-height`, und das waechst mit der Schrift des
 * Hauses mit. Das Wort steht mittig darin, ob es nun eine Zeile braucht oder zwei.
 */
.pay-method-btn > span {
    line-height: 1.2;
    min-height: 2.4em;
    display: flex;
    align-items: center;
    text-align: center;
}
.pay-method-btn { border-color: color-mix(in srgb, var(--pm-akzent, var(--djk-border)) 60%, transparent); }
.pay-method-btn .icon { width: 30px; height: 30px; color: var(--pm-akzent, inherit); }
.pay-method-btn:hover { border-color: var(--pm-akzent, var(--djk-yellow)); transform: translateY(-2px); }

/*
 * DIE LETZTE REIHE IST IMMER VOLL (09.09.2026, Ansage des Wirts).
 *
 * Drei Kacheln je Reihe. Bleibt am Ende EINE uebrig — „Personalessen" —, stand sie bisher
 * allein im linken Drittel und rechts daneben klaffte die Luecke; bleiben ZWEI uebrig, klaffte
 * ein Drittel. Der Wirt: *„если в ряду одна кнопка, то должна растянуться на всю ширину
 * и занять место трех кнопок … всегда ряд должен быть полным."*
 *
 * Das ist die RUECKNAHME des 08.09.2026, wo `flex: 1 1` zu `0 0` wurde, damit die einzelne
 * Kachel eben NICHT die ganze Breite nimmt. Der Unterschied zu damals: `1 1` haette bei zwei
 * uebrigen Kacheln BEIDE auf die Haelfte gedehnt — gewuenscht ist, dass die erste ihr Drittel
 * behaelt und nur die LETZTE den Rest nimmt. Deshalb kein `flex-grow`, sondern zwei Regeln,
 * die genau den Fall treffen.
 *
 * Die Rechnung: eine Spalte ist `33.333% - 7px`, die Luecke 10px. Zwei Spalten samt Luecke
 * dazwischen sind also `66.666% - 4px`, drei sind die volle Breite.
 */
.pay-method-btn:last-child:nth-child(3n + 1) { flex-basis: 100%; }
.pay-method-btn:last-child:nth-child(3n + 2) { flex-basis: calc(66.666% - 4px); }

/* Kassenbeleg: weiss/schwarzer Kassenbon-Look statt dunklem App-Theme, ueberall wiederverwendet
   (personal/verlauf.php-Modal, Admin-Gutscheine-Modal, admin/gutschein_beleg_print.php) — siehe
   dasselbe Muster in .admin-main-area/.auth-split-right (CSS-Variablen auf einem Scope-Container
   umdefinieren, keine andere Regel muss angefasst werden). */
/* source/style_css/140_receipts.css - style.css part 17 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Belege: überall dasselbe Bon-Aussehen ----------
   Ein Beleg soll aussehen wie der Zettel aus dem Drucker, egal ob er in der Kasse, in der
   Verwaltung oder auf der Bestell-Website erscheint: schmale Spalte, Schreibmaschinenschrift
   (damit Beträge exakt untereinander stehen), Sternchen-Linien, mittige Kopfzeile.
   Die Farbvariablen werden hier lokal auf hell umgestellt — ein Beleg ist immer schwarz auf
   weiß, auch wenn die Seite ringsum dunkel ist. */
.kassenbeleg-box {
    --djk-black-card: #ffffff;
    --djk-black-soft: #f7f7f7;
    --djk-white: #1c1c1c;
    --djk-gray: #6b6b6b;
    --djk-border: #d9d9d9;
    background: var(--djk-black-card);
    color: var(--djk-white);
    max-width: 360px;
    font-family: 'Courier New', Courier, monospace;
    font-size: 0.82rem;
    line-height: 1.55;
}
.kassenbeleg-box h3,
.kassenbeleg-box .beleg-titel {
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-family: inherit;
    font-size: 0.95rem;
    margin: 0 0 4px;
}
/* Sternchen-Linie wie auf dem gedruckten Bon. Bewusst als Inhalt und nicht als border:
   eine gepunktete Linie sieht am Bildschirm nach Formular aus, die Sternchenreihe nach Beleg.
   overflow:hidden schneidet die feste Zeichenkette sauber auf die Breite zu. */
.beleg-sterne {
    overflow: hidden;
    white-space: nowrap;
    text-align: center;
    color: var(--djk-gray);
    margin: 8px 0;
    user-select: none;
}
.beleg-sterne::after {
    content: "************************************************************";
    letter-spacing: 1px;
}
.beleg-zeile {
    display: flex;
    justify-content: space-between;
    gap: 12px;
}
.beleg-zeile > span:last-child { white-space: nowrap; }
.beleg-summe { font-weight: 700; }
.beleg-dank {
    text-align: center;
    color: var(--djk-gray);
    margin-top: 6px;
}
.modal-box.kassenbeleg-box { border-color: var(--djk-border); }

.kassenbeleg-positionen-table th, .kassenbeleg-positionen-table td { padding: 3px 4px; }
/* Spalten: 1 Pos | 2 Nr. | 3 Artikel | 4 Menge | 5 Preis. Nur der Artikelname darf umbrechen —
   Nummer, Menge und Preis gehören je auf eine Zeile. */
.kassenbeleg-positionen-table th:nth-child(2), .kassenbeleg-positionen-table td:nth-child(2),
.kassenbeleg-positionen-table th:nth-child(4), .kassenbeleg-positionen-table td:nth-child(4),
.kassenbeleg-positionen-table th:nth-child(5), .kassenbeleg-positionen-table td:nth-child(5) {
    white-space: nowrap;
}
.kassenbeleg-positionen-table td:nth-child(2) { font-variant-numeric: tabular-nums; }

/* pay-modal-search sitzt direkt auf demselben Element wie .input-icon.has-toggle (nicht als
   Wrapper darum) — Selektor deshalb mit allen drei Klassen kombiniert, sonst gewinnt die
   generische .input-icon.has-toggle input-Regel (padding-right:42px) durch höhere Spezifität.
   Werte 1:1 wie .kasse-search-bar .input-icon input (produktSearch), fürs identische Aussehen. */
.pay-modal-search { display: block; width: 100%; }
.input-icon.has-toggle.pay-modal-search input {
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    color: var(--djk-white);
    width: 100%;
    font-size: 1rem;
    /* Mit dem Suchfeld der Kopfleiste mitgezogen: der Kommentar darueber verspricht
       „Werte 1:1", und ein Versprechen, das nicht mehr stimmt, ist schlimmer als keines. */
    height: var(--kasse-bedien-h, 48px);
    padding: 0 14px 0 42px;
    border-radius: 5px;
    transition: border-color var(--transition);
}
.input-icon.has-toggle.pay-modal-search input:focus { outline: none; border-color: var(--djk-yellow); }

.gutschein-liste-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 12px 10px;
    border-bottom: 1px solid var(--djk-border);
    cursor: pointer;
}
.gutschein-liste-row:hover { background: rgba(59, 130, 246, 0.1); }

@media print {
    .no-print { display: none !important; }
}

.keypad-display {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: 6px;
    text-align: center;
    padding: 14px;
    background: var(--djk-black-soft);
    border-radius: 5px;
    margin: 14px 0;
    color: var(--djk-yellow);
    min-height: 1.4em;
}

.keypad-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}

.keypad-grid button {
    padding: 16px;
    font-size: 1.3rem;
    font-weight: 700;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-card);
    color: var(--djk-white);
    cursor: pointer;
    transition: border-color var(--transition);
}

.keypad-grid button:hover { border-color: var(--djk-yellow); }
.keypad-grid button.keypad-clear { color: var(--djk-danger); }

.mitglied-search-results {
    max-height: 220px;
    overflow-y: auto;
    margin-top: 10px;
}

.mitglied-search-results .result-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border-radius: 5px;
    cursor: pointer;
}

.mitglied-search-results .result-item:hover { background: rgba(59, 130, 246, 0.1); }

.kasse-categories {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 8px;
    margin-bottom: 16px;
    -webkit-overflow-scrolling: touch;
}

.kat-tab {
    flex-shrink: 0;
    padding: 9px 18px;
    border-radius: 5px;
    border: 2px solid var(--djk-border);
    background: var(--djk-black-card);
    color: var(--djk-white);
    font-weight: 700;
    font-size: 0.85rem;
    cursor: pointer;
    white-space: nowrap;
}

.kat-tab.active { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.12); color: var(--djk-yellow); }

/* auto-fill statt einer festen Spaltenzahl: die Kachelgröße bleibt konstant (~130px), die
   Spaltenzahl ergibt sich aus der verfügbaren Breite. So bleiben Kacheln über leicht
   unterschiedlich breite Handy-Displays hinweg gleich groß (kein unnötiges Strecken), passt
   aber automatisch eine weitere Spalte ein, sobald genug Platz dafür da ist — statt bei
   fester Spaltenzahl sichtbaren Leerraum zu lassen oder die Kacheln stark zu strecken. */
.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
    gap: 6px;
    margin-bottom: 20px;
}

.product-grid > .kueche-divider,
.product-grid > .kueche-section-divider {
    grid-column: 1 / -1;
}

/* Größen-Filter (z. B. Pizza 30/40 cm) — feste Button-Reihe oberhalb der Produkte einer
   Kategorie, die mindestens ein Produkt mit hinterlegten Größen hat (siehe kasse.js). */
.groessen-filter-row {
    display: none;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}

.groessen-filter-btn {
    flex-shrink: 0;
    padding: 8px 18px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: #3b82f6;
    color: #ffffff;
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
}

.groessen-filter-btn.active {
    border-color: var(--djk-yellow);
    color: var(--djk-black);
    background: var(--djk-yellow);
}

.product-tile {
    position: relative;
    /* Rahmenstärke und Rundung kommen aus der Verwaltung (Kasse → Ansicht). Ohne Einstellung
       stehen hier die Werte, mit denen die Kasse immer aussah: 1px und 2px. */
    border: var(--kasse-kachel-rahmen, 1px) solid transparent;
    border-radius: var(--kasse-kachel-rundung, 2px);
    overflow: hidden;
    padding: 8px;
    cursor: pointer;
    transition: border-color var(--transition), transform var(--transition);
}

/* KACHELHÖHE IM VERHÄLTNIS ZUR BREITE — Verwaltung: Kasse » Ansicht » "Kachelhöhe zur Breite".

   Ohne die Einstellung ist eine Kachel nur so hoch wie ihr Inhalt: stellt man weniger Spalten
   ein, werden die Kacheln zwar breiter, aber immer flacher. Ist die Einstellung an, wächst die
   Höhe mit der Breite mit.

   Warum overflow und min-width danebenstehen (im Browser gemessen, nicht geraten):
   aspect-ratio allein LEGT die Höhe fest und schneidet lange Produktnamen ab. Erst ohne
   Zuschnitt greift die automatische Mindesthöhe des Rasterfeldes — dann ist die Kachel so
   hoch wie die Form ODER wie ihr Inhalt, je nachdem, was mehr ist. min-width:0 gehört dazu,
   sonst zieht dieselbe Automatik die Spalten in die Breite. Die naheliegenden Wege
   min-height:fit-content, max-content und 100% scheitern alle daran, dass der Browser die
   Inhaltshöhe dann über dieselbe Form zurückrechnet.

   Nebenwirkung, bewusst in Kauf genommen: eine Kachel mit sehr langem Namen wird höher als
   ihre Nachbarn in derselben Zeile — unter den Nachbarn bleibt dann etwas Luft. */
body.kasse-kachel-form .product-tile:not(.kategorie-tile):not(.tisch-tile) {
    aspect-ratio: var(--kasse-kachel-form, auto);
    /* `visible` MUSS bleiben: mit `hidden` schneidet die feste Form alles ab, was nicht
       hineinpasst — am 12.08. war der Preis unten zur Haelfte weg. Sichtbar heisst hier: die
       Form ist ein MINDESTMASS, die Kachel darf hoeher werden, wenn Name und Preis mehr
       brauchen. Gleich hoch bleiben die Kacheln trotzdem, weil der Name unten eine feste
       Zeilenzahl belegt. */
    overflow: visible;
    min-width: 0;
}

/* Kein `align-items: stretch` hier — das war ein Fehlgriff am 12.08.: zusammen mit der festen
   Form (aspect-ratio) rechnet der Browser aus der gestreckten HOEHE die Breite zurueck, und
   eine Reihe stand ploetzlich schmaler da als die andere (220 px gegen 202 px).
   Gleich hoch werden die Kacheln einer Reihe stattdessen dadurch, dass der Name unten immer
   dieselbe Zeilenzahl belegt — gleicher Inhalt, gleiche Hoehe, und die Breite bleibt die der
   Spalte. */

.product-tile-badge {
    position: absolute;
    top: 5px;
    right: 5px;
    /* 22 statt 20: eingestellt und eingekringelt vom Wirt. Zwei Pixel klingen nach nichts, aber
       eine zweistellige Zahl sass vorher am Rand ihres Kreises. */
    min-width: 22px;
    height: 22px;
    padding: 0 5px;
    border-radius: 999px;
    /* Farbe aus der Verwaltung (Produkte → Kategorien → Zeichen auf der Produktkachel).
       Der Rückfallwert ist genau das bisherige Aussehen. */
    background: var(--kasse-badge-grund, var(--djk-yellow));
    color: var(--kasse-badge-schrift, var(--djk-black));
    font-size: 0.72rem;
    font-weight: 800;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

.product-tile-minus-btn {
    position: absolute;
    bottom: 5px;
    right: 5px;
    width: 36px;
    height: 36px;
    border-radius: 999px;
    border: none;
    background: var(--kasse-minus-grund, var(--djk-danger));
    color: var(--kasse-minus-schrift, #fff);
    font-size: 1.5rem;
    font-weight: 800;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
    cursor: pointer;
}

.product-tile:hover { border-color: var(--djk-yellow); transform: translateY(-2px); }
.product-tile.tile-added { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.15); }
.product-tile.in-cart { border-color: var(--djk-blue-light); }

.product-tile-photo {
    width: 100%;
    aspect-ratio: 1;
    /* Kein eigener Hintergrund: bei einer Kategorie-Farbe soll die Kachel komplett
       durchgefärbt wirken, nicht nur der Bereich unter dem Namen/Preis. Ohne Foto
       scheint so der Farbverlauf der Kachel (.product-tile) auch hier durch. */
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.product-tile-photo img { width: 100%; height: 100%; object-fit: cover; }
.product-tile-photo .icon { width: 28px; height: 28px; color: var(--djk-gray); }
/* Schrift und Größe kommen aus der Verwaltung (Einstellungen → Kasse → Zeichen & Farben).
   Ohne Einstellung greift der zweite Wert im `var()` — dann steht hier, was immer hier stand.
   Der Produktname ist der Grundfall; die Kategorie überschreibt ihn weiter unten mit ihrer
   eigenen Variablen, denn beide teilen sich diese Klasse. */
.product-tile-name {
    font-size: var(--kasse-schrift-produkt-groesse, 0.78rem);
    font-family: var(--kasse-schrift-produkt, inherit);
    font-weight: 700;
    padding: 8px 6px 2px;
    line-height: 1.25;
}
/*
 * Geschnitten wird am INNEREN Element, nicht am Namen selbst.
 *
 * Die Kachel ist eine Flex-Spalte, und ein Kind einer Flex-Spalte wird "blockifiziert": aus
 * `display: -webkit-box` macht der Browser `flow-root`, und `-webkit-line-clamp` greift nicht
 * mehr. Gemessen am 12.08.: der Name stand mit 52 px (vier Zeilen) da, obwohl drei eingestellt
 * waren. Ein eigener Kasten um den Text ist kein Kind der Flex-Spalte und wird geschnitten.
 */
.product-tile-name > .ptn-text {
    display: -webkit-box;
    -webkit-line-clamp: var(--kasse-kachel-namenszeilen, 2);
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* Genauso viele Zeilen HOCH, auch wenn der Name kuerzer ist — sonst waere "Gavros" eine
       Zeile hoch und die Nachbarin zwei: die Treppe, die weg soll. Die Mindesthoehe gehoert
       an den TEXT und nicht an .product-tile-name: dort sitzt darueber noch die Speisenummer
       in einer eigenen Zeile, und die zaehlte mit. */
    min-height: calc(var(--kasse-kachel-namenszeilen, 2) * 1.25em);
}

/* Einstellungen: "Fotos in der Kasse anzeigen" — getrennt für Produkte/Kategorien/Tische,
   da z. B. Tisch-Fotos gewünscht sein können, Produkt-Fotos aber nicht. Platz für das Foto
   komplett weglassen (nicht nur Bild verstecken), damit die Kachel kompakt nur Name/Preis zeigt. */
body.kasse-no-fotos-produkte .product-tile:not(.kategorie-tile):not(.tisch-tile) .product-tile-photo { display: none; }
body.kasse-no-fotos-produkte .product-tile:not(.kategorie-tile):not(.tisch-tile) .product-tile-name { padding-top: 14px; }
body.kasse-no-fotos-kategorien .kategorie-tile:not(.tisch-tile) .product-tile-photo { display: none; }
body.kasse-no-fotos-kategorien .kategorie-tile:not(.tisch-tile) .product-tile-name { padding-top: 14px; }
body.kasse-no-fotos-tische .tisch-tile .product-tile-photo { display: none; }
body.kasse-no-fotos-tische .tisch-tile .product-tile-name { padding-top: 14px; }
/* Speisenummer: Grösse und Farbe aus Verwaltung → Kasse → Ansicht („Speisenummer") und je
   Bildschirm-Band (includes/kasse_schriften.php, kasse_bereiche.php). Ohne Eingabe gibt es
   keine Variable, und der alte Wert gilt — die Farbe folgt dann weiter dem Thema. */
.product-tile-nummer { display: block; color: var(--kasse-nummer-farbe, var(--djk-gray)); font-weight: 600; font-size: var(--kasse-nummer-groesse, 0.68rem); }
/* Preisfarbe aus der Verwaltung (Produkte → Kategorien → Zeichen auf der Produktkachel). */
.product-tile-price {
    font-size: var(--kasse-schrift-preis-groesse, 0.8rem);
    font-family: var(--kasse-schrift-preis, inherit);
    font-weight: 800;
    color: var(--kasse-preis, var(--djk-yellow));
    padding: 0 6px 10px;
}

/* source/style_css/145_receipts_continued.css - style.css: receipts continued, part 18 of 78 (built by werkzeuge/parts_build.php) */
.kasse-search-bar {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 10px;
    /* Dasselbe dunkle Band wie auf dem Handy — vorher stand hier Weiss, und damit war die
       Leiste auf dem grossen Bildschirm in BEIDEN Erscheinungsbildern hell, obwohl Schrift,
       Platzhalter und Lupe darin fest hell gesetzt sind (siehe unten bei den Eingabefarben).
       Die Regel darunter im @media (max-width: 1199px) faerbte nur das Handy dunkel; der
       Bildschirm blieb uebersehen.

       `background-color` statt der Kurzform `background`: die Kurzform setzt auch
       background-image zurueck — an dieser Datei ist genau das schon einmal aufgefallen
       (der verschwundene Auswahlpfeil im dunklen Erscheinungsbild). */
    background-color: var(--kasse-leiste);
    /* Ein Zustandszeichen schweigt, solange alles in Ordnung ist (22.08.2026).
       Vorher 2px in der Akzentfarbe. Der Wirt hat gefragt, was die Linie bedeutet — und wenn
       man das fragen muss, bedeutet sie nichts. Bei „kein Internet" wird ohnehin die GANZE
       Leiste dunkelrot (body.kasse-kein-netz weiter unten); die Linie trug das Zeichen nie
       allein. Jetzt derselbe stille Strich wie zwischen den anderen Bloecken. */
    border-bottom: 1px solid var(--djk-border);
    /*
     * PLUS, NICHT MAX (22.09.2026, am Geraet nachgemessen).
     *
     * Oben stand `max(12px, env(safe-area-inset-top))`. Bei einer SEITLICHEN sicheren Zone
     * ist das richtig — die ist meistens 0, und `max` haelt dann die gewohnten 8 px. Oben
     * ist sie NIE 0: auf einem Android-Geraet sind es rund 24 bis 28 Punkte fuer die Uhr
     * und die Zeichen. `max(12, 28)` ergibt 28 — also genau die Hoehe der Systemleiste und
     * keinen Punkt mehr. Die Suchzeile klebte damit unmittelbar unter der Uhr.
     *
     * Im BROWSER faellt das nicht auf: dort ist `env()` 0, `max(12, 0)` ist 12, und die
     * Leiste hat ihre Luft. Das Programm bekam als einziges die falsche Fassung — und
     * genau danach war gefragt: nimmt das Programm dieselben Masse wie der Browser?
     *
     * Die Huelle schiebt den Inhalt NICHT selbst herunter: mit `viewport-fit=cover` und
     * einem WebView ab Fassung 140 reicht Capacitor die Zone an die Seite durch und
     * erwartet, dass die Seite sie einrechnet (SystemBars.java, shouldPassthroughInsets).
     */
    padding: calc(12px + env(safe-area-inset-top, 0px)) 12px 12px;
    transition: background-color 0.25s ease, border-color 0.25s ease;
}

/* source/style_css/150_register_welcome_offline.css - style.css part 19 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Begrüßung beim Öffnen der Kasse ----------
   Dauer steht als --kasse-gruss-dauer am Element (Verwaltung → Kasse → Ansicht).

   Sie geht per ANIMATION weg, nicht per Skript. Ein Vorhang über der ganzen Kasse, der auf ein
   setTimeout in kasse.js angewiesen wäre, bliebe bei jedem Fehler davor für immer liegen — und
   damit läge die Kasse still. Die letzten 25 % der Zeit sind das Ausblenden; danach hält
   `forwards` sie unsichtbar und `visibility: hidden` gibt die Klicks wieder frei. */
.kasse-begruessung {
    position: fixed;
    inset: 0;
    z-index: 99998;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--kasse-leiste);
    animation: kasseGrussWeg var(--kasse-gruss-dauer, 2s) ease forwards;
}
.kasse-begruessung.weg { animation: none; opacity: 0; visibility: hidden; }
/* Schon begrüßt in dieser App-Sitzung (siehe das kleine Skript in personal/kasse.php):
   dann gar nicht erst zeichnen — auch keine Animation, die 25 % ihrer Zeit deckend wäre. */
html.kasse-gruss-gesehen .kasse-begruessung { display: none; }
@keyframes kasseGrussWeg {
    0%   { opacity: 1; visibility: visible; }
    75%  { opacity: 1; visibility: visible; }
    100% { opacity: 0; visibility: hidden; }
}
.kasse-begruessung-inhalt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 24px;
    text-align: center;
}
.kasse-begruessung-logo,
.kasse-begruessung .logo-badge {
    width: 92px;
    height: 92px;
    font-size: 1.6rem;
}
.kasse-begruessung-name {
    font-size: 1.35rem;
    font-weight: 800;
    color: #f8fafc;
    letter-spacing: 0.01em;
}
.kasse-begruessung-gruss {
    font-size: 1rem;
    font-weight: 600;
    color: var(--djk-yellow);
}
/* Ein Balken, der einmal durchläuft — er sagt "es baut sich auf", ohne einen Fortschritt zu
   behaupten, den niemand misst. */
.kasse-begruessung-balken {
    width: 160px;
    height: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.15);
    overflow: hidden;
    margin-top: 4px;
}
.kasse-begruessung-balken span {
    display: block;
    width: 40%;
    height: 100%;
    border-radius: 999px;
    background: var(--djk-yellow);
    animation: kasseGrussBalken 1.1s ease-in-out infinite;
}
@keyframes kasseGrussBalken {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(260%); }
}

/* ---------- Kein Internet ----------
   Die Kasse arbeitet ohne Verbindung weiter (Buchungen gehen in die Outbox auf dem Gerät),
   aber sie sagt es: die obere Leiste wird rot und bleibt es, solange nichts durchkommt.
   Ein Zustand, der die Arbeit nicht anhält, braucht ein Zeichen, das man nicht übersieht —
   sonst merkt es niemand, bis der Feierabend die Buchungen vermisst.
   Nur die FLÄCHE wechselt; Knöpfe und Suchfeld darin bleiben, wie sie sind. */
body.kasse-kein-netz .kasse-search-bar {
    background-color: #8f1d1d;
    border-bottom-color: #ef4444;
    /* Der Hinweis bekommt eine eigene Zeile unter den Knöpfen. Auf dem grossen Bildschirm
       läuft die Leiste sonst ohne Umbruch — deshalb wird er NUR in diesem Zustand erlaubt,
       damit sich am normalen Aufbau nichts ändert. */
    flex-wrap: wrap;
}
.kasse-netz-hinweis {
    display: none;
    flex: 1 1 100%;
    order: 99;
    margin-top: 4px;
    padding: 7px 12px;
    border-radius: 5px;
    background: rgba(0, 0, 0, 0.28);
    color: #fff;
    font-size: 0.85rem;
    font-weight: 700;
    text-align: center;
    line-height: 1.35;
}

.kasse-search-input { flex: 1; }

/* Mobil: die Icon-Buttons (Tische/Küche/Bar) drängen das Suchfeld sonst auf eine
   unlesbare Restbreite zusammen — Suchfeld auf eine eigene volle Zeile unter die Icons
   umbrechen, noch innerhalb derselben (gelb umrandeten) Suchleiste. */
@media (max-width: 1199px) {
    .kasse-search-bar { flex-wrap: wrap; }
    .kasse-search-input { order: 5; flex: 1 1 100%; }
    /*
     * Feste statt nur maximale Breite: der Tisch-Name/-Nummer wechselt ständig zwischen
     * "Tische" und z. B. "#101", ohne feste Breite springt der Button dabei mit.
     *
     * ABER NICHT BEI EINEM NAMEN (05.09.2026, gemessen bei 412 px).
     *
     * Weiter unten steht die Absicht ausdrücklich: „Der Tisch-Knopf trägt seinen Namen ganz
     * — abgeschnittenes 'Tis...' sieht kaputt aus." Auf dem Telefon hielt diese Regel nicht:
     * `width: 110px` hat höhere Spezifität, und auf der Zeche von „Manana Moumou" stand im
     * Knopf „Manana M" — mitten im Namen abgeschnitten. Der Kellner sah den Menschen nicht
     * mehr, auf dessen Rechnung er gerade bucht.
     *
     * Deshalb: eine Zahl bleibt bei 110 (nichts springt), ein NAME darf wachsen — aber nur,
     * so weit die Reihe reicht. GEMESSEN bei 412 px: „Manana Moumou" braucht rund 200 px,
     * und dann bricht die Leiste um; der QR-Knopf rutschte in eine zweite Zeile und fraß
     * eine Zeile Bildschirm. Der Name geht dabei NICHT verloren: er steht die ganze Zeit
     * unten in der Warenkorb-Leiste („Tisch MG-16 – Manana Moumou"). Der Knopf oben darf
     * ihn also kürzen — mit „…" statt mitten im Wort, damit man sieht, dass da mehr steht.
     * Im Kellner-Programm steht dazu `widthIn(min = 110.dp, max = 150.dp)` samt Ellipsis —
     * dieselbe Regel.
     */
    .kasse-tische-btn#tischeBtn { width: 110px; }
    .kasse-tische-btn#tischeBtn.has-mitglied { width: auto; min-width: 110px; max-width: 150px; }
    .kasse-tische-btn#tischeBtn.has-mitglied #activeTischLabel {
        overflow: hidden; text-overflow: ellipsis;
    }
    /*
     * DER TISCH-KNOPF FUELLT DIE REIHE (25.09.2026, der Wirt: „если какие-то отсутствуют, кнопка
     * стола должна расширяться, чтобы всегда вся ширина полная"). Die Knoepfe rechts (Kueche, Bar,
     * QR, ...) behalten ihr Quadrat und stehen rechts; der Tisch nimmt, was bleibt. Fehlt einer,
     * waechst der Tisch; kommt einer dazu, wird er schmaler. Nie unter 110 px.
     */
    .kasse-search-bar .kasse-tische-btn#tischeBtn,
    .kasse-search-bar .kasse-tische-btn#tischeBtn.has-mitglied {
        flex: 1 1 110px; width: auto; min-width: 110px; max-width: none;
    }
    .kasse-search-bar .kasse-tische-btn#tischeBtn #activeTischLabel {
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
}

/* Mobil (<1200px, siehe Desktop-3-Spalten-Layout weiter unten): Kopfleiste (Suche/Icons) und
   Warenkorb-Leiste sollen fix stehen bleiben, nur das Produktraster dazwischen scrollt. Ohne
   das rollt der ganze Body — beim Überziehen (Pull-to-Refresh-Geste) zieht das den ganzen
   Bildschirminhalt mit und reißt oben/unten kurz weißen Leerraum auf (kein eigenes Scroll-Ziel
   mehr vorhanden). body.kasse-body wird per position:fixed komplett aus dem Dokumentfluss
   genommen; #kasseProductsSection ist damit der einzige tatsächlich scrollende Bereich. */
@media (max-width: 1199px) {
    body.kasse-body {
        position: fixed;
        /* inset:0 (top/right/bottom/left je 0) reicht allein schon aus, um exakt auf den
           sichtbaren Viewport zu strecken — ganz ohne eigene Höhenangabe. Ein zusätzliches
           height:100dvh (frühere Fassung) kann in installierten PWAs (standalone, iOS) leicht
           von der tatsächlich sichtbaren Höhe abweichen; da top+bottom+height für ein
           position:fixed-Element "overconstrained" sind, gewinnt dann height und bottom wird
           neu berechnet — sichtbar als schmaler Streifen unter der eigentlich fixen unteren
           Leiste. Ohne explizite Höhe kann das nicht mehr passieren. */
        inset: 0;
        /*
         * DER EIGENTLICHE GRUND, WARUM AUF DEM IPHONE DIE KNOEPFE UNTEN FEHLTEN
         * (01.09.2026, dritter Anlauf — die ersten beiden haben nur die Wirkung bekaempft).
         *
         * Ganz oben in dieser Datei steht fuer JEDE Seite `body { min-height: 100vh }`.
         * Auf dem iPhone ist `100vh` die GROSSE Ansicht (die ohne Browserleisten) — auf dem
         * Geraet des Wirts gemessen: `100lvh` = 874, `100dvh` = `visualViewport.height` = 812.
         *
         * Und `min-height` schlaegt `height`. Die Zeile weiter unten gab dem Koerper also
         * brav 812, und diese eine geerbte Zeile machte daraus wieder 874 — bei `top: 0`
         * reicht er damit 62 Punkte unter den Bildschirmrand. GEMESSEN am Bildschirmfoto
         * seines Telefons: die Kante der Warenkorb-Leiste sitzt auf 778, „Bezahlen" beginnt
         * auf 823 und muesste auf 878 enden — der Bildschirm hoert bei 874 auf. Genau die
         * 62 Punkte, und genau die Haelfte eines Knopfes, die er gesehen hat.
         *
         * Warum es zwei Anlaeufe gedauert hat: `100dvh` und `visualViewport` waren beide
         * RICHTIG (beide melden 812) — sie kamen nur nie zum Zug. Gefunden hat es erst ein
         * Messblatt mit denselben Regeln, aber OHNE diese geerbte Zeile: dort stimmte alles.
         *
         * Der Koerper steht hier auf `position: fixed` mit `inset: 0`; eine Mindesthoehe
         * kann ihm nichts Gutes tun und nur, wie hier, seine Hoehe uebersteuern.
         */
        min-height: 0;
        width: 100%;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        /* Kasse hat keine .bottom-nav (eigene kasse-bottom-bar übernimmt das) — die globale
           Reserve dafür (siehe body { padding-bottom } weiter oben) würde hier nur eine leere
           Lücke unter der Warenkorb-Leiste aufreißen. */
        padding-bottom: 0;
        background: var(--djk-black);
    }

    /*
     * DAS IPHONE LEGT SEINE EIGENE LEISTE UEBER DEN FUSS (01.09.2026).
     *
     * Der Wirt: „на самсунге подошло, но на айфоне ушли вниз — половина кнопок видно."
     *
     * `position: fixed; inset: 0` spannt auf den LAYOUT-Viewport. Auf Android ist der so
     * gross wie das Sichtbare; in Safari auf dem iPhone ist er GROESSER, solange die
     * Bedienleiste des Browsers eingeblendet ist — der untere Rand der Kasse liegt dann
     * hinter dieser Leiste, und von der Knopfreihe sieht man die obere Haelfte.
     *
     * `100dvh` ist die Hoehe, die WIRKLICH sichtbar ist, und sie waechst und schrumpft mit
     * der Leiste. `bottom: auto` gehoert dazu: top + bottom + height zugleich waeren
     * ueberbestimmt, und dann gewinnt die Hoehe und der untere Rand wird neu gerechnet —
     * genau der schmale Streifen, vor dem der Absatz darueber warnt.
     *
     * Nur fuer WebKit: `-webkit-touch-callout` gibt es ausschliesslich dort. Android bleibt
     * damit unberuehrt — dort stimmt es seit dem 31.08., und eine Aenderung koennte nur
     * schaden.
     */
    @supports (-webkit-touch-callout: none) {
        body.kasse-body {
            bottom: auto;
            /*
             * DIE HOEHE, DIE WIRKLICH ZU SEHEN IST.
             *
             * ACHTUNG, WER HIER ETWAS AENDERT: diese Zeile war NIE falsch. Auf dem iPhone
             * des Wirts gemessen melden `100dvh` und `visualViewport.height` beide 812 —
             * richtig. Sie kam nur nicht zum Zug, weil `body { min-height: 100vh }` aus dem
             * Kopf dieser Datei daraus wieder 874 machte. Siehe `min-height: 0` oben; ohne
             * das ist jede Hoehe hier wirkungslos.
             *
             * `visualViewport` statt `100dvh`, weil der Browser damit nicht gerechnet,
             * sondern GEFRAGT wird: es ist die Flaeche, die er selbst als sichtbar meldet,
             * und sie folgt seinen Leisten ohne den bekannten Nachlauf von `dvh`.
             * `kasse.js` schreibt sie fort; `100dvh` bleibt der Rueckweg fuer alles, was
             * `visualViewport` nicht kennt (iOS vor 13).
             *
             * Die Regel steht NUR in diesem @supports-Block: gemessen kennt Chrome
             * `-webkit-touch-callout` nicht (`CSS.supports(...) = false`), Android bleibt
             * also unberuehrt — dort stimmt es seit dem 31.08.
             */
            height: var(--kasse-sicht-hoehe, 100dvh);
        }
    }
    body.kasse-body .kasse-search-bar { flex: 0 0 auto; position: static; }
    body.kasse-body #kasseProductsSection {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        background: linear-gradient(180deg, #eff6ff 0%, #ffffff 65%);
    }
    /* Wie .kasse-search-bar: aus position:fixed heraus und als normales Flex-Kind ans Ende
       von body.kasse-body (100dvh, position:fixed) gehängt. Ein eigenständiges
       position:fixed;bottom:0 auf dieser Leiste richtet sich sonst nach dem Layout-Viewport
       statt dem tatsächlich sichtbaren (dvh-bewussten) Viewport — auf manchen mobilen Browsern
       (ein-/ausblendende Adressleiste) blieb dadurch ein sichtbarer Spalt unter der Leiste. */
    body.kasse-body .kasse-bottom-bar { flex: 0 0 auto; position: static; }

    /* source/style_css/155_register_welcome_offline_continued.css - style.css: register welcome offline continued, part 20 of 78 (built by werkzeuge/parts_build.php) */
    /*
     * Aufgezogen nimmt der Warenkorb den GANZEN Bildschirm ein.
     *
     * Nicht über `position: fixed` — genau davor warnt der Absatz darüber (Adressleiste,
     * dvh). Stattdessen räumen die beiden Geschwister in der Spalte den Platz, und die Leiste
     * nimmt ihn: `flex: 1 1 auto`. Der Produktbereich behält dabei seine Rollhöhe (nur auf 0
     * gedrückt), damit er nach dem Zuklappen wieder dort steht, wo man ihn verlassen hat.
     *
     * Die Klasse sitzt am body, weil die Geschwister von der Leiste aus nicht erreichbar sind;
     * kasse.js setzt und nimmt sie zusammen mit `expanded`.
     */
    body.kasse-body .kasse-bottom-bar.expanded {
        /*
         * Über die ganze Fläche: der Körper der Kasse ist hier ein Raster aus zwei Spalten und
         * drei Reihen (Suchleiste / Kategorien+Produkte / Leiste). Aufgezogen belegt die Leiste
         * alle Felder auf einmal.
         *
         * Die Geschwister bleiben stehen und werden nur verdeckt — sie auszublenden wäre
         * verlockend, würde aber die Fenster mitnehmen, die IN der linken Spalte hängen
         * (Kategorien, Tische, Artikel-Fenster). Der Knopf "Warengruppe" sitzt in der
         * aufgezogenen Leiste; sein Fenster muss aufgehen können.
         */
        grid-row: 1 / -1;
        grid-column: 1 / -1;
        z-index: 60;
        /* Was noch draussen ist, bleibt unsichtbar — sonst schoebe sich die Summe beim
           Hereingleiten über die Suchleiste. */
        overflow: hidden;
        padding-top: calc(6px + env(safe-area-inset-top, 0px));
        min-height: 0;
        display: flex;
        flex-direction: column;
        /*
         * Die Fläche SELBST ist durchsichtig — die Farbe liegt im ::before darunter.
         *
         * Der Wirt: „когда двигались, сзади касса виднелась." Aufgezogen soll die dunkle Fläche
         * also erst MIT den Blöcken kommen, nicht vor ihnen. Warum über die Deckkraft eines
         * eigenen Elements und nicht über `background-color`: eine Farbe auf bildschirmgrosser
         * Fläche muss der Browser in JEDEM Bild neu malen, und das hat gemessen sichtbar
         * geruckelt. Eine Deckkraft erledigt die Grafikeinheit, ohne etwas neu zu malen.
         *
         * Rand und Schatten fallen aufgezogen weg: sie kosten dieselbe Malerei und haben auf
         * einer bildschirmfüllenden Fläche nichts zu begrenzen.
         */
        background-color: transparent;
        border-top-color: transparent;
        box-shadow: none;
    }
    /*
     * Die dunkle Fläche als eigene Ebene HINTER dem Inhalt.
     *
     * Sie entsteht erst mit `.expanded` — und weil dabei auch `.korb-eingang` steht, beginnt sie
     * bei Deckkraft 0, ohne dass dafür etwas festgeschrieben werden müsste (ein frisch
     * entstandenes Element bewegt sich nicht auf seinen Anfangswert zu). Fällt `.korb-eingang`
     * weg, dunkelt sie in derselben Zeit nach, in der die Blöcke hereingleiten.
     */
    body.kasse-body .kasse-bottom-bar.expanded::before {
        content: '';
        position: absolute;
        inset: 0;
        z-index: -1;
        background: var(--djk-black-card);
        opacity: 1;
        transition: opacity var(--korb-dauer-unten) var(--korb-kurve);
        pointer-events: none;
    }
    body.kasse-body .kasse-bottom-bar.expanded.korb-eingang::before { opacity: 0; }
    /* Beim AUFZIEHEN kommt der dunkle Grund erst zum Schluss (26.09.2026, Foto des Wirts: „beim
       Oeffnen ist der Hintergrund da, beim Schliessen nicht - so ist es schoen"). Die Kasse bleibt
       sichtbar, waehrend die Bloecke hereingleiten; der Grund dunkelt im letzten Drittel nach.
       Nur fuer das Oeffnen: beim Zuziehen (`korb-eingang` kommt dazu) greift diese Regel nicht,
       der Grund geht also sofort mit. */
    body.kasse-body .kasse-bottom-bar.expanded:not(.korb-eingang)::before {
        transition: opacity calc(var(--korb-dauer-unten) * 0.35) ease-out calc(var(--korb-dauer-unten) * 0.65);
    }
    /*
     * WÄHREND der Bewegung greift der Finger hindurch.
     *
     * Zugeklappt wird über eine Bewegung, und bis die zu Ende ist, trägt die Leiste weiter
     * `expanded` — sie liegt also noch über dem ganzen Bildschirm. Da man jetzt die Kasse
     * dahinter SIEHT, tippt man auch darauf; ohne das hier versackte der Tipp in der
     * durchsichtigen Leiste, und die Kasse wirkte tot.
     */
    body.kasse-body .kasse-bottom-bar.expanded.korb-eingang { pointer-events: none; }
    /*
     * 25 zu 75 — und zwar genau.
     *
     * Die beiden Teile bekommen `flex-basis: 0` und die Wachstumszahlen 25 und 75: dann teilt
     * der Browser den Platz, der nach Kopfzeile und Knopfreihe übrig ist, in genau diesem
     * Verhältnis auf. Eine ausgerechnete Höhe in Pixeln käme nie ganz hin — Innenabstände und
     * Rundungen verschieben sie um ein paar Prozent, und die Knopfreihe ist mal ein-, mal
     * zweizeilig.
     */
    body.kasse-body .kasse-bottom-bar.expanded .kasse-summe-gross {
        flex: 25 1 0;
        height: auto;
        min-height: 0;
    }
    /*
     * Die blaue Oberkante fährt MIT.
     *
     * Zugeklappt trägt die Leiste selbst den Strich (`.kasse-bottom-bar { border-top }`) — das
     * ist die Linie, an der die Kasse aufhört und der Warenkorb anfängt. Aufgezogen ist die
     * Leiste bildschirmfüllend und ihr Rand deshalb abgeschaltet; damit verschwand die Linie
     * genau in dem Moment, in dem der Block unterwegs ist. Der Wirt hat die beiden Zustände
     * nebeneinandergelegt und gefragt, was da fehlt.
     *
     * Sie gehört an den KOPF: der wandert mit der Liste, also wandert die Linie mit ihm — und
     * unterwegs sieht der Block aus wie die zugeklappte Leiste, nur weiter oben. Der Schatten
     * dazu, aus demselben Grund.
     */
    /*
     * Die SEITEN fahren mit.
     *
     * Die Leiste ist 14 px links und rechts gepolstert; Kopf, Liste und Knopfreihe stehen also
     * innerhalb davon. Aufgezogen ist die Fläche selbst durchsichtig (die Farbe liegt im
     * ::before und dunkelt erst nach) — und damit blieben genau diese beiden Streifen leer,
     * solange der Block unterwegs war. Der Wirt: „бока так же пустые спускаются и в конце
     * заполняются."
     *
     * Gelöst mit zwei Schlagschatten ohne Weichzeichnung: das ergibt links und rechts je ein
     * volles Band in der Farbe der Leiste, gemalt VOM BLOCK SELBST — es fährt also mit ihm und
     * ist da, sobald er da ist. Kein Platzbedarf, keine Verschiebung, und die Grafikeinheit malt
     * es zusammen mit dem Block (eine Breite oder ein Rand hätte das Raster neu gerechnet).
     *
     * Nur zur Seite, nicht nach oben: über dem Kopf soll die Kasse weiter durchscheinen, und
     * ein Band oberhalb der blauen Kante sähe aus, als sei sie nicht mehr die Oberkante.
     */
    body.kasse-body .kasse-bottom-bar.expanded .kasse-cart-summary,
    body.kasse-body .kasse-bottom-bar.expanded .cart-list,
    body.kasse-body .kasse-bottom-bar.expanded .kasse-bottom-actions {
        --korb-seitenband: -14px 0 0 0 var(--djk-black-card), 14px 0 0 0 var(--djk-black-card);
        box-shadow: var(--korb-seitenband);
    }
    body.kasse-body .kasse-bottom-bar.expanded .kasse-cart-summary {
        border-top: 2px solid var(--djk-yellow);
        /* Die blaue Kante braucht ihren Schatten nach oben — dazu die beiden Seitenbänder. */
        box-shadow: var(--korb-seitenband), 0 -4px 16px rgba(0, 0, 0, 0.45);
    }
    body.kasse-body .kasse-bottom-bar.expanded .cart-list {
        flex: 75 1 0;
        height: auto;
        max-height: none;
        min-height: 0;
        overflow-y: auto;
    }
}

.kasse-search-bar .input-icon input {
    /* Dunkles Feld, in beiden Erscheinungsbildern: die Suche ist der einzige Ort in der oberen
       Leiste, in den man hineinschreibt — sie soll sich von den Knöpfen daneben absetzen. */
    background: #3d414c;
    border: 1px solid var(--djk-border);
    color: var(--djk-white);
    width: 100%;
    font-size: 1rem;
    /* Dieselbe Hoehe wie der Tisch-Knopf daneben. Das senkrechte Polster faellt dafuer
       weg — links bleiben die 42 fuer die Lupe. */
    height: var(--kasse-bedien-h, 48px);
    padding: 0 14px 0 42px;
    border-radius: 5px;
    transition: border-color var(--transition);
}

.kasse-search-bar .input-icon input:focus {
    outline: none;
    border-color: var(--djk-yellow);
}

/* source/style_css/160_register_top_bar.css - style.css part 21 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* EIN Mass fuer die obere Leiste (22.08.2026): der Tisch-Knopf stand auf festen 44,
   das Suchfeld kam ueber Schrift und Polster auf 49. Nebeneinander fiel das auf.
   48 liegt ueber dem Daumenmass und laesst die Leiste, wie sie war. */
:root { --kasse-bedien-h: 48px; }
.kasse-tische-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    height: var(--kasse-bedien-h, 48px);
    padding: 0 12px;
    border-radius: 5px;
    border: 2px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-weight: 700;
    font-size: 0.78rem;
    cursor: pointer;
    max-width: 110px;
}

.kasse-tische-btn .icon { width: 20px; height: 20px; flex-shrink: 0; }
.kasse-tische-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kasse-tische-btn:hover { border-color: var(--djk-yellow); }
.kasse-tische-btn.has-active { border-color: var(--djk-yellow); color: var(--djk-yellow); background: rgba(59, 130, 246, 0.12); }

/* DIESELBEN DREI FARBEN WIE AUF DER KACHEL (03.09.2026, Ansage des Wirts).

   Rot: in Kueche oder Bar liegt noch etwas. Gruen: alles ausgegeben, es fehlt nur die Zahlung.
   Blau (das `has-active` von oben) heisst weiter „nichts offen" — deshalb steht `tisch-frei`
   hier gar nicht, es waere dieselbe Farbe zweimal.

   NACH `.has-active`, gleiche Staerke: sonst bliebe der Knopf blau. Und die Schrift fest
   weiss, wie bei der Kachel — im hellen Erscheinungsbild ist `--djk-white` fast schwarz. */
/*
 * DIESELBEN DREI FARBEN WIE IM GRUNDRISS (10.09.2026).
 *
 * Der Zustand eines Tisches steht an VIER Stellen im Stilblatt: im Grundriss
 * (`.tp-view-tisch`), auf der Kachel ohne Grundriss (`.tisch-tile`), auf dem Knopf der
 * Tischliste (`.kasse-tische-btn`) und auf dem Merkzeichen einer Gruppe (`.tisch-kat-chip`).
 *
 * Alle vier zeigen DENSELBEN Zustand demselben Menschen, oft nebeneinander. Faerbte man nur
 * eine um, hiesse Rot auf dem einen Bildschirm etwas anderes als Bernstein auf dem naechsten
 * — und niemand koennte sagen, welches die Wahrheit ist.
 *
 * Bernstein ist hell: die Schrift darauf ist dunkel (7,21 : 1 gegen weiss 2,19).
 */
.kasse-tische-btn.tisch-bereit {
    border-color: #62c0e0;
    background: linear-gradient(150deg, #2f9fc9 0%, #1f7594 100%);
    color: #fff;
}
.kasse-tische-btn.tisch-wartet {
    border-color: #f5c65c;
    background: linear-gradient(150deg, #e0a52e 0%, #b8821c 100%);
    color: #1f2328;
}
/*
 * FAERBT SICH DER KNOPF, WIRD AUCH SEIN ZEICHEN WEISS (06.09.2026, Ansage des Wirts).
 *
 * Die Schrift wurde schon weiss (`color: #fff` oben) — das Zeichen blieb blau: es traegt
 * `ikon-blau` aus ICON_FARBE, und die Regel dort setzt `!important`, weil ein Sinnbild
 * sonst ueberall anders aussaehe. Auf dem gruenen Grund stand damit ein blaues Tischchen
 * neben weisser Schrift.
 *
 * Deshalb hier ein `!important` dagegen — und zwar NUR fuer die zwei gefaerbten Zustaende
 * dieses einen Knopfes. Ueberall sonst behaelt das Zeichen die Farbe des Hauses.
 */
.kasse-tische-btn.tisch-bereit .icon,
.kasse-tische-btn.tisch-wartet .icon,
.kasse-tische-btn.tisch-bereit svg,
.kasse-tische-btn.tisch-wartet svg { color: #fff !important; }
/* Das ZEICHEN bleibt in der Farbe des Hauses (`ikon-blau` u. Ae. setzen `!important`) — eine
   Regel dagegen waere hier gestanden, ohne etwas zu tun. Gemessen, nicht vermutet. */

.kasse-kueche-btn {
    position: relative;
    width: 44px;
    height: 44px;
    padding: 0;
    justify-content: center;
}

/* Auf schmalen Bildschirmen sollen die Icon-Buttons (Kassenbericht/Küche/Bar/Reservierungen/QR)
   nie einzeln auf eine eigene Zeile umbrechen — lieber gemeinsam etwas schmaler werden. Muss
   NACH der festen 44px-Regel oben stehen, sonst gewinnt bei gleicher Spezifität die spätere
   Regel im Stylesheet unabhängig von der Media Query. Nur der Tisch-Button bleibt fest (siehe
   .kasse-tische-btn#tischeBtn weiter oben — Name/Nummer braucht seine feste Breite). */
@media (max-width: 1199px) {
    .kasse-kueche-btn {
        /* Mitwachsen, aber QUADRATISCH bleiben.
           Vorher stand hier nur eine elastische Breite gegen eine feste Höhe von 44px — auf
           einem breiten Telefon wurden daraus 78x44, also liegende Rechtecke. `aspect-ratio`
           bindet die Höhe an die Breite, damit stimmt das Verhältnis auf jedem Bildschirm.
           Die Grenzen halten sie im brauchbaren Bereich: unter 40px trifft der Finger nicht
           mehr sicher, über 56px wirken vier Symbole wie Kacheln. */
        flex: 1 1 44px;
        width: auto;
        min-width: 40px;
        max-width: 56px;
        height: auto;
        aspect-ratio: 1;
        padding: 0;
    }
    /* Das Symbol wächst mit, sonst sitzt ein 20px-Zeichen verloren in einem 56px-Knopf. */
    .kasse-kueche-btn .icon { width: 46%; height: 46%; }
    /* Der Tisch-Knopf daneben zieht mit: eine Reihe aus Knöpfen in zwei verschiedenen Höhen
       (44 gegen 56) liest sich wie ein Versehen. Er behält seine Breite, nur die Höhe kommt
       jetzt aus der Reihe statt aus einer festen Zahl. */
    .kasse-search-bar #tischeBtn { height: auto; align-self: stretch; }
}

/* Verschiedene Akzentfarben je Icon-Button in der Kasse-Topbar — rein optisch, damit
   die fünf/sechs nebeneinanderliegenden Icons sich auf einen Blick unterscheiden lassen. */
#kassenberichtLink { border-color: #7c3aed99; color: #7c3aed; }
#kassenberichtLink:hover { border-color: #7c3aed; color: #6d28d9; }
#kuecheBellBtn { border-color: #ea580c99; color: #ea580c; }
#kuecheBellBtn:hover { border-color: #ea580c; color: #c2410c; }
#barBellBtn { border-color: #0d948899; color: #0d9488; }
#barBellBtn:hover { border-color: #0d9488; color: #0f766e; }
#reservierungenBtn { border-color: #16a34a99; color: #16a34a; }
#reservierungenBtn:hover { border-color: #16a34a; color: #15803d; }
.kueche-bell-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--djk-danger);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 800;
    align-items: center;
    justify-content: center;
}
/* Reservierungen-Glocke: unbestätigte Online-Anfragen warten auf eine Aktion (anders als die
   reine Kopfzahl-Info sonst) — leichtes Pulsieren macht das zusätzlich sichtbar. */
.kueche-bell-badge-urgent { animation: ruf-pulse 1.4s ease-in-out infinite; }

/* Küche/Bar: Live-Bestellticket-Liste */
.kueche-ticket {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-left: var(--brett-g-kante, 4px) solid var(--djk-yellow);
    border-radius: var(--brett-g-rundung, 5px);
    padding: 12px 14px;
    margin-bottom: 10px;
    font-family: var(--brett-schrift, inherit);
    letter-spacing: var(--brett-zeichen-abstand, normal);
    /* 0 heisst „so breit wie die Spalte" — der Trenner in der Mitte bleibt verschiebbar. */
    max-width: var(--brett-g-breite-max, none);
}
/* Offenes Detail-Panel bekommt schon einen Farbakzent, sobald eine echte Aktion darauf
   ausgelöst wurde — dieselbe Farbe, in der die Mini-Karte nach dem Schließen blinkt. */
.kueche-ticket-detail-bearbeitet {
    border-left-color: var(--kueche-flash-color, var(--djk-blue));
    background: var(--kueche-accent-bg, rgba(139, 92, 246, 0.08));
}
/* Kopfzeile: links der Tisch, rechts Uhr und Schließen.
   `min-width: 0` auf dem linken Teil ist hier das Entscheidende: ohne das schrumpft ein
   Flex-Kind nie unter seinen Inhalt, und ein langer Tischname ("Tisch #101 – Stammtisch")
   schob auf dem Telefon die ganze Zeile aus dem Fenster — die Uhr und das × standen neben
   dem Kasten auf schwarzem Grund, und links fehlte der Anfang. Jetzt bricht der Name um und
   das Ende der Zeile bleibt, wo es hingehört. */
.kueche-ticket-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin-bottom: 4px;
}
.kueche-ticket-head > :first-child { min-width: 0; }
/* Uhr und × rücken nie zusammen und wandern nie unter den Text: sie sind der Ausgang. */
.kueche-ticket-head-rechts {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
}
.kueche-ticket-tisch { font-weight: 800; color: var(--djk-yellow); font-size: 0.85rem; }
/* Im geoeffneten Auftrag steht die Tischnummer wie auf dem Bon: gross und gesperrt gesetzt.
   Sie ist die erste Frage jedes Kochs ("fuer welchen Tisch?") und auf dem Papier deshalb
   dasselbe: T i s c h  1 0 5.

   Hier stand `white-space: nowrap`, damit "Tisch" und die Nummer nicht auf zwei Zeilen fallen.
   Das hat den Zusammenhalt gerettet und dafuer das Fenster gesprengt: seit ein Tisch auch eine
   Bezeichnung tragen kann ("Tisch #101 – Stammtisch"), war die GANZE Zeile unzerbrechlich und
   damit breiter als ein Telefon. Zusammengehalten wird jetzt nur noch, was zusammengehoert —
   ueber ein geschuetztes Leerzeichen in der Zeichenkette selbst (siehe kueche_queue.php).
   Der Name dahinter darf umbrechen und rutscht unter die Nummer. */
.kueche-ticket-detail .kueche-ticket-tisch {
    display: block;
    font-size: var(--brett-g-kopf-gross, 1.5rem);
    color: var(--brett-g-kopf-farbe, inherit);
    letter-spacing: .18em;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    line-height: 1.15;
    overflow-wrap: break-word;   /* ein einzelnes ueberlanges Wort bricht notfalls auch selbst */
}
.kueche-ticket-detail .kueche-ticket-ankunft { letter-spacing: 0; font-size: 0.9rem; }
/* Die Bezeichnung des Tisches steht klein unter der Nummer, mit der Uhrzeit daneben. Gross und
   gesperrt wie die Nummer wuerde ein Name wie "Sonnenschein-Wolkenberger" den Kopf allein vier
   Zeilen hoch machen — die Nummer ist die Frage des Kochs, der Name nur die Beigabe. */
.kueche-ticket-detail .kueche-ticket-tischname {
    /*
     * IN DIE ERSTE ZEILE (27.08.2026) — auf Ansage, mit Kringel um den Kopf des Auftrags.
     *
     * Hier stand `display: block`, also Nummer oben und Bezeichnung darunter. Auf dem breiten
     * Bildschirm war das eine halbe Zeile Luft fuer nichts.
     *
     * `inline` und NICHT `nowrap`: die Zeile darf weiterhin brechen. Genau daran ist die erste
     * Fassung gescheitert (siehe den Absatz ueber `.kueche-ticket-tisch`) — eine unzerbrechliche
     * Zeile mit einem Namen wie „Sonnenschein-Wolkenberger" war breiter als ein Telefon und schob
     * das halbe Fenster aus dem Bild. So bleibt es bei EINER Zeile, wo es passt, und bricht nur,
     * wo es muss.
     *
     * Gemessen: kurzer Name auf breitem Schirm 45px -> 28px (also von zwei Zeilen auf eine);
     * langer Name auf 340px bricht weiterhin, laeuft aber nirgends ueber den Rand.
     */
    display: inline;
    margin-left: .55em;
    font-family: 'Segoe UI', Roboto, -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 0.85rem;
    letter-spacing: .02em;
    font-weight: 600;
    color: var(--djk-gray);
    overflow-wrap: break-word;
}
.kueche-ticket-detail .kueche-ticket-tischname .kueche-ticket-ankunft { font-size: 0.85rem; }
/* Auf einem schmalen Geraet wird die Sperrung enger statt die Zeile zu brechen — lieber etwas
   gedraengter als in drei Teile zerlegt. */
@media (max-width: 560px) {
    .kueche-ticket-detail .kueche-ticket-tisch { font-size: 1.25rem; letter-spacing: .08em; }
    .kueche-ticket-detail .kueche-ticket-ankunft { font-size: 0.8rem; }
}

/* Stornieren steht oben links unter dem Kopf, klein und fuer sich: es wirft das ganze Ticket
   weg und hat unten neben "Fertig" nichts zu suchen — dort lag es in Reichweite des Fingers,
   der gerade den grossen gruenen Knopf getroffen hat. */
.kueche-ticket-storno-zeile {
    display: flex;
    justify-content: flex-start;
    margin: 2px 0 10px;
}
.kueche-ticket-storno {
    padding: 6px 15px;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    opacity: .8;   /* zurueckhaltend, aber noch gross genug, um ihn absichtlich zu treffen */
}
.kueche-ticket-storno:hover { opacity: 1; }
.kueche-ticket-ankunft { font-weight: 600; color: var(--djk-gray); font-size: 0.72rem; font-variant-numeric: tabular-nums; }
.kueche-ticket-head time { color: var(--djk-gray); font-size: 0.78rem; }
.kueche-ticket-body { display: flex; align-items: baseline; gap: 8px; }
/* source/style_css/170_members_as_tables.css - style.css part 22 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Mitglieder als Tisch-Kategorie -------------------------------------------------------
   Keine Kacheln, sondern Zeilen über die volle Breite: Code | Name | (Schuld) | Summe |
   Schließen. Eine Zeche ist eine Liste von Namen, kein Raumplan — Kacheln würden hier nur
   Platz kosten und das Suchen erschweren. */
/* Der Behälter #tischOverlayGrid ist sonst ein Kachel-Raster (grid, Spalten à 108 px). Ohne
   diese Umschaltung werden Suchfeld und Zeilen zu schmalen Säulen gequetscht — genau so sah es
   auf dem Handy aus. ID + Klasse, damit die Regel die Raster-Klasse sicher schlägt. */
/* Suchzeile und Liste liegen zusammen auf einer ruhigen Fläche — so ist der Mitglieder-Bereich
   als eigener Bereich zu erkennen, und die weissen Karten heben sich davon ab.
   SEITLICH kein Polster: die Karten laufen damit genauso breit wie die Tisch-Kacheln der
   anderen Kategorien. Ein zusätzlicher Innenabstand hätte an beiden Rändern Platz gekostet,
   ohne etwas zu erklären. Oben und unten bleibt Luft, damit der Bereich atmet. */
/*
 * DIE MITGLIEDERLISTE ROLLT (05.09.2026, Ansage des Wirts — und er hat es mehrfach gesagt).
 *
 * GEMESSEN im laufenden Fenster: die Liste beginnt 65 Punkte unter dem oberen Rand, die
 * Leiste mit „Gutscheine / Mitglieder" ist 69 hoch, das Fenster 915. Ihre eigene Hoehe kam
 * dagegen aus dem INHALT (drei Mitglieder = 397) — bei acht Mitgliedern wurde sie 900 und
 * mehr, und `.kategorie-overlay` schneidet mit `overflow: hidden` alles darunter ab. „Eis
 * Müller" und alles nach ihm war damit nicht erreichbar: keine Geste half, denn es gab
 * nirgends etwas zu rollen.
 *
 * Jetzt hat sie eine Grenze und ihr eigenes Rollen. Die zwei Zahlen sind gemessen und stehen
 * deshalb hier: 65 der Abstand nach oben, 69 die Leiste — dazu der Rand des Geraets
 * (`safe-area-inset-bottom`), den die Leiste auf einem Telefon mit Ausschnitt zusaetzlich
 * traegt.
 *
 * `100dvh` statt `100vh`: auf dem Telefon zaehlt `vh` die Adresszeile mit, die beim Rollen
 * verschwindet — die Liste waere dann genau um deren Hoehe zu lang.
 */
#tischOverlayGrid.mitglieder-modus {
    display: block;
    background: var(--djk-black-soft);
    border: 0;
    border-radius: 0;
    padding: 12px 0;
    max-height: calc(100vh - 65px - 69px);
    max-height: calc(100dvh - 65px - 69px - env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
/* Suche 60 %, "+ Mitglied" der Rest. */
.mitglied-suche-zeile { display: flex; gap: 8px; padding: 0 0 10px; }
.mitglied-suche-feld { position: relative; flex: 0 0 60%; min-width: 0; }
.mitglieder-modus .mitglied-suche-feld input { padding-right: 40px; }
/* Das X sitzt IM Feld rechts, nicht daneben — daneben würde es dem Knopf "+ Mitglied" Platz
   wegnehmen. Es erscheint nur, wenn etwas drinsteht. */
.mitglied-suche-loeschen {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--djk-gray);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
}
.mitglied-suche-loeschen:hover { color: var(--djk-white); }
.mitglied-neu-btn {
    flex: 1;
    min-width: 0;
    padding: 12px 8px;
    border: 1px solid var(--djk-yellow);
    border-radius: 0;
    background: var(--djk-yellow);
    color: #fff;
    font-size: 0.9rem;
    font-weight: 800;
    white-space: nowrap;
    cursor: pointer;
}

/* Kurzformular: Foto zuerst, dann die drei Felder — in der Reihenfolge, in der der Service
   fragt. */
.mitglied-form { display: flex; flex-direction: column; gap: 10px; }
.mitglied-form input[type="text"],
.mitglied-form input[type="tel"] {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--djk-border);
    border-radius: 0;
    background: var(--djk-black-card);
    color: var(--djk-white);
    font-size: 1rem;
}
.mitglied-form-foto {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 140px;
    height: 140px;
    margin: 0 auto 4px;
    border: 2px dashed var(--djk-border);
    border-radius: 0;
    background: var(--djk-black-soft);
    overflow: hidden;
    cursor: pointer;
}
.mitglied-form-foto img { width: 100%; height: 100%; object-fit: cover; }
/* Solange kein Bild da ist, darf der leere Platzhalter KEINEN Platz beanspruchen — sonst
   steht die Vorschau als leerer Block neben dem Kamerasymbol und der Kasten wirkt zerteilt.
   Eigene Regel nötig, weil `display` einer Autorenregel das [hidden] des Browsers schlägt
   (siehe Falle 2 im Projekthandbuch). */
.mitglied-form-foto img[hidden],
.mitglied-form-foto .mitglied-form-foto-platzhalter[hidden] { display: none; }
.mitglied-form-foto-platzhalter {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    color: var(--djk-gray);
    font-size: 0.8rem;
    font-weight: 600;
}
.mitglied-form-foto-platzhalter .icon { width: 30px; height: 30px; }
/* Einwilligung: klein, aber antippbar — die ganze Zeile ist das Label, nicht nur das Kästchen.
   Der Haken sitzt oben, damit er bei zweizeiligem Text nicht mittig wegrutscht. */
.mitglied-form-einwilligung {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin-top: 12px;
    color: var(--djk-gray);
    font-size: 0.82rem;
    line-height: 1.4;
    cursor: pointer;
}
.mitglied-form-einwilligung input[type="checkbox"] {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    margin: 1px 0 0;
    accent-color: var(--djk-yellow);
}
.mitglied-form-fehler {
    padding: 10px 12px;
    border-radius: 0;
    background: #fee2e2;
    color: #991b1b;
    font-size: 0.88rem;
}

/* Element + zwei Klassen: die allgemeinen Formularregeln weiter oben in dieser Datei wiegen
   (0,1,1) und würden eine einfache Klasse schlagen (siehe CSS-Falle im Projekthandbuch). */
.mitglieder-modus .mitglied-suche-zeile input {
    display: block;
    width: 100%;
    max-width: none;
    padding: 12px 14px;
    border: 1px solid var(--djk-border);
    border-radius: 0;
    background: var(--djk-black-card);
    color: var(--djk-white);
    font-size: 1rem;
}
.mitglied-liste { display: flex; flex-direction: column; gap: 8px; padding: 0; }

/* Aufbau der Karte: Foto links über die VOLLE Hoehe, rechts drei Zeilen — Name, Knoepfe,
   Zahlen. Die Karte hat selbst kein Polster; das Foto sitzt buendig an der Kante, den Abstand
   traegt der Inhalt rechts davon. */
.mitglied-zeile {
    display: flex;
    align-items: stretch;
    gap: 0;
    width: 100%;
    padding: 0;
    border: 1px solid var(--djk-border);
    border-radius: 0;
    /* Farben aus der bestehenden Palette, keine erfundenen Variablen: --djk-black-card ist die
       Kartenflaeche, --djk-white die Textfarbe darauf (im hellen Design ein dunkles Blau). */
    background: var(--djk-black-card);
    overflow: hidden;
    cursor: pointer;
}
.mitglied-zeile:hover { border-color: var(--djk-yellow); }
/* Wer etwas offen hat, ist farbig abgesetzt — dieselbe Sprache wie ein besetzter Tisch. */
.mitglied-zeile-offen { border-left: 4px solid var(--djk-yellow); }

/* Gesicht des Gastes, formatfuellend ueber die Kartenhoehe. Ohne Foto die Initialen — ein
   leeres Feld hilft niemandem. */
.mitglied-avatar {
    flex-shrink: 0;
    width: 74px;
    align-self: stretch;
    object-fit: cover;
    background: var(--djk-black-soft);
    border: 0;
    border-radius: 0;
}
.mitglied-avatar-leer {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 74px;
    font-weight: 800;
    font-size: 1.35rem;
    color: var(--djk-yellow);
}

.mitglied-zeile-inhalt {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    /* Enger als vorher (5): mit der Sparte steht jetzt eine Zeile mehr in derselben Karte. */
    gap: 3px;
    padding: 6px 10px 6px 12px;
}
/* Die Sparte steht UEBER dem Namen: klein, ruhig, in der Hausfarbe — sie ordnet ein, sie
   ruft nicht. Kein Umbruch; wer in drei Sparten ist, sieht sie spaeter durch Komma getrennt. */
.mitglied-zeile-sparte {
    min-width: 0;
    color: var(--djk-yellow);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mitglied-zeile-name {
    min-width: 0;
    color: var(--djk-white);
    /* Kleiner als vorher (1.02): der Name ist nicht mehr das Einzige in dieser Spalte. */
    font-size: 0.94rem;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Knoepfe: gleich breit und gleich hoch, egal wie viele es sind (09.09.2026, Ansage des
   Wirts: *„остальные кнопки сделай ровно и одинаково"*). Vorher war „Berichtigen"
   44 breit und „Details" so breit wie sein Wort — die Reihe sprang von Zeile zu Zeile, je
   nachdem, wen das Haus bearbeiten darf. */
.mitglied-zeile-tasten { display: flex; align-items: center; gap: 6px; }
.mitglied-zeile-bearbeiten,
.mitglied-zeile-details {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 92px;
    height: 30px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 0;
    cursor: pointer;
}
.mitglied-zeile-bearbeiten .icon { width: 18px; height: 18px; }
.mitglied-zeile-bearbeiten { background: var(--djk-yellow); color: #fff; }

/* --- Fenster "Rechnung begleichen" an der Theke -------------------------------------------
   Bewusst schmal und ohne Aufteilen-Logik: hier wird eine Schuld bezahlt, nicht ein Tisch
   abgerechnet. Die Liste sagt, WOFUER — sonst zahlt jemand eine Zahl, die er nicht einordnen
   kann. */
.mg-rechnung-liste {
    max-height: 180px;
    overflow-y: auto;
    border: 1px solid var(--djk-border);
    border-radius: 6px;
    padding: 6px 10px;
}
.mg-rechnung-zeile {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 4px 0;
    font-size: 0.9rem;
    border-bottom: 1px dashed var(--djk-border);
}
.mg-rechnung-zeile:last-child { border-bottom: none; }
.mg-rechnung-summe {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    margin-top: 10px;
    font-weight: 800;
    font-size: 1.05rem;
}
.mg-zahlarten { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.mg-zahlarten .btn { width: 100%; }
.mitglied-zeile-bearbeiten:hover { filter: brightness(1.08); }
/* Breite und Hoehe stehen oben bei den gleichen Knoepfen — hier nur, was DIESEN unterscheidet. */
.mitglied-zeile-details {
    border: 1px solid var(--djk-border);
    background: transparent;
    color: var(--djk-yellow);
    font-size: 0.85rem;
    font-weight: 700;
    white-space: nowrap;
}
.mitglied-zeile-details:hover { border-color: var(--djk-yellow); }

/* Zahlen: Mitgliedsnummer, offene Rechnungen, und ganz rechts die laufende Zeche. */
.mitglied-zeile-zahlen { display: flex; align-items: center; gap: 10px; }
.mitglied-zeile-code {
    font-weight: 800;
    color: var(--djk-yellow);
    font-variant-numeric: tabular-nums;
}
/* Alte, schon gestellte Rechnungen — bewusst anders als die laufende Zeche: das eine kann der
   Kellner noch kassieren, das andere ist bereits Schuld. */
.mitglied-zeile-schuld { color: var(--djk-danger); font-weight: 700; }
.mitglied-zeile-summe {
    color: var(--djk-white);
    font-weight: 800;
    margin-left: auto;
    text-align: right;
}
/* Symbole statt der Woerter "RECHNUNG"/"OFFEN": als Text brauchten sie so viel Platz, dass die
   Zeile umbrach und die Betraege uebereinander rutschten. Blatt = gestellte Rechnung,
   Sanduhr = laufende Zeche. */
.mitglied-zeile-schuld,
.mitglied-zeile-summe {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.mitglied-zeile-schuld .icon,
.mitglied-zeile-summe .icon { width: 15px; height: 15px; flex-shrink: 0; opacity: .8; }

/* ---------- Vollbild-Karte eines Mitglieds ----------
   Grosses Gesicht und Name: der Service soll den Gast wiedererkennen, bevor etwas auf ihn
   gebucht wird. Liegt über allem, auch über der Tischauswahl. */
.mitglied-detail-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1200;
    background: rgba(15, 23, 42, .55);
    padding: 20px;
    overflow-y: auto;
}
.mitglied-detail-overlay.active { display: flex; align-items: center; justify-content: center; }
.mitglied-detail-karte {
    position: relative;
    width: 100%;
    max-width: 420px;
    padding: 28px 24px 22px;
    border: 1px solid var(--djk-border);
    border-radius: 0;
    background: var(--djk-black-card);
    text-align: center;
}
.mitglied-detail-karte .modal-close { top: 10px; right: 10px; }
.mitglied-detail-foto {
    display: block;
    width: 160px;
    height: 160px;
    margin: 0 auto 16px;
    border-radius: 0;
    object-fit: cover;
    background: var(--djk-black-soft);
    border: 2px solid var(--djk-yellow);
}
.mitglied-detail-foto-leer {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    font-weight: 800;
    color: var(--djk-yellow);
}
/* Antippbar: das Foto geht formatfüllend auf. Der Zeiger sagt es am Rechner, die kleine Lupe
   auf dem Handy. */
.mitglied-detail-foto-zoombar { cursor: zoom-in; }

/* source/style_css/180_photo_zoom_ticket.css - style.css part 23 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Foto formatfüllend, mit zwei Fingern zoombar ----------
   touch-action: none ist Pflicht: sonst fängt der Browser Kneifen und Wischen selbst ab und
   die eigene Zoom-Logik bekommt die Bewegung nie zu sehen. */
.foto-zoom-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1300;
    background: #000;
}
.foto-zoom-overlay.active { display: block; }
.foto-zoom-buehne {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    touch-action: none;
}
.foto-zoom-buehne img {
    max-width: 100%;
    max-height: 100%;
    transform-origin: center center;
    will-change: transform;
    user-select: none;
    -webkit-user-drag: none;
}
.foto-zoom-close {
    position: absolute;
    /* Dieselbe Verwechslung wie in der Kopfleiste der Kasse: oben ist die sichere Zone nie
       0, und `max` frisst deshalb den Abstand ganz auf — der Knopf sass an der Uhr. */
    top: calc(10px + env(safe-area-inset-top, 0px));
    right: 12px;
    z-index: 2;
    color: #fff;
    font-size: 2rem;
    line-height: 1;
    padding: 10px;
}
.foto-zoom-hinweis {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    text-align: center;
    color: #ffffffb3;
    font-size: 0.8rem;
    pointer-events: none;
}

.mitglied-detail-name { font-size: 1.4rem; font-weight: 800; color: var(--djk-white); }
.mitglied-detail-code { color: var(--djk-gray); font-size: 0.9rem; margin-top: 2px; }
/* Die Sparte auch hier in der Hausfarbe und gesperrt — dieselbe Handschrift wie in der Zeile
   der Liste, damit man sie als DASSELBE liest und nicht als zwei Angaben. */
.mitglied-detail-sparte {
    color: var(--djk-yellow);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    margin-top: 8px;
}
.mitglied-detail-seit { color: var(--djk-gray); font-size: 0.82rem; margin-top: 2px; }
.mitglied-detail-summen { margin: 18px 0; text-align: left; }
.mitglied-detail-summen .md-zeile {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--djk-border);
    color: var(--djk-white);
}
.mitglied-detail-summen .md-zeile:last-child { border-bottom: 0; }
.mitglied-detail-summen .md-schuld { color: var(--djk-danger); }
/* Nachweis der Einwilligung — klein und ruhig, aber vorhanden. Fehlt er, wird das benannt. */
.mitglied-detail-einwilligung {
    margin: 0 0 14px;
    text-align: left;
    color: var(--djk-gray);
    font-size: 0.78rem;
    line-height: 1.45;
}
.mitglied-detail-einwilligung-fehlt { color: var(--djk-danger); }

/* Erst wenn es wirklich eng wird, schrumpfen Foto und Knöpfe. */
@media (max-width: 430px) {
    /* Auf schmalen Geräten schrumpft das Foto, damit rechts genug für Name und Zahlen bleibt —
       der Aufbau selbst bleibt gleich. */
    .mitglied-avatar { width: 62px; }
    .mitglied-avatar-leer { min-height: 62px; font-size: 1.15rem; }
    .mitglied-zeile-inhalt { padding: 7px 8px 7px 10px; }
    /* Auch auf dem schmalen Bildschirm gleich breit — sonst springt die Reihe wieder. */
    .mitglied-zeile-bearbeiten,
    .mitglied-zeile-details { width: 78px; height: 28px; padding: 0; }
    .mitglied-zeile-zahlen { gap: 8px; font-size: 0.92rem; }
    .mitglied-detail-foto { width: 130px; height: 130px; }
}

.kueche-ticket-menge { font-weight: 800; color: var(--djk-white); font-size: 1.05rem; }
/* Speisenummer aus der Karte: gedämpft und schmal gesetzt, damit sie die Zeile ordnet, ohne
   dem Gerichtnamen die Aufmerksamkeit zu nehmen. Der Abstand zum Namen ist kleiner als der
   Spalten-gap, damit Nummer und Name als ein Block gelesen werden. */
.kueche-ticket-nummer {
    font-weight: 700;
    color: var(--djk-gray);
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
    margin-right: -3px;
}
.kueche-ticket-name { color: var(--djk-white); font-size: 1rem; }
/* Extras kleben direkt unter ihrem Gericht; der Abstand entsteht stattdessen ZWISCHEN den
   Gerichten — so ist auf einen Blick klar, welche Extras zu welchem Gericht gehören. */
.kueche-ticket-meta { color: var(--djk-gray); font-size: 0.78rem; margin-top: 1px; }
.kueche-item + .kueche-item { margin-top: 10px; }

/* --- Der Zettel: eine Position, aus drei Metern lesbar ------------------------------------
   Die Kuechentafel haengt nicht auf dem Schreibtisch. Wer daran arbeitet, hat die Haende voll,
   steht zwei bis drei Meter weg und schaut im Vorbeigehen hin — 1 rem heller Text auf dunklem
   Grund reicht dafuer nicht. Deshalb liegt jede Position auf einer WEISSEN Flaeche mit
   schwarzer, fetter Schrift: der groesstmoegliche Kontrast, den ein Bildschirm hergibt, und
   derselbe, den ein Bon auf Papier haette.

   Die Farben stehen hier ausgeschrieben und NICHT als Variable. Sonst kippt der Zettel im
   dunklen Erscheinungsbild mit (`--djk-white` ist dort hell) — und genau das soll er nicht:
   der Zettel ist in beiden Erscheinungsbildern weiss, weil die Lesbarkeit aus der Entfernung
   nicht Geschmackssache ist. */
/* Der Bon auf Papier ist die Vorlage — der Wirt hat ihn danebengelegt: eine schmale weisse
   Bahn, Schreibmaschinenschrift, gestrichelte Linien zwischen den Positionen, alles gleich
   gross. Das hat einen Grund, der aelter ist als jeder Bildschirm: in einer Schreibmaschinen-
   schrift steht jedes Zeichen an derselben Stelle, Mengen und Nummern liegen also
   untereinander, und das Auge findet die Zeile ohne zu suchen. Genau das bildet der
   Bildschirm jetzt nach.

   Deshalb steht hier eine Schriftfamilie fest und nicht die des Projekts: das ist keine
   Gestaltung, das ist die Funktion. */
.kueche-ticket-detail .kueche-item {
    background: #ffffff;
    padding: var(--brett-g-polster-y, 10px) var(--brett-g-polster-x, 12px);
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    /* Gestrichelte Trennlinien wie die Perforationen auf dem Bon — die Position ist ein
       abgetrennter Streifen, keine schwebende Karte. */
    border-top: 2px dashed #9ca3af;
}
/*
 * ACHTUNG, GEMESSEN AM 05.09.2026: der geoeffnete Auftrag erzeugt diese Klassen NICHT.
 *
 * `buildItemsHtml()` in station_board.js, das `.kueche-item` und `.kueche-ticket-menge`
 * schreibt, wird nur aus `buildMiniHtml()` und `miniZettelHtml()` gerufen — also fuer die
 * kleine Karte. Der offene Auftrag besteht aus `buildBlattHtml()`, und das ist ein PAPIER.
 *
 * Die Regeln hier unten treffen also derzeit nichts. Sie bleiben stehen, weil sie den
 * Rueckfallweg beschreiben (`miniZettelHtml` ohne Blaetter) und weil ein grosser, sorgfaeltig
 * begruendeter Block nicht auf Verdacht geloescht wird. Wer eine EINSTELLUNG fuer den grossen
 * Auftrag sucht: sie gehoert an `.druck-zeile.ist-position` / `.ist-zusatz` weiter unten —
 * genau dort haben die drei Regler seit dem 05.09. ihre Wirkung.
 */
.kueche-ticket-detail .kueche-item:last-child { border-bottom: 2px dashed #9ca3af; }
.kueche-ticket-detail .kueche-item + .kueche-item { margin-top: var(--brett-g-pos-abstand, 0px); }
.kueche-ticket-detail .kueche-ticket-body {
    align-items: baseline;
    gap: var(--brett-g-zeilen-abstand, 8px);
    flex-wrap: wrap;
}
/* Auf dem Bon steht "1x 61 Griechischer Bauernsalat" in EINER Groesse. Die Menge dort gross
   und den Namen klein zu setzen, hiesse die Zeile auseinanderzureissen — sie wird als ein
   Stueck gelesen. */
.kueche-ticket-detail .kueche-ticket-menge {
    color: #000000;
    font-size: var(--brett-g-menge-gross, 1.35rem);
    font-weight: 700;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
}
.kueche-ticket-detail .kueche-ticket-name {
    color: #000000;
    font-size: var(--brett-g-name-gross, 1.35rem);
    font-weight: 700;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
}
/* Auf dem Bon steht die Speisenummer in derselben Groesse wie der Name — sie gehoert zur
   Zeile. Nur die Farbe ist gedaempft, damit der Name die Zeile trotzdem anfuehrt. */
.kueche-ticket-detail .kueche-ticket-nummer {
    color: #4b5563;
    font-size: var(--brett-g-name-gross, 1.35rem);
    font-weight: 700;
}
/* Beilagen, Extras, Kommentar: eine Stufe kleiner, aber ausdruecklich NICHT blass. "Ohne
   Zwiebel" falsch zu lesen kostet einen Teller. Eingerueckt wie die Folgezeilen auf dem Bon,
   damit sie sichtbar zu ihrem Gericht gehoeren. */
.kueche-ticket-detail .kueche-ticket-meta {
    color: #1f2937;
    font-size: var(--brett-g-meta-gross, 1.05rem);
    font-weight: 400;
    line-height: 1.35;
    margin-top: 3px;
    padding-left: 2.2em;
}
/* Platz und Gast sagen, WOHIN der Teller geht — auf Weiss ein kraeftiges Braun statt des
   Themenblaus, das im dunklen Bild zu hell fuer weissen Grund waere. */
.kueche-ticket-detail .kueche-ticket-meta .kueche-ticket-platz { color: #b45309; }

/* Die Uebersichtskarte rechts bleibt bewusst flach: waere dort auch ein Zettel, waere die
   ganze Spalte eine Wand aus Weiss und der geoeffnete Auftrag ginge darin unter. Deshalb sind
   die Regeln oben auf `.kueche-ticket-detail` eingeschraenkt — die Uebersicht braucht gar
   keine Gegenregel. */
.kueche-ticket-staff { color: var(--djk-gray); font-size: 0.72rem; margin-top: 6px; opacity: 0.75; }

/* Vorspeise-Block, Kategorie-Gruppen und Salat-Sammelgruppe innerhalb der Detailkarte */
.kueche-vorspeise-block {
    background: rgba(59, 130, 246, 0.1);
    border: 1px solid rgba(59, 130, 246, 0.35);
    border-radius: 5px;
    padding: 10px 12px;
    margin-bottom: 10px;
}
.kueche-block-label {
    font-weight: 800;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--djk-yellow);
    margin-bottom: 6px;
}
.kueche-divider { height: 1px; background: var(--djk-border); margin: 10px 0; }
.kueche-section-divider { display: flex; align-items: center; gap: 10px; margin: 16px 0 10px; }
.kueche-section-divider::before, .kueche-section-divider::after { content: ''; flex: 1; height: 1px; background: var(--djk-border); }
.kueche-section-divider span { flex: 0 0 auto; font-weight: 800; font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--djk-yellow); }
.kueche-gruppe {
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 10px 12px;
    margin-bottom: 8px;
}
.kueche-gruppe:last-child { margin-bottom: 0; }
.kueche-gruppe-erledigt { background: rgba(76, 175, 80, 0.12); border-color: var(--djk-success); }
.kueche-gruppe-unterwegs { background: rgba(224, 90, 90, 0.12); border-color: var(--djk-danger); }
.kueche-gruppe-plain-wrap { display: flex; flex-direction: column; gap: 10px; }
.kueche-gruppe-plain { padding: 2px 0; }
.kueche-gruppe-name-plain { font-weight: 700; font-size: 0.8rem; color: var(--djk-white); margin-bottom: 4px; }
.kueche-gruppe-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.kueche-gruppe-name { font-weight: 700; font-size: 0.8rem; color: var(--djk-white); }
.kueche-gruppe-control { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.kueche-senden-btn, .kueche-zuteil-btn, .kueche-erledigt-btn {
    padding: 6px 10px;
    border-radius: 5px;
    border: 1.5px solid var(--djk-yellow);
    background: rgba(59, 130, 246, 0.12);
    color: var(--djk-yellow);
    font-size: 0.75rem;
    font-weight: 700;
    cursor: pointer;
}
.kueche-senden-btn:hover, .kueche-zuteil-btn:hover, .kueche-erledigt-btn:hover { background: rgba(59, 130, 246, 0.22); }
.kueche-senden-btn:disabled, .kueche-zuteil-btn:disabled, .kueche-erledigt-btn:disabled { opacity: 0.5; cursor: default; }
.kueche-erledigt-btn { border-color: var(--djk-success); background: rgba(76, 175, 80, 0.16); color: #15803d; }
.kueche-sendung-badge { font-size: 0.72rem; font-weight: 700; }
.kueche-sendung-unterwegs { color: var(--djk-yellow); }
.kueche-sendung-erledigt { color: #15803d; }
.kueche-abbrechen-btn {
    padding: 5px 9px;
    border-radius: 5px;
    border: 1.5px solid var(--djk-danger, #e05a5a);
    background: rgba(224, 90, 90, 0.12);
    color: var(--djk-danger, #e05a5a);
    font-size: 0.68rem;
    font-weight: 700;
    cursor: pointer;
    margin-left: 8px;
}
.kueche-abbrechen-btn:hover { background: rgba(224, 90, 90, 0.22); }
.kueche-abbrechen-btn:disabled { opacity: 0.5; cursor: default; }
/* Die Handgriffe unter dem Auftrag. Sie werden mit fettigen Fingern und im Vorbeigehen
   getroffen — deshalb gross und mit klarem Unterschied zwischen "ich rufe jemanden" (die
   beiden runden Knoepfe nebeneinander) und "ich bin fertig" (der grosse gruene darunter).

   DIESELBE Reihe steht auch unter einer einzelnen Gruppe (.kueche-gruppe-actions). Sie war
   frueher klein — mit der Begruendung, sie wiederhole sich je Gruppe und mache das Ticket
   endlos lang. Das stimmt nicht: sie wird NUR in der eingeschraenkten Ansicht gezeichnet
   (siehe buildGruppeHtml in station_board.js), also bei einer Abteilung, die genau ihre eigene
   Gruppe sieht. Fuer Viktoria war das die einzige Knopfreihe ueberhaupt — und sie war die
   kleinste im Haus. Jetzt haben alle dieselben Knoepfe (11.08.2026). */
.kueche-ticket-actions,
.kueche-gruppe-actions { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.kueche-ticket-btn {
    flex: 1;
    min-width: 90px;
    padding: 9px 10px;
    border-radius: 5px;
    border: 1.5px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
}
/* Die beiden Ruf-Knoepfe: rund und breit genug für einen Daumen. */
.kueche-ticket-actions .kueche-ticket-btn,
.kueche-gruppe-actions .kueche-ticket-btn {
    min-width: 120px;
    padding: var(--brett-g-knopf-hoehe, 15px) 18px;
    border-radius: 999px;
    font-size: var(--brett-g-knopf-gross, 0.95rem);
    font-weight: 700;
}
.kueche-ticket-btn:hover { border-color: var(--djk-yellow); }
.kueche-ticket-btn:disabled { opacity: 0.5; cursor: default; }
.kueche-ticket-btn-fertig {
    background: rgba(76, 175, 80, 0.16);
    border-color: var(--djk-success);
    color: #15803d;
}
/* "Fertig" steht für sich in voller Breite unter den Ruf-Knoepfen und ist wirklich grün, nicht
   nur grün umrandet: es ist der Handgriff, der am haeufigsten und am eiligsten kommt.
   `order` haelt ihn unten, auch wenn ein Ruf-Knopf ("✓ Anna unterwegs") auf volle Breite geht. */
.kueche-ticket-actions .kueche-ticket-btn-fertig,
.kueche-gruppe-actions .kueche-ticket-btn-fertig {
    order: 2;
    flex: 1 0 100%;
    padding: var(--brett-g-knopf-hoehe, 20px);
    border-radius: var(--brett-g-knopf-rundung, 18px);
    font-size: var(--brett-g-knopf-gross, inherit);
    /* DIE EINSTELLUNG WAR STUMM (05.09.2026).
       „Farbe: Fertig" (brett_g_fertig_farbe) steht seit dem 04.09. in der Maske und wurde als
       --brett-g-fertig-farbe auch ausgegeben — nur las sie hier niemand: die Farbe stand fest
       als #16a34a, ausgerechnet die Vorgabe der Einstellung. Beim KLEINEN Zettel war sie
       verdrahtet (--brett-k-fertig-farbe), beim grossen nicht. Wer sie umstellte, sah die
       kleine Karte wechseln und den grossen Zettel nicht — und suchte den Fehler bei sich.
       Kräftiges Grün bleibt die Vorgabe: auf einem hellen Ton waere weisse Schrift kaum zu
       lesen, und dieser Knopf muss aus zwei Metern eindeutig sein.
       Die flache Farbe steht VOR dem Verlauf: ein Browser ohne `color-mix` laesst die zweite
       Zeile fallen und behaelt trotzdem die eingestellte Farbe. */
    border-color: color-mix(in srgb, var(--brett-g-fertig-farbe, #16a34a) 85%, #000);
    background: var(--brett-g-fertig-farbe, #16a34a);
    background: linear-gradient(180deg,
        var(--brett-g-fertig-farbe, #16a34a),
        color-mix(in srgb, var(--brett-g-fertig-farbe, #16a34a) 85%, #000));
    color: #ffffff;
    font-size: 1.25rem;
    font-weight: 800;
    letter-spacing: .03em;
    box-shadow: 0 4px 14px rgba(16, 185, 129, .28);
}
.kueche-ticket-actions .kueche-ticket-btn-fertig:hover,
.kueche-gruppe-actions .kueche-ticket-btn-fertig:hover { border-color: #15803d; filter: brightness(1.08); }
.kueche-ticket-actions .kueche-ticket-btn-fertig:active,
.kueche-gruppe-actions .kueche-ticket-btn-fertig:active { transform: translateY(1px); }
/* Gesperrt (Online-Bestellung, deren Zeit noch nicht bestaetigt ist): grau statt grün, sonst
   greift die Küche danach, weil grün nun einmal "los" heisst. */
.kueche-ticket-actions .kueche-ticket-btn-fertig:disabled,
.kueche-gruppe-actions .kueche-ticket-btn-fertig:disabled {
    background: var(--djk-black-soft);
    border-color: var(--djk-border);
    color: var(--djk-gray);
    box-shadow: none;
}
.kueche-ticket-btn-blink {
    border-color: var(--djk-danger);
    color: #fff;
    animation: kueche-btn-blink 1s ease-in-out infinite;
}
@keyframes kueche-btn-blink {
    0%, 100% { background: rgba(181, 52, 44, 0.9); }
    50% { background: rgba(181, 52, 44, 0.55); }
}
.kueche-ticket-btn-acked {
    background: rgba(76, 175, 80, 0.22);
    border-color: var(--djk-success);
    color: #15803d;
    flex-basis: 100%;
}

.kueche-online-info {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px dashed var(--djk-border);
}
.kueche-online-typ { font-size: 0.8rem; font-weight: 700; color: var(--djk-yellow); margin-bottom: 8px; }
.kueche-online-bestaetigt { font-size: 0.82rem; font-weight: 700; color: #15803d; margin-top: 6px; }
.kueche-zeit-btn { flex: 0 0 auto; min-width: 70px; }

/* source/style_css/185_photo_zoom_ticket_continued.css - style.css: photo zoom ticket continued, part 24 of 78 (built by werkzeuge/parts_build.php) */
/* Vollbild-Alarm: Kellner wird von Küche/Bar gerufen */
.ruf-fullscreen-overlay {
    position: fixed;
    inset: 0;
    background: linear-gradient(160deg, #b5342c 0%, #7a1f1a 100%);
    color: #fff;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 24px;
    animation: ruf-pulse 1s ease-in-out infinite;
}
@keyframes ruf-pulse {
    0%, 100% { filter: brightness(1); }
    50% { filter: brightness(1.25); }
}
.ruf-fullscreen-title { font-size: 1.6rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 4px; }
.ruf-fullscreen-quelle { font-size: 0.95rem; opacity: 0.85; margin-bottom: 12px; }
.ruf-fullscreen-tisch { font-size: 2.6rem; font-weight: 800; margin-bottom: 28px; }
.ruf-fullscreen-btn {
    padding: 16px 32px;
    border-radius: 5px;
    border: none;
    background: #fff;
    color: #7a1f1a;
    font-size: 1.1rem;
    font-weight: 800;
    cursor: pointer;
}

/* Blink-Farbe der Mini-Karten je nach Bearbeitungsstand (siehe buildMiniHtml() in
   station_board.js): neu/gesehen/bearbeitet — admin-konfigurierbar unter Admin > Küche.
   Die tatsächliche Farbe kommt als Inline-Style (--kueche-flash-color/--kueche-flash-bg) pro
   Element, damit sie ohne Neuladen/CSS-Änderung aus den Einstellungen kommen kann. */
@keyframes kueche-ticket-flash-dynamic {
    0%, 40%, 80% { background: var(--kueche-flash-bg, rgba(255, 107, 107, 0.35)); }
    20%, 60%, 100% { background: var(--djk-black-card); }
}
.kueche-ticket-flash-dynamic {
    border-left-color: var(--kueche-flash-color, var(--djk-danger));
    animation: kueche-ticket-flash-dynamic 1s ease-in-out infinite;
}

/* source/style_css/190_kitchen_bar_split_view.css - style.css part 25 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* Küche/Bar: Split-Ansicht — links Detail (großes ausgewähltes Ticket, 35% Breite),
   rechts die Mini-Karten als dicht gepackte Masonry-Sektion (~3 Spalten, Karten
   unterschiedlich hoch, keine gleichmäßigen Zeilen — die nächste Karte einer Spalte
   beginnt direkt dort, wo die vorige endet). container-wide--board hebt dafür die
   1100px-Breitenbegrenzung auf, damit die Ansicht den ganzen Bildschirm nutzt. */
.container-wide.container-wide--board {
    max-width: 100%;
    padding: 0 14px;
}
.kueche-board {
    display: flex;
    gap: 16px;
    align-items: stretch;
    /*
     * Zwei Spalten, zwei Bildlaufleisten.
     *
     * Der Wirt: „когда скролим белый тикет — так как он может быть длинный — скроллиться должна
     * только она, а правый блок отдельно." Vorher rollte die ganze Seite: ein langer Zettel
     * schob die Übersicht mit nach oben aus dem Bild, und wer oben etwas suchte, musste erst
     * den Zettel zurückrollen.
     *
     * Deshalb bekommt das Brett die Höhe des Fensters (dvh, damit die Leiste auf dem Telefon
     * mitzählt), und jede Spalte rollt für sich.
     */
    height: calc(100dvh - 20px);
    min-height: 380px;
}
.kueche-board-detail {
    flex: 0 0 35%;
    min-width: 0;
    overflow-y: auto;
    /* Damit der letzte Knopf nicht am unteren Rand klebt. */
    padding-bottom: 12px;
}
.kueche-board-detail .empty-state {
    background: var(--djk-black-card);
    border: 1px dashed var(--djk-border);
    border-radius: 5px;
    padding: 40px 20px;
}
.kueche-board-list {
    flex: 1 1 65%;
    min-width: 0;
    overflow-y: auto;
    padding-bottom: 12px;
    /*
     * RASTER statt Spaltensatz (`columns`).
     *
     * Spaltensatz füllt eine Spalte bis zur Höhe des Kastens und fängt dann RECHTS die nächste
     * an. Solange die Seite als Ganzes rollte, war das egal — der Kasten wuchs einfach mit.
     * Seit jede Spalte ihre eigene Bildlaufleiste hat (feste Höhe), lief der Inhalt dagegen nach
     * rechts aus dem Bild: die Getränke-Karten standen außerhalb, und selbst der Satz „Aktuell
     * keine offenen Bestellungen" zerfiel in zwei Hälften nebeneinander. Genau das hat der Wirt
     * fotografiert.
     *
     * Ein Raster füllt von links nach rechts und dann nach UNTEN — also in die Richtung, in die
     * auch gerollt wird. Die Mindestbreite je Karte bleibt: lieber weniger Spalten als eine
     * unlesbar schmale Karte.
     */
    display: grid;
    /* Mindest- und Hoechstbreite kommen aus Verwaltung → Bildschirme (includes/brett_aussehen.php);
       ohne die Einstellung stehen hier die Werte, die vorher fest hier standen. */
    grid-template-columns: repeat(auto-fill, minmax(var(--brett-k-breite-min, 250px), var(--brett-k-spalte, 1fr)));
    gap: var(--brett-k-luecke, 8px);
    align-content: start;
    /* Jede Karte endet mit ihrem Inhalt - sonst dehnt das Raster sie auf die Zeilenhoehe. */
    align-items: start;
}

/*
 * Eine Karte fängt dort an, wo die vorige aufhört (23.08.2026).
 *
 * Das Raster stellt jede REIHE auf die Höhe ihrer größten Karte; bei sehr verschieden langen
 * Bestellungen bleiben darunter Löcher, und der Wirt hat sie rot eingekringelt. Die Karten
 * werden deshalb in `station_board.js` von Hand auf Spalten verteilt — jede in die, die
 * gerade am kürzesten ist. Diese Spalten sind die Rasterfelder.
 */
.kueche-board-spalte {
    display: flex;
    flex-direction: column;
    gap: var(--brett-k-luecke, 8px);
    min-width: 0;
}

/*
 * Die Zeile mit dem GERICHT ist die, die gelesen wird (23.08.2026).
 *
 * Der Wirt hat sie in den Entwicklerwerkzeugen auf 1.3em gestellt und den Zettel fotografiert:
 * Kopf, Uhrzeit und Trennlinien bleiben klein, das Gericht wird groß. Auf Papier ändert sich
 * nichts — dort entscheidet die Einstellung unter Verwaltung → Drucken.
 */
/*
 * ... und zwar STÄRKER als die Zeile selbst (23.08.2026, zweiter Anlauf).
 *
 * Die Größe steht als `style=""` an der Zeile: sie kommt aus der Druck-Einstellung (dort ist die
 * Position doppelt hoch, also `2em` mit einem `scale(0.5, 1)` als Ausgleich). Eine Regel im
 * Stilblatt kommt dagegen nicht an — deshalb hier ausnahmsweise `!important`, und der Ausgleich
 * muss mit weg, sonst stünde die Schrift schmalgedrückt da.
 *
 * Auf Papier ändert sich nichts: dort gilt weiter die Einstellung unter Verwaltung → Drucken.
 */
/* Das Gericht — und alles, was zu ihm gehoert: Kommentar, Extras, „Kueche Divers". Sie kamen
   aus derselben Druck-Einstellung mit 2em heraus; auf dem Brett stand der Zusatz damit so
   gross wie das Gericht selbst und sprengte die Zeile. (23.08.2026) */
/*
 * HIER WIRKEN DIE EINSTELLUNGEN JETZT WIRKLICH (05.09.2026).
 *
 * Vorher stand hier fest `1.3em`, und die Einstellungen „Schrift: Gericht" / „Schrift: Extras"
 * hingen an `.kueche-ticket-detail .kueche-ticket-menge` — Klassen, die der offene Auftrag gar
 * nicht erzeugt (er ist ein Papier, siehe buildBlattHtml in station_board.js). Man drehte am
 * Regler und nichts geschah.
 *
 * Der Faktor der Zettel-Skala bleibt dabei: sonst wuerde „alles groesser" die beiden Zeilen
 * ueberspringen. Deshalb `calc(... * var(--brett-g-zettel-faktor))` und nicht die blosse Zahl.
 */
.kueche-ticket-detail .druck-zeile.ist-position {
    font-size: calc(var(--brett-g-name-gross, 19px) * var(--brett-g-zettel-faktor, 1)) !important;
    transform: none !important;
    /* Luft vor jedem neuen Gericht — nicht vor dem ersten. */
    margin-top: var(--brett-g-pos-abstand, 0px);
}
.kueche-ticket-detail .druck-papier .druck-zeile.ist-position:first-child { margin-top: 0; }
.kueche-ticket-detail .druck-zeile.ist-zusatz {
    font-size: calc(var(--brett-g-meta-gross, 14px) * var(--brett-g-zettel-faktor, 1)) !important;
    transform: none !important;
}

/*
 * Eine Trennlinie bricht nicht um.
 *
 * Sie ist so breit wie die Papierrolle (42 Zeichen); auf einem Telefon passte sie nicht und
 * hinterliess ein einsames „---" in der nächsten Zeile — der Wirt hat es eingekringelt. Was
 * über den Rand ragt, wird abgeschnitten: eine Linie ist eine Linie, egal wie lang.
 */
/*
 * Die Trennlinie bricht nicht um — zweiter Anlauf (23.08.2026).
 *
 * Der erste stand VOR `.kueche-ticket-detail .druck-zeile { white-space: pre-wrap; padding-left:
 * 3ch; text-indent: -3ch; }`. Gleiche Stärke, spätere Regel gewinnt — auf dem Telefon brach die
 * Linie weiter um. Jetzt ist die Regel enger geschrieben (zwei Klassen plus Elternklasse) und
 * gilt für Brett wie Karte.
 */
.druck-zeile.ist-linie,
.kueche-ticket-detail .druck-zeile.ist-linie,
.kueche-mini-papier .druck-zeile.ist-linie {
    white-space: nowrap;
    overflow: hidden;
    padding-left: 0;
    text-indent: 0;
}

/*
 * Fertig = grün, das ganze Blatt.
 *
 * Nicht nur ein Häkchen am Rand: wer durch die Küche geht, soll auf einen Blick sehen, welcher
 * Zettel erledigt ist. Die Schrift bleibt schwarz — auf diesem Grün liest sie sich besser als
 * weiße, und der Zettel soll ein Zettel bleiben.
 */
.kueche-blatt-fertig .druck-papier {
    background: #4caf50;
    border-color: #2e7d32;
}
.kueche-blatt-fertig .kueche-gang { background: transparent; }

/*
 * Eine Zeile, die ihr Mensch abgehakt hat (23.08.2026).
 *
 * Der Wirt: „если работник пиццы нажмет, что он закончил, то у главного на маленьких тикетах
 * именно его продукты должны зеленого цвета стать." Also nicht der ganze Auftrag und nicht nur
 * ein Haken am Rand — die Zeilen selbst. Wer daruebersieht, erkennt am gruenen Block sofort,
 * was noch fehlt.
 */
.kueche-item-fertig {
    background: rgba(22, 163, 74, 0.18);
    border-left: 3px solid #16a34a;
    border-radius: 4px;
    padding-left: 6px;
}
.kueche-item-fertig .kueche-ticket-name,
.kueche-item-fertig .kueche-ticket-menge,
.kueche-item-fertig .kueche-ticket-nummer { color: #4ade80; }

/* Ist an einer Bestellung nichts mehr offen, ist die ganze Karte gruen. */
.kueche-ticket-mini-fertig {
    border-color: #16a34a;
    border-left-color: #16a34a;
    background: rgba(22, 163, 74, 0.16);
}

/* „alles an X" — ein Knopf zwischen Zettel und „Drucken", in voller Breite. */
.kueche-blatt-senden-alles { margin-top: 6px; }
.kueche-blatt-senden-alles .kueche-blatt-alles-btn {
    width: 100%;
    padding: 12px 16px;
    border-radius: 5px;
    font-size: 0.82rem;
}

/* Ziehbarer Griff zwischen Detail-Panel und Masonry-Liste — Breite per Maus/Touch
   verstellbar, siehe station_board.js. Die sichtbare Linie ist schmal, die klick-/
   greifbare Fläche (per Padding) deutlich breiter, damit sie auch auf Tablets gut
   trifft. Die gewählte Breite wird pro Station (Küche/Bar) in localStorage gemerkt. */
.kueche-board-resizer {
    flex: 0 0 17px;
    align-self: stretch;
    cursor: col-resize;
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: 0 7px;
    touch-action: none;
}
.kueche-board-resizer span {
    width: 3px;
    border-radius: 3px;
    background: var(--djk-border);
}
.kueche-board-resizer:hover span,
.kueche-board-resizer.is-dragging span {
    background: var(--djk-yellow);
}
.kueche-board-resizer.is-dragging { cursor: col-resize; }

.kueche-ticket-timer {
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--djk-white);
    font-size: var(--brett-g-timer-gross, 0.95rem);
}
.kueche-ticket-close {
    background: none;
    border: none;
    color: var(--djk-gray);
    cursor: pointer;
    font-size: 1.5rem;
    line-height: 1;
    padding: 2px 4px;
}
.kueche-ticket-close:hover { color: var(--djk-white); }

.kueche-ticket-mini {
    background: var(--brett-k-grund, var(--djk-black-card));
    border: var(--brett-k-rahmen, 1px) solid var(--brett-k-rahmen-farbe, var(--djk-border));
    border-left: var(--brett-k-kante, 4px) solid var(--djk-yellow);
    border-radius: var(--brett-k-rundung, 5px);
    padding: var(--brett-k-polster-y, 10px) var(--brett-k-polster-x, 12px);
    font-family: var(--brett-schrift, inherit);
    letter-spacing: var(--brett-zeichen-abstand, normal);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: border-color var(--transition), background var(--transition);
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
    margin-bottom: 8px;
}
.kueche-ticket-mini:hover { border-color: var(--djk-yellow); }
.kueche-ticket-mini.active { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.1); }
.kueche-ticket-mini-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.kueche-ticket-mini-tisch {
    font-weight: var(--brett-k-kopf-fett, 800);
    color: var(--brett-k-kopf-farbe, var(--djk-yellow));
    font-size: var(--brett-k-kopf-gross, 0.85rem);
}
.kueche-ticket-mini .kueche-ticket-ankunft { font-size: var(--brett-k-ankunft-gross, 0.72rem); }
.kueche-ticket-mini-timer {
    font-weight: 800;
    font-size: var(--brett-k-timer-gross, 0.9rem);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
    color: var(--brett-k-timer-farbe, var(--djk-white));
}
/* Die Uhr in einer eigenen Zeile oder unten — Verwaltung → Bildschirme, „Wo die Uhr steht". */
.kueche-ticket-mini .kueche-timer-zeile { display: flex; justify-content: flex-end; }
/* KEIN `gap` hier: der Abstand zwischen zwei Positionen steht als `margin-top` an der Huelle
   (siehe unten). Beides zusammen ergaebe zwei Abstaende uebereinander, und die eingestellte Zahl
   waere nicht mehr die, die man misst. */
.kueche-ticket-mini-items { display: flex; flex-direction: column; gap: 0; }
.kueche-ticket-mini-items .kueche-ticket-body { gap: var(--brett-k-zeilen-abstand, 6px); font-size: 0.82rem; }
.kueche-ticket-mini-items .kueche-ticket-menge {
    font-size: var(--brett-k-menge-gross, 0.82rem);
    color: var(--brett-k-menge-farbe, var(--djk-white));
    font-weight: var(--brett-k-menge-fett, 800);
}
.kueche-ticket-mini-items .kueche-ticket-nummer {
    font-size: var(--brett-k-menge-gross, 0.82rem);
    color: var(--brett-k-nummer-farbe, #9ca3af);
}
.kueche-ticket-mini-items .kueche-ticket-name {
    font-size: var(--brett-k-name-gross, 0.82rem);
    color: var(--brett-k-name-farbe, var(--djk-white));
}
.kueche-ticket-mini-items .kueche-ticket-meta {
    font-size: var(--brett-k-meta-gross, 0.7rem);
    color: var(--brett-k-meta-farbe, var(--djk-gray));
    margin-top: 0;
}
/* Seit die Positionen in einer Huelle stecken, greifen die alten `+`-Regeln zwischen den
   Geschwistern nicht mehr — der Abstand haengt jetzt an der Huelle. */
.kueche-ticket-mini-items .kueche-item + .kueche-item { margin-top: var(--brett-k-pos-abstand, 6px); }
.kueche-ticket-mini-ruf {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--djk-danger);
    flex-shrink: 0;
    animation: kueche-btn-blink-dot 1s ease-in-out infinite;
}
@keyframes kueche-btn-blink-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

@keyframes kueche-warn2-pulse { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.15); } }
.kueche-ticket-mini.kueche-pulse,
.kueche-ticket-detail.kueche-pulse {
    animation: kueche-warn2-pulse 1.4s ease-in-out infinite;
}

@media (max-width: 780px) {
    /* Auf schmalen Geräten steht alles untereinander — dort rollt wieder die Seite, sonst
       hätte man zwei kleine Fenster statt einer langen Bahn. */
    .kueche-board { flex-direction: column; height: auto; min-height: 0; }
    .kueche-board-detail, .kueche-board-list { overflow-y: visible; }
    .kueche-board-detail {
        display: none;
        position: static;
    }
    .kueche-board-detail.is-open {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 95;
        background: var(--djk-black);
        overflow-y: auto;
        padding: calc(16px + env(safe-area-inset-top, 0px)) 14px calc(16px + env(safe-area-inset-bottom, 0px));
    }
    .kueche-board-list { width: 100%; grid-template-columns: 1fr; }
    .kueche-board-resizer { display: none; }
    .container-wide.container-wide--board { padding: 0 8px; }
}

.container-wide {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 8px;
}

@media (max-width: 480px) {
    .container-wide { padding: 0 6px; }
}

.kasse-bottom-bar {
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 55;
    background: var(--djk-black-card);
    border-top: 2px solid var(--djk-yellow);
    /* Kantig: die Leiste sitzt am unteren Bildschirmrand auf und soll dort nicht "schweben". */
    border-radius: 0;
    box-shadow: var(--shadow);
    /*
     * UNTEN NUR DIE SICHERE ZONE — kein Platzhalter mehr fuer eine Leiste, die es hier nicht
     * gibt (31.08.2026).
     *
     * Hier standen `52px + env(safe-area-inset-bottom)`. Die 52 waren die Reserve fuer die
     * globale `.bottom-nav`; die Kasse hat keine, und genau deshalb steht ein paar hundert
     * Zeilen weiter oben schon `body.kasse-body { padding-bottom: 0 }` mit der Begruendung,
     * die Reserve wuerde „nur eine leere Luecke unter der Warenkorb-Leiste aufreissen". Am
     * BODY war sie weggenommen, an der LEISTE blieb sie stehen.
     *
     * Auf dem iPhone fiel das nicht auf: dort frisst die eigene Bedienleiste des Browsers
     * zusammen mit der sicheren Zone genau diesen Streifen. Auf einem Android-Telefon ohne
     * beides blieb er als leeres schwarzes Feld unter den Knoepfen stehen — der Wirt hat es
     * eingekringelt. Gemessen am 360x800-Bildschirm: die Knoepfe endeten bei 734, der
     * Bildschirm bei 800.
     *
     * `env(safe-area-inset-bottom)` bleibt: der Balken des iPhones und die Wischleiste von
     * Android liegen wirklich dort, und die Seite traegt `viewport-fit=cover`, also meldet
     * der Browser sie auch. Die 10 px sind Luft, kein Platzhalter.
     */
    padding: 4px 14px calc(10px + env(safe-area-inset-bottom, 0px));
}

/* source/style_css/195_kitchen_bar_split_view_continued.css - style.css: kitchen bar split view continued, part 26 of 78 (built by werkzeuge/parts_build.php) */
.kasse-cart-summary {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: none;
    border: none;
    color: var(--djk-white);
    font-weight: 800;
    font-size: 0.98rem;
    padding: 10px 0;
    cursor: pointer;
}

.kasse-cart-summary #cartTotal { color: var(--djk-yellow); }

.kasse-cart-chevron {
    display: inline-block;
    color: var(--djk-gray);
    font-size: 0.7rem;
    transition: transform var(--transition);
}

.kasse-bottom-bar.expanded .kasse-cart-chevron { transform: rotate(180deg); }

/* source/style_css/200_cart_total_animation.css - style.css part 27 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Die grosse Summe über dem Warenkorb ----------
   Aufgezogen nimmt die Leiste die GANZE Höhe ein (`top: 0`), und der freie Platz wird geteilt:
   25 % die Summe, 75 % die Liste — genau so, wie der Wirt es aufgezeichnet hat.

   Die Bewegung ist der eigentliche Punkt: die Summe kommt von OBEN herunter, die Liste von
   UNTEN herauf, und sie treffen sich an dieser Grenze. Dafür haben beide schon ihre volle Höhe,
   wenn es losgeht, und werden nur verschoben (`.korb-eingang`) — eine wachsende Höhe sähe aus
   wie Aufklappen, nicht wie Hereingleiten. Beim Zuklappen läuft dasselbe rückwärts.

   Die Höhen rechnet kasse.js aus (--korb-summe-h / --korb-liste-max): nur dort ist bekannt, wie
   viel die Kopfzeile und die Knopfreihe schon wegnehmen. */
:root {
    /*
     * Zwei Dauern, je eine für den oberen und den unteren Block — der Wirt stellt sie in der
     * Verwaltung ein (Kasse → Ansicht). personal/kasse.php schreibt die Werte hier hinein; die
     * Zahlen unten sind nur der Rückfall, falls die Seite sie einmal nicht mitbringt.
     */
    --korb-dauer-oben: 600ms;
    --korb-dauer-unten: 600ms;
    --korb-kurve: cubic-bezier(.22, .61, .36, 1);
    /* Für alles, was mit der LANGSAMEREN der beiden Bewegungen laufen soll. */
    --korb-bewegung: var(--korb-dauer-unten) var(--korb-kurve);
}
.kasse-summe-gross {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 0;
    margin: 0;
    overflow: hidden;
    opacity: 0;
    transform: translateY(-100%);
    background: var(--djk-yellow);
    color: #ffffff;
    border-radius: 12px;
    font-weight: 800;
    /* Die Zahl füllt die Fläche, ohne bei langen Beträgen aus ihr herauszulaufen. */
    font-size: clamp(1.8rem, 11vw, 3.6rem);
    line-height: 1;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
    /*
     * NUR schieben, nicht ein- und ausblenden.
     *
     * Der Wirt: „эти блоки могут не становиться транспарентными, а просто двигаться вверх-вниз."
     * Er hat recht — beim Zuklappen wurde der Block auf halbem Weg blass und tauchte am Ende
     * wieder auf, weil `expanded` erst danach faellt. Ein Block, der einfach hinausfaehrt und
     * dabei am Bildrand abgeschnitten wird (die Leiste hat `overflow: hidden`), sieht ruhiger
     * aus und laesst die Frage gar nicht erst aufkommen.
     *
     * Eigene Dauer je Block (Verwaltung → Kasse → Ansicht).
     */
    transition: transform var(--korb-dauer-oben) var(--korb-kurve);
}
.kasse-bottom-bar.expanded .kasse-summe-gross {
    height: var(--korb-summe-h, 25vh);
    margin: 0 0 8px;
    /* Deckkraft ohne Übergang: sie steht sofort, geschoben wird nur. Unsichtbar ist der Block
       zugeklappt ohnehin — dort ist seine Höhe 0 und `overflow: hidden`. */
    opacity: 1;
    transform: translateY(0);
}
/* Sind Positionen zum Aufteilen angehakt, steht hier deren Summe — dasselbe Zeichen wie an der
   kleinen Summe (siehe .cart-total-auswahl), damit man beide sofort als „Auswahl" liest. */
.kasse-summe-gross.ist-auswahl::after {
    content: '✓';
    font-size: 0.42em;
    margin-left: 0.35em;
    opacity: 0.85;
}

/* Die Höhe der aufgezogenen Liste setzt kasse.js als --korb-liste-max: sie reicht bis zur
   Unterkante der Suchleiste. Die 220px sind nur der Rückfallwert, falls das Skript nicht
   gelaufen ist. */
.kasse-bottom-bar .cart-list {
    max-height: var(--korb-liste-max, 220px);
    margin: 0 0 10px;
    /*
     * Der untere Block hat seine EIGENE Dauer. Und er liegt HINTER der Knopfreihe: der Wirt
     * hat es so verlangt — „нижняя когда поднимается или спускается она перекрывает две
     * нижние кнопки, сделай чтобы блок заходил и выходил за кнопками". Dafür bekommt die
     * Knopfreihe weiter unten eine eigene Ebene mit undurchsichtigem Grund; die Liste
     * verschwindet dahinter, statt über sie zu fahren.
     */
    position: relative;
    z-index: 0;
    transition: transform var(--korb-dauer-unten) var(--korb-kurve);
}
/* Zugeklappt: kein Platz mehr. Das `display:none` kommt erst NACH der Bewegung dazu
   (kasse.js) — sonst gäbe es nichts mehr zu bewegen. */
.kasse-bottom-bar:not(.expanded) .cart-list {
    max-height: 0;
    margin: 0;
    opacity: 0;
    transform: translateY(100%);
}

/* Aufgezogen (nur schmale Ansicht): siehe @media (max-width: 1199px) weiter oben. */
/* Der Zwischenstand einer Bewegung: die Summe steht über ihrem Platz, die Liste unter ihrem.
   kasse.js setzt ihn beim Öffnen für EIN Bild und beim Schliessen bis zum Ende. */
.kasse-bottom-bar.expanded.korb-eingang .kasse-summe-gross {
    transform: translateY(-100%);
}
.kasse-bottom-bar.expanded.korb-eingang .cart-list {
    transform: translateY(var(--korb-schub, 100%));
}

/* ---------- Die Kopfzeile (Tisch + Summe) gehört zum UNTEREN Block ----------
   Der Wirt: „надо сделать эту часть Tisch #101 с суммой вместе с нижним блоком поднималась,
   а верхняя сверху спускалась."

   Sie stand bisher fest an ihrem Platz, während beide Blöcke noch unterwegs waren. Verschoben
   wird um DIESELBE Strecke wie die Liste (`--korb-schub`, von kasse.js gesetzt) und nicht um
   die eigene Höhe: sonst wäre sie nach 40 Pixeln fertig, während die Liste noch 500 vor sich
   hat, und von „gemeinsam" bliebe nichts.

   Zugeklappt ist sie die einzige Zeile der kleinen Leiste — dort muss sie ohne Bewegung sofort
   an ihrem Platz stehen, deshalb `transition: none`. */
.kasse-bottom-bar .kasse-cart-summary {
    position: relative;
    z-index: 0;
    /* Eigener Grund: sonst sieht man beim Fahren die Kasse DURCH die Zeile hindurch, und sie
       wirkt löchrig. Mit ihm bilden Kopfzeile und Liste ein Stück, das sich gemeinsam bewegt —
       so hat es der Wirt verlangt („может этот объединить с листом заказов, чтобы у него был
       задний фон"). Dieselbe Farbe wie die Leiste, zugeklappt fällt sie also nicht auf. */
    background: var(--djk-black-card);
    transition: transform var(--korb-dauer-unten) var(--korb-kurve);
}
/* Ihr eigener Weg — auf das Pixel gemessen, siehe korbSetzen in kasse.js. Der Rückfall ist der
   Weg der Liste, falls das Skript einmal nicht dazu kommt. */
.kasse-bottom-bar.expanded.korb-eingang .kasse-cart-summary {
    transform: translateY(var(--korb-schub-kopf, var(--korb-schub, 100%)));
}
.kasse-bottom-bar:not(.expanded) .kasse-cart-summary {
    transition: none;
    transform: none;
    opacity: 1;
}
/* Der eine Augenblick, in dem kasse.js den Anfangsstand festschreibt: dabei darf sich nichts
   bewegen, sonst gleitet die Kopfzeile erst zu ihrem Startpunkt (gemessen: 57 px hin und
   zurück, weil `--korb-schub` beim ersten Rechnen noch nicht stand). */
.kasse-bottom-bar.korb-ohne-bewegung .kasse-cart-summary,
.kasse-bottom-bar.korb-ohne-bewegung .cart-list,
.kasse-bottom-bar.korb-ohne-bewegung .kasse-summe-gross {
    transition: none;
}

/* ---------- Animation des Warenkorbs: vier Varianten (26.09.2026) ----------
   Einstellung Verwaltung → Kasse → Ansicht („Animation des Warenkorbs"), gespeichert in
   einstellungen.kasse_korb_anim; personal/kasse.php setzt am body `korb-anim-<wert>`. Ohne Klasse
   läuft die Bewegung oben unverändert (Standard). Alles baut auf derselben Mechanik auf
   (expanded / korb-eingang / --korb-schub*), bewegt wird nur transform und opacity. */

/* FEDER — nur beim Öffnen (ohne `korb-eingang`) eine Kurve mit leichtem Überschwingen; das
   Zuziehen läuft mit der gewohnten Kurve. Der cubic-bezier davor ist der Rückfall für Browser
   ohne linear(). Nur die Kurve wird ersetzt, `korb-ohne-bewegung` (transition: none) gilt weiter. */
body.korb-anim-feder .kasse-bottom-bar.expanded:not(.korb-eingang) .kasse-summe-gross,
body.korb-anim-feder .kasse-bottom-bar.expanded:not(.korb-eingang) .cart-list,
body.korb-anim-feder .kasse-bottom-bar.expanded:not(.korb-eingang) .kasse-cart-summary {
    transition-timing-function: cubic-bezier(.34, 1.3, .64, 1);
    transition-timing-function: linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017 19.6%, 1.061 22.4%, 1.076 25.2%, 1.068 28.4%, 1.017 36.2%, 0.996 41.3%, 0.989 46.4%, 1 63%, 1);
}

/* REIHE — nur kasse.js (korbReiheSpielen, Web Animations): keine eigene Regel nötig. */

/* BLATT — die Liste kommt als Blatt mit runden oberen Ecken und Griff; die Kasse dahinter
   bleibt sichtbar, abgedunkelt und leicht verkleinert. Herunterziehen am Kopf schliesst. */
body.korb-anim-blatt .kasse-bottom-bar.expanded::before {
    background: #000;
    transition: opacity var(--korb-dauer-unten) var(--korb-kurve);
}
body.korb-anim-blatt .kasse-bottom-bar.expanded:not(.korb-eingang)::before {
    /* --korb-zieh (0…1) setzt kasse.js nur während des Ziehens am Griff. */
    opacity: calc(0.55 * (1 - var(--korb-zieh, 0)));
    transition: opacity var(--korb-dauer-unten) var(--korb-kurve);
}
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded .kasse-cart-summary {
    margin: 0 -14px;
    /* Rechts endete der Kopf vorher zu frueh (Foto 26.09.): der negative Rand streckt ein
       Element mit fester Breite nicht - also die Breite selbst um beide Raender vergroessern. */
    width: calc(100% + 28px);
    max-width: none;
    box-sizing: border-box;
    padding: 18px 14px 10px;
    border-top: none;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.4);
    /* Gezogen wird am Kopf — dort gibt es nichts zu rollen. Die Liste rollt weiter normal. */
    touch-action: none;
}
/* Der Griff: nur Zeichen, die Fläche zum Ziehen ist der ganze Kopf. */
body.korb-anim-blatt .kasse-bottom-bar.expanded .kasse-cart-summary::before {
    content: '';
    position: absolute;
    top: 6px;
    left: 50%;
    width: 36px;
    height: 4px;
    margin-left: -18px;
    border-radius: 2px;
    background: #94a3b8;
    pointer-events: none;
}
/* Das Blatt ist durchgehend: eigener Grund unter der Liste, kein Spalt über den Knöpfen. */
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded .cart-list {
    background: var(--djk-black-card);
    margin-bottom: 0;
    padding-bottom: 10px;
}
/* Die Kasse tritt zurück, solange das Blatt offen ist (kasse.js: body.korb-blatt-hinten). */
body.korb-anim-blatt #kasseProductsSection,
body.korb-anim-blatt .kasse-search-bar {
    transform-origin: 50% 0;
    transition: transform var(--korb-dauer-unten) var(--korb-kurve);
}
body.korb-anim-blatt.korb-blatt-hinten #kasseProductsSection,
body.korb-anim-blatt.korb-blatt-hinten .kasse-search-bar {
    transform: scale(0.94);
}
/* Während des Ziehens folgt alles dem Finger, ohne Übergang. */
body.korb-zieht .kasse-bottom-bar .kasse-cart-summary,
body.korb-zieht .kasse-bottom-bar .cart-list,
body.korb-zieht #kasseProductsSection,
body.korb-zieht .kasse-search-bar,
body.korb-zieht .kasse-bottom-bar.expanded::before {
    transition: none;
}
/* Losgelassen unter 30 %: federnd zurück an den Platz. */
body.korb-anim-blatt .kasse-bottom-bar.korb-zurueck .kasse-cart-summary,
body.korb-anim-blatt .kasse-bottom-bar.korb-zurueck .cart-list {
    transition: transform 450ms linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%, 0.938 16.7%, 1.017 19.6%, 1.061 22.4%, 1.076 25.2%, 1.068 28.4%, 1.017 36.2%, 0.996 41.3%, 0.989 46.4%, 1 63%, 1);
}

/* FLUG — die grosse Summe gleitet nicht herein, ihre Karte blendet nur ein; der Betrag fliegt
   als eigenes Element (.korb-flug-zahl, kasse.js) aus der Kopfzeile an seinen Platz. */
body.korb-anim-flug .kasse-bottom-bar.expanded .kasse-summe-gross,
body.korb-anim-flug .kasse-bottom-bar.expanded.korb-eingang .kasse-summe-gross {
    transform: none;
    transition: opacity calc(var(--korb-dauer-oben) * 0.5) ease;
}
body.korb-anim-flug .kasse-bottom-bar.expanded.korb-eingang .kasse-summe-gross { opacity: 0; }
.kasse-bottom-bar.korb-flug .kasse-summe-gross { color: transparent; }
.korb-flug-zahl {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 70;
    margin: 0;
    color: #ffffff;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    transform-origin: 0 0;
    will-change: transform;
    pointer-events: none;
}

/* Wer weniger Bewegung wünscht, bekommt bei allen vier Varianten keine. */
@media (prefers-reduced-motion: reduce) {
    body[class*="korb-anim-"] .kasse-bottom-bar .kasse-summe-gross,
    body[class*="korb-anim-"] .kasse-bottom-bar .cart-list,
    body[class*="korb-anim-"] .kasse-bottom-bar .kasse-cart-summary,
    body[class*="korb-anim-"] .kasse-bottom-bar.expanded::before,
    body[class*="korb-anim-"] #kasseProductsSection,
    body[class*="korb-anim-"] .kasse-search-bar {
        transition: none !important;
    }
}

.kasse-bottom-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding-bottom: 14px;
    /*
     * Die Knopfreihe liegt VOR der Liste — sie ist der feste Rand der Leiste, und was sich
     * bewegt, verschwindet dahinter. Der eigene Grund ist dafür nötig: ohne ihn schiene die
     * Liste durch die Lücken zwischen den Knöpfen hindurch.
     */
    position: relative;
    z-index: 1;
    background: var(--djk-black-card);
    /*
     * Eine eigene Ebene für die Knopfreihe.
     *
     * Der Wirt: „когда она доходит до самого конца, немного дёргаются кнопки." Gemessen bewegt
     * sich die Reihe dabei NICHT — sie steht in jedem Bild auf 723, in beide Richtungen. Das
     * Zucken kommt vom Neuzeichnen: in dem Augenblick, in dem die Leiste von Bildschirmhöhe auf
     * ihre kleine Höhe fällt, bekommt der Warenbereich dahinter seine Rollhöhe zurück, und der
     * Browser malt die ganze Fläche neu.
     *
     * `translateZ(0)` legt die Reihe auf eine eigene Ebene; sie wird dann nicht mit neu
     * gerastert. Bewusst NUR hier und nicht an der Liste: diese Reihe ist 121 Pixel hoch, eine
     * bildschirmgrosse Liste wäre eine teure Ebene (siehe Falle 86, `will-change` auf dem
     * Telefon).
     */
    transform: translateZ(0);
    /*
     * Der Grund reicht bis zur UNTERKANTE der Leiste.
     *
     * Unter den Knöpfen liegt noch die Fusspolsterung der Leiste (52 px + Gerätekante). Ohne
     * diesen Griff schaute die vorbeifahrende Liste dort hindurch — im Bild gesehen, während
     * sie hinter den Knöpfen nach unten fuhr. Die Polsterung wandert deshalb IN die Knopfreihe
     * (`padding-bottom`) und wird durch ein gleich grosses negatives `margin-bottom` wieder
     * ausgeglichen: die Knöpfe bleiben, wo sie sind, nur ihr Grund reicht weiter.
     */
    /* Die Fusspolsterung der Leiste ist seit dem 31.08.2026 nur noch 10 px plus Geraetekante
       (vorher 52 — die Reserve fuer eine Leiste, die die Kasse nicht hat). Dieselbe Zahl muss
       hier stehen, sonst reicht der Grund entweder nicht bis zur Unterkante oder darueber
       hinaus. */
    padding-bottom: calc(14px + 10px + env(safe-area-inset-bottom, 0px));
    margin-bottom: calc(-10px - env(safe-area-inset-bottom, 0px));
}

.kasse-bottom-actions .btn { flex: 1 1 90px; min-width: 90px; padding: 12px 4px; height: 55px; font-size: 0.82rem; overflow: hidden; }
/* Zeichen UND Wort nebeneinander auf denselben 90 px (02.09.2026, auf Ansage).

   Das Zeichen ist das, was man aus dem Augenwinkel trifft; das Wort bestaetigt es. Damit
   beides in einen Knopf passt, der schon 55 hoch und nur 90 breit ist: das Zeichen bekommt
   ein festes Mass (ohne das nimmt sich ein SVG die ganze Hoehe — siehe „Knoepfe in den
   Rueckfrage-Fenstern" weiter oben) und der Abstand ist knapp. */
.kasse-bottom-actions .btn:not(.kasse-aktion-zeichen) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.kasse-bottom-actions .btn:not(.kasse-aktion-zeichen) svg,
.kasse-bottom-actions .btn:not(.kasse-aktion-zeichen) .icon {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
}
/*
 * Die beiden Zeichen-Knöpfe in der Mitte („Tisch wechseln" und „Nachricht an die Küche").
 *
 * Vier beschriftete Knöpfe nebeneinander passen auf ein Telefon nicht — bei 390 px blieben je
 * 90 px, und „Tisch wechseln" wäre abgeschnitten. Diese beiden tragen deshalb nur ihr Zeichen und
 * sind so breit, wie eine Fingerkuppe braucht; Storno und Bezahlen behalten ihre Wörter und den
 * Platz. Der Name steht im `title`/`aria-label`.
 */
.kasse-bottom-actions .btn.kasse-aktion-zeichen {
    flex: 0 0 58px;
    min-width: 58px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.kasse-bottom-actions .btn.kasse-aktion-zeichen .icon { width: 24px; height: 24px; }
/* Die Sätze im Fenster „Nachricht an die Küche" — eine Liste zum Lesen, keine Ja/Nein-Frage:
   deshalb ohne die 40 px Polsterung der grossen Knöpfe, sonst stünde das Feld für den eigenen
   Satz weit unterhalb des Bildschirmrands. */
.ergaenzen-satzliste { display: flex; flex-direction: column; gap: 8px; }
.modal-box .ergaenzen-satzliste .btn-block.ergaenzen-satz {
    padding: 14px 16px;
    text-align: left;
    justify-content: flex-start;
    border-radius: 10px;
    font-size: 0.95rem;
}
.kasse-bottom-actions .btn.has-active { background: red; color: #fcfcfc; border-color: red; }

/* Full-screen category picker */
.kategorie-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 90;
    background: var(--djk-black);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: calc(20px + env(safe-area-inset-top, 0px)) 12px calc(16px + env(safe-area-inset-bottom, 0px));
}

.kategorie-overlay.active { display: block; }

.kategorie-overlay-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.kategorie-overlay-header h3 { margin: 0; }

/* source/style_css/205_cart_total_animation_continued.css - style.css: cart total animation continued, part 28 of 78 (built by werkzeuge/parts_build.php) */
/* Was in der gewaehlten Tischgruppe offen steht — direkt NEBEN dem Titel, nicht am anderen
   Ende der Zeile: es gehoert zu „Tisch waehlen" wie der Preis zum Namen.

   `margin-right: auto` traegt die ganze Anordnung: der Kopf ist `space-between`, und ohne
   diese Zeile setzte sich die Summe genau in die Mitte zwischen Titel und Kreuz. So nimmt
   sie den freien Platz und das Kreuz bleibt rechts aussen.

   Die Akzentfarbe, weil es dieselbe Zahl ist wie unten in der Leiste („Tisch 110  6,00 €") —
   der Kellner sucht am Bildschirm nach DIESER Farbe, wenn er nach Geld sucht. */
.kategorie-overlay-header .tisch-overlay-summe {
    margin-right: auto;
    padding-left: 12px;
    color: var(--djk-yellow);
    font-size: 1.05rem;
    font-weight: 800;
    white-space: nowrap;
}

/* Tisch wechseln (Produkte übertragen) statt normaler Tischwahl — visuell abheben, damit klar
   ist, dass eine Auswahl hier Positionen verschiebt statt nur den aktiven Tisch zu setzen. */
#tischOverlay.tisch-overlay-transfer { background: var(--djk-black); border-top: 4px solid var(--djk-yellow); }
#tischOverlay.tisch-overlay-transfer .kategorie-overlay-header h3 { color: var(--djk-yellow); }

/* source/style_css/210_header_buttons_join_back.css - style.css part 29 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/*
 * ═══ DIE ZWEI KNOEPFE IM KOPF: ZUSAMMENRUECKEN UND ZURUECK (12.09.2026) ═══
 *
 * Sie stehen links vom Kreuz — genau dort, wo der Wirt sie eingekringelt hat. Dieselbe
 * Groesse wie das Kreuz, damit die Zeile ruhig bleibt: drei verschieden grosse Knoepfe
 * nebeneinander lesen sich wie drei verschieden wichtige Dinge.
 */
.tisch-kopf-btn {
    position: static;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    margin-right: 6px;
    padding: 0;
    border: 1px solid var(--djk-border);
    border-radius: 12px;
    background: transparent;
    color: var(--djk-text);
    cursor: pointer;
}
.tisch-kopf-btn:active { transform: scale(.96); }
/* Der Modus laeuft: der Knopf bleibt gedrueckt, solange gewaehlt wird. */
.tisch-kopf-btn.active {
    border-color: var(--djk-yellow);
    background: rgba(240, 180, 41, 0.16);
}
/*
 * WAEHREND DER WAHL sagt eine Kante, was schon gewaehlt ist: der HAUPTTISCH kraeftig, die
 * anderen leiser. Keine Fuellfarbe — die traegt schon den Zustand der Kueche, und zwei
 * Auskuenfte in derselben Farbe sind eine zu viel.
 */
/*
 * WAAGERECHT ODER SENKRECHT? (13.09.2026) — die Frage vor dem Zusammenruecken.
 *
 * Dieselben Kacheln wie bei der Zahlungsart (`.pay-method-btn`): der Wirt kennt sie, und der
 * Daumen weiss, wohin. Nur ZWEI, gleich breit — das Raster statt der Flex-Zeile, denn deren
 * Regel fuer die letzte Reihe haette die zweite Kachel auf zwei Drittel gedehnt.
 *
 * Das Bild: der Haupttisch in der Farbe des Hauses gefuellt, die anderen nur umrandet.
 */
.tz-richtung-titel { margin-top: 0; }
.tz-richtung-wahl { display: grid; grid-template-columns: 1fr 1fr; }
.tz-richtung-wahl .pay-method-btn > span { flex-direction: column; gap: 2px; }
.tz-richtung-wahl .pay-method-btn small { font-weight: 500; font-size: .78rem; opacity: .7; }
.tz-richtung-bild { width: 76px; height: 46px; }
.tz-richtung-bild rect { stroke-width: 2; }
.tz-richtung-bild .tz-bild-haupt { fill: var(--djk-yellow); stroke: var(--djk-yellow); }
.tz-richtung-bild .tz-bild-teil { fill: transparent; stroke: currentColor; }
.tz-richtung-abbrechen { margin-top: 14px; }

#tischOverlay.tische-zusammen-modus .tp-view-tisch-shape,
#tischOverlay.tische-zusammen-modus .tisch-tile { opacity: .72; }
#tischOverlay .tisch-zusammen-haupt,
#tischOverlay .tisch-zusammen-gewaehlt { opacity: 1; }
#tischOverlay .tisch-zusammen-haupt .tp-view-tisch-shape,
#tischOverlay g.tisch-zusammen-haupt .tp-view-tisch-shape {
    stroke: #ffffff;
    stroke-width: 5;
}
#tischOverlay .tisch-zusammen-gewaehlt .tp-view-tisch-shape,
#tischOverlay g.tisch-zusammen-gewaehlt .tp-view-tisch-shape {
    stroke: #ffffff;
    stroke-width: 3;
    stroke-dasharray: 7 5;
}
/* Und dasselbe auf der Kachel ohne Grundriss. */
#tischOverlay div.tisch-zusammen-haupt { outline: 4px solid #ffffff; outline-offset: -4px; }
#tischOverlay div.tisch-zusammen-gewaehlt { outline: 3px dashed #ffffff; outline-offset: -3px; }

/* .modal-close defaults to position:absolute for use inside .modal-box; inside the
   overlay header it must stay in normal flex flow, otherwise it pins to the raw
   viewport edge and overlaps the phone's status bar / gesture area. */
.kategorie-overlay-header .modal-close {
    position: static;
    flex-shrink: 0;
    padding: 8px;
    margin: -8px -8px -8px 0;
    line-height: 1;
}
/* Die Groesse des Zeichens gilt auch fuer das Kreuz am Fuss der Tischgruppen-Saeule
   (19.09.2026): EINE Zahl fuer beide, damit sie nicht wieder auseinanderlaufen. */
.kategorie-overlay-header .modal-close,
.tisch-kat-filter .modal-close { font-size: 1.7rem; }

/* Gleiches auto-fill-Prinzip wie .product-grid — gilt für Tisch- UND Kategorie-Auswahl,
   da beide Overlays diese Klasse teilen (siehe personal/kasse.php, personal/kassenbericht.php). */
.kategorie-overlay-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
    gap: 8px;
}

.kategorie-tile .product-tile-photo { aspect-ratio: 1.1; }
/* Die Kategorie teilt sich `.product-tile-name` mit dem Produkt — hier bekommt sie ihre eigene
   Schrift und Größe, sonst gäbe es die Einstellung nur einmal für beide. */
.kategorie-tile .product-tile-name {
    text-align: center;
    padding: 8px 6px;
    font-size: var(--kasse-schrift-kategorie-groesse, 0.78rem);
    font-family: var(--kasse-schrift-kategorie, inherit);
}
/* Kategorienamen linksbündig: sie sind ganze Wörter ("Flaschenbier Biermix") und brechen oft
   auf zwei Zeilen um — zentriert steht die zweite Zeile dann eingerückt unter der ersten, und
   das Auge findet den Anfang nicht mehr. Der farbige Streifen links markiert ohnehin die
   Kante, an der die Schrift beginnen soll.

   NICHT für Tischkacheln: die tragen dieselbe Klasse (`product-tile kategorie-tile tisch-tile`,
   siehe buildTischTileHtml in kasse.js), zeigen aber nur eine kurze Nummer wie "#101" — die
   gehört mittig. */
.kategorie-tile:not(.tisch-tile) .product-tile-name { text-align: left; padding-bottom: 10px; }
/* Statt einer festen gelben Auswahl-Markierung: ein farbiger Streifen links, in der Farbe der
   gerade aktiven Warengruppe (--aktive-warengruppe-farbe, wird von kasse.js beim Wechsel der
   Warengruppe gesetzt — siehe #warengruppenRow). Fällt auf Gelb zurück, solange keine
   Warengruppe eine eigene Farbe hat. Gilt auch für die Produkt-Kacheln im Raster darunter
   (#productGrid .product-tile), damit sichtbar bleibt, in welcher Warengruppe man gerade ist.
   !important nötig, da farbige Kategorie-/Produkt-Kacheln (Foto-Akzentfarbe, siehe kasse.js
   buildKategorieTileHtml/buildProduktTileHtml) ihre eigene border-color per Inline-Style setzen —
   die hätte sonst gegenüber dieser Klasse Vorrang, egal wie spezifisch der Selektor ist. */
.kategorie-tile.active { border-left: 5px solid var(--aktive-warengruppe-farbe, var(--djk-yellow)) !important; }
/* Der farbige Streifen bleibt der KATEGORIE (Zeile darueber) und ist von den Produkt-Kacheln
   verschwunden — abgeschaltet vom Wirt im Bild. Der Grund leuchtet ein: in welcher Warengruppe
   man steht, sagt schon die hervorgehobene Kategorie links; an jeder einzelnen Produkt-Kachel
   wiederholt, wurde daraus ein Streifenmuster statt einer Auskunft. */

/* Die Start-Kategorie trägt unten rechts einen kleinen Stern. Der dunkle Schatten hält ihn auch
   auf hellen Kategoriefarben und über einem Foto lesbar.
   Die Ecke ist gemessen, nicht geraten: eine Kategorie-Kachel in der linken Spalte ist 133 breit
   und trägt ihren Namen linksbündig ab 13px. Links läge der Stern auf dem ersten Buchstaben,
   und rechts NEBEN dem Namen wird es eng, sobald der Name lang ist — deshalb unten rechts, mit
   einem freigehaltenen Streifen (siehe padding-bottom weiter unten). */
/* ==============================================================================================
   HOEHE UND TEXTLAGE JE KACHELART (02.09.2026, auf Ansage des Wirts)
   ==============================================================================================
   „мы должны в админке настраивать и высату категории и плиток продуктов и Warengruppen и
   текст … у всех этих трех отдельно должна настраиваться."

   Die Werte kommen als Variablen aus `kasse_kachel_variablen()` (includes/kasse_schriften.php);
   dort steht auch, warum die drei Arten getrennt einstellbar sind. Ohne Einstellung stehen
   dort genau die bisherigen Werte, die Regeln aendern also nichts, solange niemand etwas
   waehlt — mit EINER Ausnahme: die Kategorie steht jetzt mittig, so angesagt.

   Die Kachel ist eine SPALTE. Deshalb ist `justify-content` die senkrechte Achse und
   `align-items` die waagerechte — wer das vertauscht, dreht die Einstellung um 90 Grad.
   `min-height` und nicht `height`: ein langer Name darf die Kachel weiter wachsen lassen,
   sonst stuende er ausserhalb.
   ============================================================================================== */
/* AUF DEM GROSSEN BILDSCHIRM ist die Kategorie-Kachel ein `block` — dort sagen Flex-Achsen
   gar nichts. Sie wird deshalb hier zur SPALTE: ein `block` stapelt seine Kinder ohnehin
   untereinander, es bewegt sich also nichts, was nicht soll — aber die senkrechte Achse
   existiert. In einer Spalte ist `justify-content` die SENKRECHTE.

   Tischkacheln tragen dieselbe Klasse und bleiben aussen vor: sie zeigen nur „#101", und
   das gehoert mittig, unabhaengig von dieser Einstellung. */
.kategorie-tile:not(.tisch-tile) {
    display: flex;
    flex-direction: column;
    min-height: var(--kasse-hoehe-kategorie, 58px);
    justify-content: var(--kasse-text-kategorie-senkrecht, center);
    align-items: var(--kasse-text-kategorie-waagerecht, center);
    /* Siehe die Erklaerung an der Produktkachel darunter — dieselben zwei Fallen. */
    min-width: 0;
    width: 100%;
}
.kategorie-tile:not(.tisch-tile) .product-tile-name {
    text-align: var(--kasse-text-kategorie-aus, center);
    max-width: 100%;
}

#kasseProductsSection .product-tile:not(.kategorie-tile):not(.tisch-tile) {
    min-height: var(--kasse-hoehe-produkt, auto);
    /*
     * DIE BREITE GEHOERT DER SPALTE, NICHT DER HOEHE.
     *
     * Die Kachel traegt `aspect-ratio` (Kasse → Ansicht → Kachelhoehe zur Breite). Mit einer
     * `min-height` rechnet der Browser daraus die BREITE zurueck — gemessen: Spalte 111,9,
     * Kachel 190, ueber den rechten Rand hinaus. Dieselbe Falle steht seit dem 12.08. weiter
     * oben im Stylesheet. Mit fester Breite bestimmt das Verhaeltnis nur noch die Hoehe.
     */
    width: 100%;
    justify-content: var(--kasse-text-produkt-senkrecht, flex-start);
    align-items: var(--kasse-text-produkt-waagerecht, flex-start);
    /*
     * `align-items` NIMMT DEM KIND DAS STRECKEN — und damit der Kachel ihre Breite.
     *
     * Gemessen: mit einer Textlage ausser „links" liefen die Kacheln ueber den rechten Rand
     * und beruehrten sich. Zwei Vorgaben zusammen:
     *   1. In einer Flex-Spalte ist `align-items: stretch` die Vorgabe; der Name fuellt die
     *      Breite und bricht um. Bei `center`/`flex-end` bekommt er seine EIGENE Breite —
     *      bei „Alkoholfrei Spalter Bier" die des laengsten Wortes.
     *   2. Ein Raster-Kind hat `min-width: auto` und kann nicht schmaler werden als sein
     *      Inhalt. Also wuchs die Spalte mit.
     * `min-width: 0` hier und `max-width: 100%` am Namen halten das an.
     */
    min-width: 0;
}
#kasseProductsSection .product-tile:not(.kategorie-tile):not(.tisch-tile) .product-tile-name {
    text-align: var(--kasse-text-produkt-aus, left);
    max-width: 100%;
}

/* LUFT FUER DIE STERNE (02.09.2026, auf Ansage).

   Eine einzeilige Kachel war exakt so hoch wie ihr Name (50,25) und die Sterne sassen mit
   3 px auf der Unterkante. Acht Punkte mehr als MINDESTHOEHE: der Name bleibt, wo er war,
   der Streifen entsteht unten, wo die Sterne stehen. Zweizeilige Kacheln (66,5) merken
   nichts davon.

   Derselbe Wert steht im Kellner-Programm (SpaltenKachel in Tisch.kt) — zusammen aendern. */
.kategorie-tile.ist-start-kat::after {
    content: "★";
    position: absolute;
    /* 8 statt 3 (02.09.2026, auf Ansage: „подними звезда повыше"). Die Kachel ist seit
       demselben Tag hoch genug dafuer; auf der Kante sass er wie angeklebt. */
    bottom: 8px;
    right: 5px;
    font-size: 0.95rem;
    line-height: 1;
    /* Farbe aus der Verwaltung (Produkte -> Kategorien -> "Sterne auf der Kategorie-Kachel").
       Der Rueckfallwert ist genau das bisherige Aussehen; die Variable wird nur ausgegeben,
       wenn wirklich etwas eingestellt ist, sonst ginge die Themenfarbe beim Umschalten auf
       dunkel verloren. */
    color: var(--kasse-stern, var(--djk-copper, #fbbf24));
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
    pointer-events: none;
}


/* Zweite Marke: hier macht diese Warengruppe auf. DERSELBE Stern, nur in einer anderen Farbe —
   beide Farben kommen aus der Verwaltung. Sie können auf DERSELBEN Kachel stehen (meine
   Start-Kategorie UND Start ihrer Gruppe), deshalb müssen sie sich unterscheiden lassen.
   Der eigene Stern behält seinen Platz ganz aussen, der zweite rückt vor ihn: die gewohnte
   Marke soll nicht wandern, nur weil die andere dazukommt oder wegfällt. */
.kategorie-tile.ist-wg-start-kat::before {
    content: "★";
    position: absolute;
    /* 8 statt 3 (02.09.2026, auf Ansage: „подними звезда повыше"). Die Kachel ist seit
       demselben Tag hoch genug dafuer; auf der Kante sass er wie angeklebt. */
    bottom: 8px;
    right: 5px;
    font-size: 0.95rem;
    line-height: 1;
    color: var(--kasse-wg-stern, var(--djk-yellow));
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
    pointer-events: none;
}
.kategorie-tile.ist-start-kat.ist-wg-start-kat::before { right: 22px; }

/* Die Sterne stehen unten rechts. Freigehalten wird dafür NICHTS mehr — das Polster ist das
   normale der Kachel.
   Zwischenstände waren: rechts neben dem Namen bis zu 37px (schnürte den Namen genau dort ein,
   wo er am längsten ist) und danach ein eigener Streifen von 21px unten. Beides ausdrücklich
   verworfen; die Kacheln sind hoch genug, dass der Name über den Sternen endet.
   Bleibt hier stehen, damit niemand die Regel für vergessen hält und wieder ein Polster
   erfindet — der Wert ist Absicht. */
.kategorie-overlay-grid .kategorie-tile.ist-start-kat,
.kategorie-overlay-grid .kategorie-tile.ist-wg-start-kat {
    padding-bottom: 8px;
}

/* source/style_css/220_category_long_press_sheet.css - style.css part 30 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Blatt zum langen Drücken auf eine Kategorie (siehe #katMenue in personal/kasse.php) --- */
.kat-menue .kat-menue-box { max-width: 420px; padding: 18px; }
.kat-menue-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}
.kat-menue-kopf h3 { margin: 0; font-size: 1.05rem; }
/* Ein Menüeintrag, kein Formularfeld: volle Breite, links das Zeichen, rechts der Text.
   `text-align: left`, weil <button> von sich aus zentriert. */
.kat-menue-eintrag {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    padding: 12px;
    text-align: left;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    color: inherit;
    cursor: pointer;
}
.kat-menue-eintrag:hover { border-color: var(--djk-yellow); }
.kat-menue-stern { flex: 0 0 auto; color: var(--djk-gray); line-height: 0; }
.kat-menue-stern svg { width: 22px; height: 22px; }
/* Gesetzt: der Stern füllt sich und bekommt dieselbe Kupferfarbe wie die Marke auf der Kachel,
   damit erkennbar ist, dass beide dasselbe meinen. */
.kat-menue-eintrag.an { border-color: var(--djk-copper, #fbbf24); }
.kat-menue-eintrag.an .kat-menue-stern { color: var(--djk-copper, #fbbf24); }
.kat-menue-eintrag.an .kat-menue-stern svg { fill: currentColor; }
.kat-menue-text { display: block; }
.kat-menue-text strong { display: block; margin-bottom: 3px; }
.kat-menue-text .hint { display: block; }
/* `[hidden]` verliert gegen jede Anzeige-Regel des Autors (siehe Fallen). Die beiden Flächen
   sind zwar schlichte Blöcke, aber die Regel steht hier, bevor jemand ihnen ein `display` gibt. */
.kat-menue-box [hidden] { display: none; }

/* Fläche B: die Kategorien einer Warengruppe zur Auswahl. Ein Haken statt eines Sterns —
   hier wird EINE aus mehreren gewählt, nicht eine einzelne an- und ausgeschaltet. */
.kat-menue-frage { margin: 0 0 12px; }
.kat-menue-liste { display: grid; gap: 8px; max-height: 46vh; overflow-y: auto; }
.kat-menue-haken { flex: 0 0 auto; color: transparent; line-height: 0; }
.kat-menue-haken svg { width: 22px; height: 22px; }
.kat-menue-wahl.an { border-color: var(--djk-yellow); }
.kat-menue-wahl.an .kat-menue-haken { color: var(--djk-yellow); }
.kat-menue-wahl .kat-menue-text strong { margin-bottom: 0; }
.kat-menue-fussnote { margin: 12px 0 0; }

/* Ziffernblock neben der Kategorienauswahl — nur auf dem großen Kassen-Bildschirm sichtbar
   (siehe @media min-width:1200px), auf Handy/Tablet bleibt die Kategorienauswahl unverändert. */
.kasse-dial-panel { display: none; }

/* Hülle um Kategorien und Warengruppen (siehe personal/kasse.php). Auf dem großen Bildschirm
   verschwindet sie aus dem Layout: beide Blöcke liegen dort per position:fixed an ihrem Platz,
   und eine zusätzliche Kiste dazwischen würde nur stören. Erst auf Handy/Tablet wird sie zur
   Spalte, in der die beiden übereinander liegen (siehe @media max-width:1199px). */
.kasse-spalte-links { display: contents; }
.kasse-spalte-wuerfel { display: contents; }
/* Die Menü-Fläche gibt es nur auf dem Handy-Würfel — auf dem großen Bildschirm ist die linke
   Spalte der Bon, und dort führt der Uhr-Knopf oben zum Verlauf. */
.kasse-menue-flaeche { display: none; }

/* Warengruppen-Filter vor der Kategorienauswahl (Zone "Warengruppen") — wie der Ziffernblock
   nur auf dem großen Kassen-Bildschirm sichtbar; auf Handy/Tablet erscheint er in derselben
   Spalte wie die Kategorien, sobald dorthin gewischt wird. */
.warengruppen-row { display: none; }
/* Überschrift/Schließen nur auf der mobilen Vollbild-Seite (siehe #warengruppenRow.mobile-open
   weiter unten) — in der dauerhaften Spalte des großen Bildschirms würde sie sonst eine
   Rasterzelle belegen und die Knöpfe verschieben. */
.warengruppen-row-header { display: none; }
/* Groß wie der STORNO-Knopf im Ziffernblock (.kasse-dial-topbtns .btn: padding 25px 6px) —
   das ist bewusst dieselbe Griffigkeit, beide sitzen in derselben schmalen Spalte. Die Farbe
   kommt aus der Admin (warengruppen.farbe/text_farbe, siehe personal/kasse.php Inline-Style)
   statt fest hier — nur der Auswahlring ist hier verdrahtet, damit die eigene Farbe sichtbar
   bleibt (wie bei .kategorie-tile.active). */
.warengruppe-chip {
    display: block;
    width: 100%;
    text-align: center;
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 30px 6px;
    cursor: pointer;
    /* Schrift und Größe aus der Verwaltung; ohne Einstellung wie bisher (erbt von der App). */
    font-family: var(--kasse-schrift-warengruppe, inherit);
    font-size: var(--kasse-schrift-warengruppe-groesse, inherit);
    transition: filter var(--transition), border-color var(--transition), box-shadow var(--transition);
}
.warengruppe-chip:hover { filter: brightness(1.08); }

/* Hoehe und Textlage der Warengruppe (02.09.2026, aus der Verwaltung).

   Sie steht HINTER der Grundregel darueber: davor haette sie nie gegolten — dieselbe Falle
   wie bei `.pay-method-btn` am selben Tag (gleiches Gewicht, die spaetere Regel gewinnt).

   Und die Kachel wird hier zur SPALTE: als `display: block` haetten `justify-content` und
   `align-items` nichts zu sagen. Als Spalte ist `justify-content` die senkrechte Achse. */
.warengruppe-chip {
    display: flex;
    flex-direction: column;
    min-height: var(--kasse-hoehe-warengruppe, auto);
    justify-content: var(--kasse-text-warengruppe-senkrecht, flex-start);
    align-items: var(--kasse-text-warengruppe-waagerecht, flex-start);
    text-align: var(--kasse-text-warengruppe-aus, left);
    /* Siehe die Produktkachel: ohne `min-width: 0` kann sie nicht schmaler werden als ihr
       laengstes Wort, sobald `align-items` das Strecken abschaltet. */
    min-width: 0;
}
/* Dieselbe Sprache wie bei der aktiven Kategorie und den Produktkacheln: ein farbiger Streifen
   an der linken Kante. Er markiert deutlich, ohne sich ueber die Flaeche zu legen — der
   frühere `box-shadow: inset 0 0 0 2px` ergab zusammen mit dem 1px-Rand ein 3px breites Band,
   das sich rundum in die Kachel hineinfrass, genau gegen die Absicht eine Zeile weiter oben.

   Der Streifen nimmt bewusst die Akzentfarbe und NICHT `--aktive-warengruppe-farbe` wie bei
   .kategorie-tile.active: dort markiert die Gruppenfarbe eine fremde Kachel, hier waere sie
   die eigene Hintergrundfarbe des Chips — der Streifen wuerde unsichtbar. */
.warengruppe-chip.active { border-color: var(--djk-yellow); border-left-width: 5px; }

/* Mobil/Tablet (<1200px): Hauptbildschirm ist dieselbe 2-Spalten-Aufteilung wie auf dem Desktop —
   links dauerhaft die Kategorien der aktiven Warengruppe (#kategorieOverlay, schmale Textliste),
   rechts deren Produkte (#kasseProductsSection). Beide per position:fixed aus dem normalen Fluss
   geholt, damit sie unabhängig voneinander scrollen; #kategorieOverlay ist hier kein Overlay mehr,
   sondern feste Spalte, deshalb display/inset überschrieben. Zwischen Suchleiste (74px) und
   Warenkorb-Leiste unten. */
@media (max-width: 1199px) {
    /* Grid statt der sonst hier geltenden Flex-Spalte (siehe body.kasse-body weiter oben): nur so
       können Kategorien und Produkte nebeneinander stehen, obwohl #kategorieOverlay im Markup
       hinter der Warenkorb-Leiste steht. Ohne feste Höhenangaben — die mittlere Zeile nimmt sich
       den Platz, der zwischen Suchleiste und Warenkorb-Leiste übrig bleibt. Alle übrigen
       body-Kinder (Overlays, Modale) sind position:fixed und damit nicht Teil des Grids. */
    /* Spaltenbreite und Produktspalten kommen aus Admin → Kasse (siehe admin/kasse.php); die
       Variablen setzt personal/kasse.php am Seitenanfang. Die Fallbacks halten das Layout
       heil, falls die Einstellung fehlt. */
    body.kasse-body {
        display: grid;
        grid-template-columns: var(--kasse-mobil-kat-breite, 38%) 1fr;
        grid-template-rows: auto minmax(0, 1fr) auto;
    }
    /* Nur noch die Platzierung im Raster. Die Farbe steht jetzt am Grundsatz der Leiste
       (--kasse-leiste) und gilt damit für jede Breite — vorher färbte diese Zeile allein das
       Handy dunkel und liess den grossen Bildschirm weiss. */
    body.kasse-body .kasse-search-bar { grid-column: 1 / -1; grid-row: 1; }
    body.kasse-body .kasse-bottom-bar { grid-column: 1 / -1; grid-row: 3; }

    /* Die linke Spalte ist ein WÜRFEL, der sich dreht: vorn die Kategorien, auf der linken
       Seitenfläche die Warengruppen. Gewischt wird zwischen beiden — siehe "Wischen in der
       linken Spalte" in kasse.js.

       Die Arbeit ist auf drei Ebenen verteilt, und das ist kein Zufall:
         .kasse-spalte-links   — die Hülle: sitzt in der Rasterzelle, beschneidet (overflow) und
                                 stellt mit `perspective` den Raum auf. KEIN transform: das würde
                                 fixierte Nachfahren an sie binden.
         .kasse-spalte-wuerfel — dreht sich (`preserve-3d`). Er darf KEIN overflow bekommen:
                                 alles außer `visible` macht die 3D-Ebene wieder flach.
         die beiden Flächen    — stehen still, jede an ihrer Seite des Würfels.
       Eine Ebene weniger, und einer dieser drei Punkte fällt hinten runter. */
    body.kasse-body .kasse-spalte-links {
        display: block;
        grid-column: 1;
        grid-row: 2;
        position: relative;
        min-height: 0;
        overflow: hidden;
        border-right: 1px solid var(--djk-border);
        background: var(--djk-black);
    }
    body.kasse-body.kasse-wisch-spalte .kasse-spalte-links {
        /* Je kleiner der Wert, desto stärker die Flucht. 900px dreht sichtbar räumlich, ohne
           dass die Schrift an der Kante auseinanderläuft. */
        perspective: 900px;
    }
    body.kasse-body.kasse-wisch-spalte .kasse-spalte-wuerfel {
        display: block;
        position: absolute;
        inset: 0;
        transform-style: preserve-3d;
        /* Erst um die halbe Würfeltiefe zurück, dann drehen — so bleibt die vordere Fläche
           genau in der Spalte stehen, statt beim Drehen auf den Betrachter zuzuwandern.
           Die Tiefe ist die halbe Spaltenbreite und wird von kasse.js gemessen; translateZ
           kennt keine Prozente, deshalb der Umweg über die Variable. */
        transform: translateZ(calc(-1 * var(--kasse-spalte-tiefe, 60px))) rotateY(var(--kasse-wuerfel-grad, 0deg));
        transition: transform 0.45s cubic-bezier(0.25, 0.8, 0.3, 1);
    }
    body.kasse-body.kasse-wisch-spalte.kasse-spalte-wg .kasse-spalte-wuerfel { --kasse-wuerfel-grad: 90deg; }
    /* Während der Finger dreht, folgt der Würfel sofort — eine Überblendung liefe hinterher. */
    body.kasse-body.kasse-wischt .kasse-spalte-wuerfel { transition: none; }

    body.kasse-body #kategorieOverlay {
        display: flex !important;
        flex-direction: column;
        position: absolute;
        inset: 0;
        /* Der Vollbild-Wert von .kategorie-overlay (90) darf hier NICHT gelten: seit die Spalte
           absolut liegt, würde sie damit über der Warenkorb-Leiste stehen und die aufgeklappte
           Artikelliste verdecken. */
        z-index: 1;
        min-height: 0;
        padding: 10px 6px 10px 10px;
        border-right: none;
        overflow-y: auto;
        overflow-x: hidden;
        overscroll-behavior: contain;
    }
    /* Vordere Würfelfläche. Ohne eingeschaltete Geste bleibt sie unverschoben — dann ist die
       Spalte einfach die Kategorienliste, wie eh und je. */
    body.kasse-body.kasse-wisch-spalte #kategorieOverlay {
        transform: translateZ(var(--kasse-spalte-tiefe, 60px));
        backface-visibility: hidden;
    }
    /* Linke Würfelfläche: erst die eigene Achse quer stellen, dann um dieselbe Tiefe nach
       außen — dadurch liegt sie an der linken Seite. Nur wenn die Geste eingeschaltet ist
       (Admin → Kasse → Ansicht), sonst bleibt hier alles wie vorher. */
    body.kasse-body.kasse-wisch-spalte #warengruppenRow:not(.mobile-open) {
        display: grid;
        grid-template-columns: 1fr;
        align-content: start;
        gap: 6px;
        position: absolute;
        inset: 0;
        z-index: 1;
        min-height: 0;
        padding: 10px 6px 10px 10px;
        /* Eigener Grund: sonst schimmern die Kategorien während des Wischens durch. */
        background: var(--djk-black);
        overflow-y: auto;
        /* Ausdrücklich: `overflow-y: auto` allein macht aus dem waagerechten `visible` ebenfalls
           ein `auto` — schon ein Pixel Überstand hätte dann eine Bildlaufleiste quer unter den
           Knöpfen. In einer Spalte, die nur nach unten scrollen soll, ist das nichts als Ballast. */
        overflow-x: hidden;
        overscroll-behavior: contain;
        transform: rotateY(-90deg) translateZ(var(--kasse-spalte-tiefe, 60px));
        backface-visibility: hidden;
    }
    /* Hintere Würfelfläche: das Menü (Verlauf, Abmelden). Noch eine Vierteldrehung weiter —
       dieselbe Rechnung wie bei den anderen beiden Flächen, nur um die Rückseite. */
    /* Nur die ABGEWANDTEN Flächen abschalten — und nur, wenn kasse.js gesagt hat, welche vorn
       steht (data-wuerfel). Bewusst so herum: eine Regel, die erst etwas WEGNIMMT, wenn sie
       sicher weiß wovon, kann bei einem JavaScript-Fehler nichts kaputt machen. Umgekehrt
       (alles aus, das vordere wieder an) wäre bei fehlendem data-wuerfel die ganze Spalte tot.
       Nötig ist es, weil die abgewandten Flächen nur durch backface-visibility unsichtbar sind
       und geometrisch weiter über derselben Stelle liegen — sie fingen sonst den Klick ab. */
    body.kasse-body.kasse-wisch-spalte[data-wuerfel="kategorien"] #warengruppenRow:not(.mobile-open),
    body.kasse-body.kasse-wisch-spalte[data-wuerfel="kategorien"] .kasse-menue-flaeche,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel="warengruppen"] #kategorieOverlay,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel="warengruppen"] .kasse-menue-flaeche,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel="menue"] #kategorieOverlay,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel="menue"] #warengruppenRow:not(.mobile-open) {
        pointer-events: none;
    }
    /*
     * IM RUHEZUSTAND GIBT ES GAR KEINEN WÜRFEL MEHR.
     *
     * Das ist keine Feinheit, sondern der Kern: Chrome steigt beim Treffertest nicht in eine
     * gedrehte Fläche innerhalb eines 3D-Kontextes hinunter. Gemessen mit
     * document.elementFromPoint() genau auf der Mitte eines Warengruppen-Knopfes: zurück kam
     * nicht der Knopf, sondern die Hülle .kasse-spalte-links. Der Knopf war sichtbar, seine
     * Maße stimmten, pointer-events stand auf auto — und trotzdem war er für Maus UND Finger
     * nicht vorhanden. Genau das ist der Fehler "die Knöpfe reagieren nicht".
     *
     * Deshalb: sobald sich nichts mehr dreht, fällt die Drehung weg (transform: none) und der
     * 3D-Kontext wird flach. Sichtbar ändert das nichts — in jeder Ruhelage ist die
     * Gesamtverschiebung ohnehin die Identität —, aber die vordere Fläche liegt dann wieder in
     * der normalen Ebene und nimmt Klicks an wie jedes andere Element.
     */
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe] .kasse-spalte-wuerfel {
        transform: none;
        transform-style: flat;
        /* OHNE ÜBERBLENDUNG. Sonst wird das Wegnehmen der Drehung selbst animiert: der Würfel
           dreht nach der fertigen Bewegung noch einmal aus 90° zurück nach 0°, und weil die
           Fläche gleichzeitig ihre Gegendrehung verliert, sieht man die Knöpfe zusammenklappen
           und wieder aufgehen. Gemessen: 450 ms Drehung fertig, ab 550 ms sprang der Knopf von
           133 px Breite auf 45 px und brauchte weitere 400 ms zurück. Beide Zustände sind
           visuell identisch — der Wechsel darf deshalb gar nichts zeigen. */
        transition: none;
    }
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe] #kategorieOverlay,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe] #warengruppenRow:not(.mobile-open),
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe] .kasse-menue-flaeche {
        transform: none;
        backface-visibility: visible;
    }

    /* Steht der Würfel still, sind dieselben Flächen ganz weg statt nur unklickbar — dann kann
       auch kein Browser sie beim Treffertest noch berücksichtigen. */
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe][data-wuerfel="kategorien"] #warengruppenRow:not(.mobile-open),
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe][data-wuerfel="kategorien"] .kasse-menue-flaeche,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe][data-wuerfel="warengruppen"] #kategorieOverlay,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe][data-wuerfel="warengruppen"] .kasse-menue-flaeche,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe][data-wuerfel="menue"] #kategorieOverlay,
    body.kasse-body.kasse-wisch-spalte[data-wuerfel-ruhe][data-wuerfel="menue"] #warengruppenRow:not(.mobile-open) {
        /* `!important`, weil die Grundregel der Kategorien-Spalte weiter oben selbst
           `display: flex !important` trägt (sie muss das `display: none` von .kategorie-overlay
           überstimmen). Ohne das hier blieb die abgewandte Kategorien-Fläche im Ruhezustand
           stehen und lag — voll deckend — unter dem Menü. Gemessen: bei data-wuerfel="menue"
           standen katOverlay UND menue gleichzeitig auf display:flex. */
        display: none !important;
    }

    /* source/style_css/225_category_long_press_sheet_continued.css - style.css: category long press sheet continued, part 31 of 78 (built by werkzeuge/parts_build.php) */
    body.kasse-body.kasse-wisch-spalte .kasse-menue-flaeche {
        display: flex;
        flex-direction: column;
        gap: 6px;
        position: absolute;
        inset: 0;
        z-index: 1;
        min-height: 0;
        padding: 10px 6px 10px 10px;
        background: var(--djk-black);
        overflow-y: auto;
        overflow-x: hidden;
        overscroll-behavior: contain;
        transform: rotateY(180deg) translateZ(var(--kasse-spalte-tiefe, 60px));
        backface-visibility: hidden;
    }
    /* Ein Menüpunkt sieht aus wie die Kacheln daneben — dieselbe Spalte, dieselbe Griffigkeit. */
    .kasse-menue-knopf {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 6px;
        flex: 0 0 auto;
        background: var(--djk-black-card);
        border: 1px solid var(--djk-border);
        border-radius: 5px;
        padding: 16px 8px;
        color: inherit;
        font: inherit;
        font-size: 0.76rem;
        font-weight: 700;
        text-align: center;
        text-decoration: none;
        cursor: pointer;
    }
    .kasse-menue-knopf .icon { width: 22px; height: 22px; }
    .kasse-menue-abmelden { color: var(--djk-danger); border-color: var(--djk-danger); }
    /* Wo die Fläche erreichbar ist, ist der Uhr-Knopf oben doppelt gemoppelt. */
    body.kasse-body.kasse-wisch-spalte #verlaufBtn { display: none !important; }
    /* Knöpfe wie die Kategorien daneben: gleiche Höhe, gleiche Schrift, gleicher Abstand —
       beim Wischen soll sich nur der Inhalt ändern, nicht das Maß. `min-width: 0` hält einen
       langen Warengruppen-Namen davon ab, die Spalte breiter zu machen als sie ist. */
    body.kasse-body.kasse-wisch-spalte #warengruppenRow:not(.mobile-open) .warengruppe-chip {
        padding: 14px 8px;
        font-size: var(--kasse-schrift-warengruppe-groesse, 0.78rem);
        min-width: 0;
        overflow-wrap: anywhere;
    }
    /* KEINE Überschrift und kein Schließen-Kreuz in der Spalte. Beide brachten nichts, was die
       Knöpfe nicht selbst sagen — und die Überschrift war breiter als die schmale Spalte, was
       ihr eine waagerechte Bildlaufleiste eingebracht hat. (Auf der Vollbild-Seite
       #warengruppenRow.mobile-open bleibt der Kopf, dort ist Platz und das Kreuz nötig.) */
    body.kasse-body.kasse-wisch-spalte #warengruppenRow:not(.mobile-open) .warengruppen-row-header {
        display: none;
    }
    /* Wo gewischt wird, ist der Knopf "Warengruppe" unten überflüssig — er führte auf eine
       Vollbild-Seite mit genau denselben Knöpfen. `!important`, weil kasse.js seine Sichtbarkeit
       am Element selbst schaltet (Inline-Stil schlägt sonst jede Regel). */
    body.kasse-body.kasse-wisch-spalte #kategorienBtn { display: none !important; }
    body.kasse-body #kategorieOverlay .kategorie-overlay-header { display: none; }
    body.kasse-body #kategorieOverlay .kategorie-overlay-grid {
        display: flex;
        flex-direction: column;
        gap: 6px;
    }
    body.kasse-body #kategorieOverlay .kategorie-tile {
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 10px;
        text-align: left;
    }
    /* HIER ist die Kachel eine REIHE (Foto links, Name rechts) — also ist `justify-content`
       die WAAGERECHTE und `align-items` die senkrechte Achse, genau umgekehrt zur Spalte auf
       dem grossen Bildschirm.

       Die Regel darueber traegt eine `id` im Waehler und schlaegt damit jede Regel, die nur
       Klassen nennt — egal wie spaet sie steht. Deshalb steht die Einstellung hier gleich
       daneben und nicht nur weiter unten; im ersten Entwurf kam die Hoehe an und die Lage
       nicht, und man sah dem Bildschirm nicht an, warum. */
    body.kasse-body #kategorieOverlay .kategorie-tile:not(.tisch-tile) {
        justify-content: var(--kasse-text-kategorie-waagerecht, center);
        align-items: var(--kasse-text-kategorie-senkrecht, center);
    }
    body.kasse-body #kategorieOverlay .kategorie-tile:not(.tisch-tile) .product-tile-name {
        text-align: var(--kasse-text-kategorie-aus, center);
    }
    body.kasse-body #kategorieOverlay .kategorie-tile .product-tile-photo {
        width: 34px;
        height: 34px;
        flex: 0 0 auto;
        aspect-ratio: 1;
    }
    body.kasse-body #kategorieOverlay .kategorie-tile .product-tile-name {
        text-align: left;
        padding: 8px 4px;
        font-size: var(--kasse-schrift-kategorie-groesse, 0.72rem);
    }

    body.kasse-body #kasseProductsSection {
        grid-column: 2;
        grid-row: 2;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        /* Eng am Rand: auf dem Handy zählt jeder Millimeter für die Kacheln — aber der
           RECHTE Rand ist der Rand des Bildschirms und muss so breit sein wie der linke
           (02.09.2026, Bilder 3 und 4 des Wirts). Gemessen: links beginnt die Kategorie-
           Kachel bei 10, rechts endete die Produktkachel bei 355 — 5 statt 10, und die Seite
           stand schief. Innen bleiben die 5: der Abstand zur Trennlinie gehoert zum Raster,
           nicht zum Bildschirmrand. */
        padding: 10px 10px 16px 5px;
    }
    body.kasse-body #kasseProductsSection .container-wide { max-width: none; margin: 0; padding: 0; }
    /* Feste Spaltenzahl aus Admin → Kasse. Auf dem Handy ist das genau richtig: dort ist die
       Produktspalte so schmal, dass die Anzahl über die Kachelgröße entscheidet.
       (Ab Tablet-Breite gilt die elastische Regel weiter unten — siehe dort.) */
    body.kasse-body #kasseProductsSection .product-grid {
        grid-template-columns: repeat(var(--kasse-mobil-produkt-spalten, 2), 1fr);
        /* Der Abstand zwischen den Kacheln — einstellbar (Kasse → Ansicht). Enger heisst: mehr
           Kacheln auf einen Blick; weiter heisst: weniger Vertipper. Beides ist eine Frage des
           Hauses, nicht des Programms. */
        gap: var(--kasse-kachel-abstand, 6px);
    }
    /* Produkt-Kacheln in derselben kompakten Machart wie die Kategorien links: kleinere
       Schrift, engeres Innenmaß — auf der schmalen rechten Spalte passen so zwei Spalten
       nebeneinander, ohne dass Namen abgeschnitten werden. */
    /* Die vier Werte hat der Wirt selbst in den Entwicklerwerkzeugen eingestellt und
       eingekringelt: oben und unten 13px, RECHTS 41px fuer den Zaehler und die rote Marke,
       links nur 2px — dort steht nichts, und jeder Millimeter mehr schnuert den Namen ein. */
    body.kasse-body #kasseProductsSection .product-tile { padding: 13px 41px 13px 2px; }
    body.kasse-body #kasseProductsSection .product-tile-name {
        /* Die eingestellte Groesse gewinnt; 0.72rem bleibt der Wert ohne Einstellung.
           Vorher stand hier eine feste Zahl, und weil dieser Selektor mit seiner ID viel
           schwerer wiegt als `.product-tile-name`, aenderte sich auf dem Handy die Schrift,
           aber nie die Groesse. */
        font-size: var(--kasse-schrift-produkt-groesse, 0.72rem);
        padding: 8px 4px 2px;
    }
    body.kasse-body #kasseProductsSection .product-tile-price {
        font-size: var(--kasse-schrift-preis-groesse, 0.72rem);
        padding: 0 4px 8px;
    }
}

/* source/style_css/230_tablet_layout_category_owner.css - style.css part 32 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* Tablet und schmaler Laptop (768–1199px): hier NICHT die feste Spaltenzahl vom Handy.
   Sie gilt bis 1199px und zog bei zwei eingestellten Spalten jede Kachel über die halbe
   Bildschirmbreite — Name und Preis standen dann verloren in einer riesigen Fläche.
   Stattdessen behalten die Kacheln ihr Maß und das Raster legt eine Spalte nach, sobald
   Platz für eine weitere ist. `1fr` lässt sie den Rest untereinander aufteilen: etwas
   nachgiebig, aber nie mehr als bis knapp unter die doppelte Mindestbreite.
   Dieselbe Bauart wie auf dem großen Kassenbildschirm, damit die Kacheln überall gleich
   groß wirken. */
@media (min-width: 768px) and (max-width: 1199px) {
    body.kasse-body #kasseProductsSection .product-grid {
        grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--kasse-tablet-produkt-min, 130px)), 1fr));
    }

    /* Die Kategorien-Spalte hatte dasselbe Problem wie die Kacheln: ein fester Prozentsatz
       (Vorgabe 38 %) gilt bis 1199px und macht aus einer schmalen Textliste auf einem breiten
       Bildschirm einen 450px-Balken — Platz, der den Produkten fehlt.
       clamp() gibt ihr eine Untergrenze, einen mitwachsenden Wunschwert und eine Obergrenze:
       sie bleibt lesbar, wächst mit dem Bildschirm mit, läuft aber nicht davon.
       Der Prozentsatz aus Admin → Kasse gilt weiter fürs Handy — dort, wofür er gedacht ist. */
    body.kasse-body {
        grid-template-columns:
            clamp(var(--kasse-tablet-kat-min, 190px), var(--kasse-tablet-kat-soll, 22%), var(--kasse-tablet-kat-max, 300px))
            1fr;
    }
}

/* Mobil/Tablet: Warengruppen-Auswahl als eigene Vollbild-Seite, geöffnet über #kategorienBtn
   ("Warengruppe", siehe .kasse-bottom-actions) — auf dem Desktop ist das dagegen eine dauerhafte
   Spalte (siehe @media min-width:1200px oben). */
@media (max-width: 1199px) {
    /* Zwei Knöpfe nebeneinander — wie in der Warengruppen-Spalte auf dem großen Bildschirm. */
    #warengruppenRow.mobile-open {
        display: grid;
        grid-template-columns: 1fr 1fr;
        align-content: start;
        gap: 10px;
        position: fixed;
        inset: 0;
        z-index: 95;
        background: var(--djk-black);
        padding: calc(16px + env(safe-area-inset-top, 0px)) 14px calc(16px + env(safe-area-inset-bottom, 0px));
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    /* Überschrift + Schließen-Knopf über die volle Breite, nicht als Rasterspalte. */
    #warengruppenRow.mobile-open .warengruppen-row-header {
        display: flex;
        grid-column: 1 / -1;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 4px;
    }
    #warengruppenRow.mobile-open .warengruppen-row-header h3 { margin: 0; }
}

/* Table picker tiles */
.tisch-tile .product-tile-photo { aspect-ratio: 1.6; }
.tisch-tile .product-tile-photo .icon { width: 30px; height: 30px; }
/* Suchtreffer aus dem Einstellungs-Verzeichnis: sitzen unter den gefilterten Menüpunkten und
   sind als Fundstelle erkennbar, nicht als weiterer Menüpunkt — deshalb eingerückt und ohne
   Symbol, mit einer Linie darüber als Grenze zum Menü. */
.admin-such-treffer { border-top: 1px solid var(--djk-sidebar-border); padding-top: 8px; margin-top: 8px; }
.admin-such-treffer-link { padding-left: 26px; font-size: 0.85rem; }
.admin-such-treffer-link span { color: var(--djk-sidebar-text); }

/* "Was fehlt noch?": Die Stufe steckt im farbigen Balken links und im Symbol, nicht nur im
   Text — beim Überfliegen soll auffallen, was blockiert, ohne dass man liest. */
.check-liste { display: flex; flex-direction: column; gap: 8px; margin-bottom: 22px; }
.check-zeile {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 4px 13px;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-left: 4px solid var(--djk-border);
    border-radius: 8px;
    padding: 13px 16px;
}
.check-blockiert { border-left-color: var(--djk-danger); }
.check-hinweis { border-left-color: var(--djk-copper); }
.check-ok { border-left-color: var(--djk-success); }
.check-marke { display: flex; align-items: center; }
.check-marke .icon { width: 19px; height: 19px; }
.check-blockiert .check-marke { color: var(--djk-danger); }
.check-hinweis .check-marke { color: var(--djk-copper); }
.check-ok .check-marke { color: var(--djk-success); }
.check-titel { font-weight: 700; font-size: 0.92rem; line-height: 1.35; }
.check-text { color: var(--djk-gray); font-size: 0.83rem; line-height: 1.5; margin-top: 2px; }
.check-knopf { flex: none; white-space: nowrap; }
/* Erledigtes tritt zurück: es ist da, damit man sieht, dass geprüft wurde — mehr nicht. */
.check-ok .check-titel { font-weight: 600; color: var(--djk-gray); }

.check-bilanz {
    font-size: 0.8rem;
    font-weight: 800;
    padding: 5px 13px;
    border-radius: 999px;
    white-space: nowrap;
}
.check-bilanz-gut { background: rgba(16, 185, 129, .16); color: #0f7a5a; }
.check-bilanz-offen { background: rgba(239, 68, 68, .14); color: var(--djk-danger); }

@media (max-width: 640px) {
    .check-zeile { grid-template-columns: auto minmax(0, 1fr); }
    .check-knopf { grid-column: 2; justify-self: start; margin-top: 6px; }
}

/* Push-Arten: Schalter links, Empfängerzahl rechts, Erklärung darunter über die volle Breite.
   Die Zahl steht bewusst auf derselben Zeile wie der Schalter — sie beantwortet die Frage,
   die man beim Umlegen stellt: "kommt das überhaupt bei jemandem an?" */
.push-art-zeile {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 2px 12px;
    padding: 11px 0;
    border-bottom: 1px solid var(--djk-border);
}
.push-art-zeile:last-of-type { border-bottom: 0; }
.push-art-empfaenger {
    align-self: center;
    white-space: nowrap;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--djk-gray);
}
.push-art-leer { color: var(--djk-danger); }
.push-art-hinweis { grid-column: 1 / -1; margin: 2px 0 0; }

/* Sammelaktion "Farben aller Kategorien": Schalter links, Farbfeld rechts am Rand, damit
   beide Zeilen dieselbe Kante haben und man die zwei Farben direkt übereinander vergleicht. */
.kat-farben-zeile {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 0;
    max-width: 420px;
}
/* Der Farbvorschlag: jedes Muster traegt die Farbe, die es vorschlaegt, und die Schrift, die
   dazu gerechnet wurde. Wer den Vorschlag liest, sieht ihn damit schon. (23.08.2026) */
.kat-farben-vorschau {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.kat-farben-probe {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 128px;
    padding: 8px 12px;
    border-radius: 10px;
    font-weight: 700;
    font-size: 0.85rem;
}
.kat-farben-probe small {
    font-size: 0.68rem;
    font-weight: 600;
    opacity: 0.75;
}
.kat-farben-zeile input[type="color"] {
    flex: none;
    width: 52px;
    height: 34px;
    padding: 2px;
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    background: var(--feld-grund);
    cursor: pointer;
}

/* ------------------------------------------------------------------------------------------
   EINE ZEILE IN DEN EINSTELLUNGS-KARTEN — Beschriftung links, Bedienelemente rechts.

   Als RASTER und nicht als `space-between`-Flex: bei Flex bestimmt jede Auswahlliste ihre
   Breite selbst („Breit" ist kürzer als „Wie die App"), und dann steht in jeder Zeile das
   Größenfeld woanders — genau das war auf dem Handy zu sehen, wo die Felder zusätzlich rechts
   aus dem Bild liefen. Mit festen Spalten fluchten alle Zeilen und alle Karten.
   ------------------------------------------------------------------------------------------ */
.einstell-zeile {
    display: grid;
    grid-template-columns: minmax(90px, 1fr) minmax(0, 200px) 86px;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}
.einstell-zeile > * { min-width: 0; }
.einstell-zeile select,
.einstell-zeile input[type="text"] { width: 100%; }
.einstell-zeile input[type="text"] { text-align: center; }
/* Farbzeilen haben statt Auswahl + Größe zwei Farbfelder. Sie belegen dieselben zwei Spalten,
   damit ihre rechte Kante mit der der Schriftzeilen fluchtet. */
.einstell-zeile .farb-paar {
    grid-column: 2 / -1;
    display: flex;
    gap: 8px;
    align-items: center;
    justify-content: flex-end;
}
.einstell-zeile .farb-paar input[type="color"] {
    flex: none;
    width: 52px;
    height: 34px;
    padding: 2px;
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    background: var(--feld-grund);
    cursor: pointer;
}
/* Schmaler Bildschirm: die Beschriftung nimmt eine eigene Zeile, sonst bleibt für die
   Auswahlliste nichts übrig. */
@media (max-width: 560px) {
    .einstell-zeile { grid-template-columns: minmax(0, 1fr) 86px; }
    .einstell-zeile > :first-child { grid-column: 1 / -1; }
    .einstell-zeile .farb-paar { grid-column: 1 / -1; justify-content: flex-start; }
}

/* Die Vorschau-Kacheln darunter — gleich breit, damit sie eine Reihe bilden und nicht
   treppenförmig stehen. */
.kachel-vorschau {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 14px 0 12px;
}
.kachel-vorschau-stueck {
    width: 150px;
    border: 1px solid var(--djk-border);
    border-radius: 2px;
    overflow: hidden;
}

/* --- Die Kategorie als Herrin ihrer Produkte -------------------------------------------------
   Ein Produkt darf von seiner Kategorie abweichen — es soll das nur nicht heimlich tun.
   Deshalb überall dieselbe Marke: kupferfarben, klein, anklickbar. */
/* Ohne `margin-top` und ohne `nowrap`: in der Zeilenliste steht die Marke neben den übrigen
   Angaben, nicht darunter — der Abstand nach oben schob sie dort aus der Mitte. Umbrechen darf
   sie, wenn es eng wird; „13 Produkte weichen ab" ist eine Aussage, kein Etikett. */
.kat-abweichung-marke {
    display: inline-block;
    padding: 5px 10px;
    border-radius: 5px;
    background: rgba(245, 158, 11, 0.16);
    color: var(--djk-copper);
    font-size: 0.62rem;
    font-weight: 700;
    text-decoration: none;
}
.kat-abweichung-marke:hover { background: rgba(245, 158, 11, 0.28); }
/* Auf der Produktkachel ist die Marke kein Link, sondern nur ein Hinweis — dort öffnet der
   Klick auf die Kachel ohnehin schon die Bearbeitung. */
span.kat-abweichung-marke { cursor: help; }

.kat-vererbung {
    margin: 0 0 16px;
    padding: 12px 14px;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    background: var(--djk-black-soft);
}
.kat-vererbung-liste { list-style: none; margin: 0 0 10px; padding: 0; }
.kat-vererbung-liste li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 0;
    border-bottom: 1px solid var(--djk-border);
    font-size: 0.78rem;
}
.kat-vererbung-liste li:last-child { border-bottom: 0; }
.kat-vererbung-titel { flex: 1 1 auto; min-width: 0; color: var(--djk-gray); }
.kat-vererbung-wert { font-weight: 700; text-align: right; }
.kat-vererbung-ok { flex: none; width: 96px; text-align: right; font-size: 0.62rem; color: var(--djk-gray); }
.kat-vererbung-liste .kat-abweichung-marke { flex: none; width: 96px; margin-top: 0; text-align: center; }

/* Die Abgleich-Liste: je Produkt eine Karte, darin je abweichendem Feld eine Zeile mit
   "so sagt es die Kategorie → so sagt es das Produkt". Das Häkchen bedeutet immer dasselbe:
   dieses Feld wieder der Kategorie folgen lassen. */
.abgleich-karte {
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    background: var(--djk-black-card);
    padding: 10px 12px;
    margin-bottom: 10px;
}
.abgleich-kopf {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
}
.abgleich-name { font-weight: 700; font-size: 0.9rem; }
.abgleich-nummer { color: var(--djk-gray); font-size: 0.7rem; font-weight: 600; }
.abgleich-feld {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 0;
    font-size: 0.78rem;
    cursor: pointer;
}
.abgleich-feld input[type="checkbox"] { flex: none; width: 18px; height: 18px; cursor: pointer; }
.abgleich-feld-titel { flex: 0 0 132px; color: var(--djk-gray); }
.abgleich-feld-wert { flex: 1 1 auto; min-width: 0; }
.abgleich-von { color: var(--djk-gray); }
.abgleich-nach { font-weight: 700; color: var(--djk-copper); }
.abgleich-heikel { color: var(--djk-danger); font-size: 0.66rem; font-weight: 700; }
/* Die drei Wege bleiben beim Blättern stehen. Bei dreizehn abweichenden Produkten ist das Ende
   der Liste 1700 px tief — wer entscheiden soll, darf die Knöpfe dafür nicht erst suchen müssen.
   Gescrollt wird die Hülle (.modal-overlay), nicht das Kästchen; `sticky` klebt deshalb
   innerhalb des Kästchens und verschwindet mit ihm, sobald es durch ist. */
.abgleich-aktionen {
    position: sticky;
    bottom: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 14px;
    padding: 12px 0;
    border-top: 1px solid var(--djk-border);
    background: var(--djk-black-card);
}
/* Das Schließkreuz des Abgleichs ist ein Link (die Liste hängt an ?abgleich= in der Adresse),
   die Grundregel .modal-close ist auf einen <button> gemünzt. */
a.modal-close { text-decoration: none; line-height: 1; }

/* source/style_css/240_bulk_change_table_plan_editor.css - style.css part 33 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Massenänderung im Produktraster -------------------------------------------------------
   Die Leiste ist zu, bis man sie braucht: über jeder Produktliste dauerhaft ein Werkzeugkasten
   wäre neunmal von zehn nur im Weg. */
.massen-leiste {
    margin: 0 0 16px;
    padding: 12px 14px;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    background: var(--djk-black-soft);
}
.massen-leiste[hidden] { display: none; }
.massen-kopf {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}
.massen-zahl { font-weight: 800; font-size: 0.85rem; }
.massen-hinweis { color: var(--djk-gray); font-size: 0.7rem; }
.massen-zeile {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}
/* Schmale Zeile, sonst wie jedes andere Feld — genau wie die Auswahlliste darunter. Bis zum
   10.08.2026 stand hier ein eigener Rand (`--djk-border`, viel heller als `--feld-rand`) und
   ein eigener Radius; das Textfeld sah daneben aus wie ein anderes Bedienelement. */
.massen-zeile input[type="text"] {
    padding: 7px 10px;
    font-size: 0.8rem;
}
.massen-zeile select {
    padding: 7px 28px 7px 10px;
    background-position: right 8px center;
    font-size: 0.8rem;
}
.massen-zeile input[type="color"] {
    width: 44px;
    height: 32px;
    padding: 2px;
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    background-color: var(--feld-grund);
    cursor: pointer;
}
.massen-teil {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}
/* Falle 2: die Regel darüber setzt display:flex und schlüge sonst das [hidden] des Browsers. */
.massen-teil[hidden] { display: none; }
.massen-teil label { display: flex; align-items: center; gap: 5px; font-size: 0.78rem; }
.massen-teil .hint { font-size: 0.68rem; }

/* Das Auswahlkästchen sitzt in der Ecke der Kachel und ist nur im Massen-Modus da.
   Falle 8: `position:absolute` braucht einen Bezugspunkt, und `.admin-produkt-card` hat von
   Haus aus keinen. Der wird deshalb hier gesetzt — aber NUR im Massen-Modus, damit sich am
   normalen Raster nichts ändert. (Das einzige weitere absolute Kind ist das unsichtbare
   `input` der Tagesschalter, opacity 0 und pointer-events none — es verschiebt nichts.) */
.massen-kasten { display: none; position: absolute; top: 6px; left: 6px; z-index: 3; }
body.massen-modus .admin-produkt-card { position: relative; }
body.massen-modus .massen-kasten { display: block; }
.massen-kasten input { width: 20px; height: 20px; cursor: pointer; }
body.massen-modus .admin-produkt-card { cursor: pointer; }
body.massen-modus .admin-produkt-card.massen-gewaehlt {
    outline: 2px solid var(--djk-yellow);
    outline-offset: -2px;
}

/* Vorschau "war → wird" */
.massen-vorschau-zeile {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 0;
    border-bottom: 1px solid var(--djk-border);
    font-size: 0.8rem;
}
.massen-vorschau-zeile:last-child { border-bottom: 0; }
.massen-vorschau-name { flex: 1 1 auto; min-width: 0; font-weight: 700; }
.massen-vorschau-name .hint { display: block; font-weight: 500; }
.massen-vorschau-werte { flex: 0 1 auto; text-align: right; }
.massen-aenderung { display: block; }
.massen-aenderung .hint { margin-right: 6px; }
.massen-gleich { opacity: 0.55; }
.massen-fehler-text { color: var(--djk-danger); font-weight: 700; }
.massen-fehler { background: rgba(239, 68, 68, 0.08); }

/* Die drei Chips "Wie Kategorie · Ja · Nein" im Produktformular. Der geerbte Wert steht blass
   in Klammern am ersten Chip — "wie Kategorie" soll nicht heißen "keine Ahnung wie". */
.erbt-chips { margin-top: 2px; }
.erbt-kat-wert { opacity: 0.65; font-weight: 600; }
/* Falle 2: eine Anzeige-Regel des Autors schlüge [hidden] des Browsers. Hier gibt es zwar
   keine, aber die Chips wandern erfahrungsgemäß — deshalb ausgeschrieben. */
.erbt-kat-wert[hidden] { display: none; }

.tisch-tile-kat { display: block; color: var(--djk-gray); font-weight: 500; font-size: 0.68rem; }
/*
 * „an 104" — dieser Tisch steht zusammengerueckt an einem anderen (12.09.2026).
 *
 * Auf dem Grundriss sieht man es: die Tafel steht da. Ohne Grundriss gibt es nur Kacheln, und
 * dort muss es DASTEHEN — sonst traegt der Kellner das Essen an die alte Stelle.
 *
 * Deshalb kein blasser Zusatz, sondern ein Schildchen: es faellt auf, ohne die Nummer zu
 * verdraengen, und es steht in allen drei Zustandsfarben lesbar (dunkel auf hell).
 */
.tisch-tile-tafel {
    display: inline-block;
    margin-top: 3px;
    padding: 1px 7px;
    border-radius: 999px;
    background: rgba(15, 23, 42, .82);
    color: #f5f2ea;
    font-weight: 600;
    font-size: 0.66rem;
    line-height: 1.5;
}

/* Fußzeile der Tisch-Kachel: links wie lange besetzt, rechts der bisher offene Betrag.
   Klein gehalten, damit die Tischnummer die Kachel weiter beherrscht. Beide Angaben dürfen
   nicht umbrechen und nicht überlaufen — deshalb `min-width: 0` plus Ellipse: lieber ein
   abgeschnittener Betrag als eine zerrissene Kachel. */
.tisch-tile-fuss {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
    padding: 3px 6px 1px;
    font-size: 0.66rem;
    line-height: 1.2;
}
.tisch-tile-dauer,
.tisch-tile-summe {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--djk-gray);
}
.tisch-tile-summe { font-weight: 800; }
/* Auf den farbigen Zuständen (rot/grün) wäre Grau nicht lesbar. */
.tisch-tile.tisch-wartet .tisch-tile-dauer,
.tisch-tile.tisch-wartet .tisch-tile-summe,
.tisch-tile.tisch-bereit .tisch-tile-dauer,
.tisch-tile.tisch-bereit .tisch-tile-summe { color: #ffffffe6; }
.tisch-tile-reservation-badge {
    position: absolute;
    top: 5px;
    right: 5px;
    display: flex;
    align-items: center;
    gap: 3px;
    padding: 2px 6px 2px 4px;
    border-radius: 999px;
    background: var(--djk-yellow);
    color: var(--djk-black);
    font-size: 0.66rem;
    font-weight: 800;
    z-index: 2;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}
.tisch-tile-reservation-badge .icon { width: 13px; height: 13px; }
/* DIESELBE BEDEUTUNG WIE IM GRUNDRISS (10.09.2026). Wo eine Tischgruppe keinen Plan hat,
   zeichnet `renderTischTiles()` Kacheln — die blieben blau, waehrend der Grundriss grau
   wurde. Ein Betrieb ohne Plan haette die alte Bedeutung gesehen, einer mit Plan die neue. */
.tisch-tile.tisch-frei { border-color: #6b768399; background: linear-gradient(150deg, #6b768340, var(--djk-black-card) 65%); }
/* Das Zeichen folgt der Kachel: sie ist seit dem 10.09.2026 grau, nicht mehr blau. */
.tisch-tile.tisch-frei .product-tile-photo .icon { color: #b6bec7; }
/* Dieselbe Wahl auf der Kachel (13.09.2026) — ein Haus ohne Plan soll sie genauso sehen. */
[data-tisch-frei="kontur"] .tisch-tile.tisch-frei { border-color: #9aa4af; background: transparent; }
[data-tisch-frei="hell"] .tisch-tile.tisch-frei { border-color: #c3cbd3; background: linear-gradient(150deg, #eef1f4 0%, #d3d9df 100%); }
[data-tisch-frei="hell"] .tisch-tile.tisch-frei :is(.product-tile-photo .icon, .product-tile-name, .tisch-tile-kat) { color: #1f2328; }
[data-tisch-frei="gruen"] .tisch-tile.tisch-frei { border-color: #4fae78; background: linear-gradient(150deg, #2e7d4f 0%, #1f5c39 100%); }
[data-tisch-frei="gruen"] .tisch-tile.tisch-frei :is(.product-tile-photo .icon, .product-tile-name, .tisch-tile-kat) { color: #fff; }
[data-tisch-frei="eigen"] .tisch-tile.tisch-frei { border-color: var(--tf-rand, #838d9b); background: var(--tf-kachel, transparent); }
[data-tisch-frei="eigen"] .tisch-tile.tisch-frei :is(.product-tile-photo .icon, .product-tile-name, .tisch-tile-kat) { color: var(--tf-kachel-schrift, inherit); }
.tisch-tile.tisch-wartet { border-color: #f5c65c; background: linear-gradient(150deg, #e0a52e 0%, #b8821c 100%); }
.tisch-tile.tisch-wartet .product-tile-photo .icon,
.tisch-tile.tisch-wartet .product-tile-name,
.tisch-tile.tisch-wartet .tisch-tile-kat { color: #1f2328; }
.tisch-tile.tisch-bereit { border-color: #62c0e0; background: linear-gradient(150deg, #2f9fc9 0%, #1f7594 100%); }
.tisch-tile.tisch-bereit .product-tile-photo .icon,
.tisch-tile.tisch-bereit .product-tile-name,
.tisch-tile.tisch-bereit .tisch-tile-kat { color: #fff; }

/* --- Admin: Tischplan-Editor (assets/js/tischplan.js) --- */
.tischplan-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.tischplan-toolbar .btn.active { background: var(--djk-yellow); color: var(--djk-black); border-color: var(--djk-yellow); }
.tischplan-body {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    flex-wrap: wrap;
}
.tischplan-canvas-wrap {
    flex: 1 1 480px;
    min-width: 280px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    overflow: hidden;
}
.tischplan-svg { display: block; width: 100%; height: auto; touch-action: none; margin: 0 auto; }
.tischplan-canvas-wrap.tp-preview-tablet { max-width: 700px; margin: 0 auto; }
/* Handy-Vorschau ohne eigenes Mobil-Layout: nur die Breite auf Handy-Maß setzen, Höhe bleibt
   auto (wie in der echten Kasse) — sonst würde das breite Standard-viewBox in eine feste
   Hochkant-Box gequetscht und oben/unten bliebe leerer Rand (genau der gemeldete Bug). Erst
   wenn wirklich das eigene Mobil-Layout bearbeitet wird (tp-editing-mobil, siehe tischplan.js
   editingMobil), hat das viewBox selbst Hochkant-Maße (CANVAS_MOBIL) und die Box darf fest
   375x812 sein, weil dann Koordinaten und Box zueinander passen. */
.tischplan-canvas-wrap.tp-preview-mobile { flex: 0 0 auto; width: 375px; max-width: 100%; min-width: 0; margin: 0 auto; }
.tischplan-canvas-wrap.tp-preview-mobile.tp-editing-mobil { height: 812px; }
.tischplan-canvas-wrap.tp-preview-mobile.tp-editing-mobil .tischplan-svg { width: 100%; height: 100%; }
.tp-preview-btn.active { background: var(--djk-yellow); color: var(--djk-black); border-color: var(--djk-yellow); }
.tischplan-preview-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.tischplan-props {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    padding: 8px 12px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
}
.tischplan-props-field { display: flex; align-items: center; gap: 8px; font-size: 0.8rem; color: var(--djk-gray); }
.tischplan-props-field input[type="color"] { width: 34px; height: 28px; padding: 0; border: 1px solid var(--djk-border); border-radius: 6px; background: none; cursor: pointer; }
.tp-grid-dot { fill: var(--djk-gray); opacity: 0.35; }
/*
 * DIE STUEHLE (10.09.2026) — eine Regel fuer alle drei Plaene.
 *
 * Sie werden in `assets/js/tisch_stuehle.js` aus `tische.plaetze` gezeichnet und tragen ueberall
 * dieselbe Klasse. Ein Stuhl ist KEIN Bedienelement: er wird nie angeklickt, nie gefaerbt nach
 * Zustand, nie beschriftet. Er sagt nur, wie viele Menschen an diesen Tisch passen.
 *
 * Darum grau und ohne eigene Farbe — der Zustand gehoert der Tischflaeche. Faerbte man die
 * Stuehle mit, waere ein besetzter Sechsertisch ein roter Fleck, an dem man die Zahl nicht mehr
 * abzaehlen kann.
 *
 * `pointer-events: none`, damit ein Griff daneben trotzdem den Tisch trifft — im Editor zieht
 * man am Tisch, nicht an seinen Stuehlen.
 */
.tisch-stuhl {
    fill: var(--tisch-stuhl);
    stroke: var(--tisch-stuhl-rand);
    stroke-width: 1;
    pointer-events: none;
}
.tp-tisch-shape { fill: #2f7cc966; stroke: #2f7cc9; stroke-width: 2; cursor: grab; }
.tp-tisch.tp-selected .tp-tisch-shape { fill: #f2c14e66; stroke: var(--djk-yellow); stroke-width: 3; }
.tp-tisch-label { fill: var(--djk-white); font-size: 26px; font-weight: 700; text-anchor: middle; dominant-baseline: middle; pointer-events: none; user-select: none; }
.tp-tisch-sublabel { fill: var(--djk-gray); font-size: 15px; text-anchor: middle; dominant-baseline: middle; pointer-events: none; user-select: none; }
.tp-resize-handle { fill: var(--djk-yellow); opacity: 0; cursor: nwse-resize; }
.tp-tisch.tp-selected .tp-resize-handle { opacity: 1; }

/* Wand/Fenster/Tür: gemeinsame Basislinie (Farbe/Dicke frei wählbar) + typspezifischer Zusatzstil */
.tp-el { cursor: pointer; }
.tp-el-base { stroke-linecap: round; }
.tp-el-hit { stroke: transparent; fill: none; }
.tp-el.tp-selected .tp-el-base { filter: drop-shadow(0 0 3px var(--djk-yellow)); }
.tp-el-fenster-glas { stroke: #ffffffcc; stroke-linecap: round; }
.tp-el-tuer-fluegel { stroke-dasharray: none; }
.tp-el-tuer-bogen { fill: none; stroke-width: 2; stroke-dasharray: 4 4; opacity: 0.7; }
.tp-el-preview { opacity: 0.6; stroke-dasharray: 8 6; }
.tp-el-handle { fill: var(--djk-yellow); stroke: var(--djk-black); stroke-width: 1.5; cursor: move; }

.tp-text-label { font-size: 28px; text-anchor: middle; dominant-baseline: middle; cursor: move; user-select: none; }
.tp-text-hit { fill: transparent; cursor: move; }
.tp-text.tp-selected .tp-text-label { filter: drop-shadow(0 0 3px var(--djk-yellow)); }
.tp-text-rotate-arm { stroke: var(--djk-yellow); stroke-width: 1.5; stroke-dasharray: 3 3; }
.tp-text-rotate-handle { fill: var(--djk-yellow); stroke: var(--djk-black); stroke-width: 1.5; cursor: grab; }

.tischplan-sidebar { flex: 0 0 220px; min-width: 200px; }
.tischplan-sidebar h4 { margin: 0 0 8px; font-size: 0.85rem; color: var(--djk-gray); }
.tischplan-unplaced { display: flex; flex-direction: column; gap: 6px; }
.tischplan-chip {
    text-align: left;
    padding: 8px 12px;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    color: var(--djk-white);
    font-size: 0.85rem;
    cursor: pointer;
}
.tischplan-chip:hover { border-color: var(--djk-yellow); }

/* source/style_css/250_table_plan_view.css - style.css part 34 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Kasse: read-only Tischplan-Ansicht (assets/js/kasse.js renderTischPlanSvg) --- */
/*
 * ═══ DER RAUM HAT SEINEN EIGENEN BODEN (10.09.2026) ═══
 *
 * Auf dem Bild des Wirts liegt der Grundriss auf einem dunklen Boden mit heller Wand — wie
 * ein Grundriss auf Papier, nicht wie ein Teil der Seite.
 *
 * Das ist mehr als Geschmack. Die Farben seines Bildes (Bernstein, Blau, Grau) sind fuer
 * einen DUNKLEN Grund gewaehlt; gerechnet gegen den hellen Standard-Grund `#f8fafc` kommt
 * Bernstein auf 2,09 : 1 und Blau auf 2,90. Alle drei Haeuser laufen zwar im dunklen
 * Erscheinungsbild — aber eine Farbe, die nur dort stimmt, ist eine halbe Farbe.
 *
 * Mit eigenem Boden stimmt sie immer: Bernstein 8,11 : 1, Blau 5,85, Grau 3,84 — unabhaengig
 * davon, was der Mensch sonst eingestellt hat.
 */
.tisch-plan-view {
    padding: 12px 16px 16px;
    background: #262b31;
    border-radius: 12px;
    margin: 0 10px 10px;
}
/*
 * Der Plan passt in den sichtbaren Teil — kein Rollen (24.08.2026).
 *
 * `max-height` an einem SVG mit viewBox behaelt das Seitenverhaeltnis: die Breite geht mit
 * zurueck, der Plan wird kleiner statt abgeschnitten. Die Zahl setzt die Kasse beim Zeichnen
 * (`--plan-hoehe`, siehe planHoeheSetzen); der Ersatzwert greift, bevor einmal gemessen wurde.
 */
.tisch-plan-svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: var(--plan-hoehe, calc(100vh - 240px));
    margin: 0 auto;
}
/* Steht NUR der Plan im Fenster, gibt es nichts zu rollen — er ist ja auf die freie Höhe
   begrenzt. Sind Tische dabei, die noch nicht eingezeichnet sind, bleibt das Rollen: ihre
   Liste steht unter dem Plan und muss erreichbar sein. */
.kategorie-overlay.active.plan-modus { overflow: hidden; }
/* Im Plan-Modus braucht auch der Kasten darunter keinen Innenabstand fuer eine Kachelreihe,
   die es gar nicht gibt — der Platz gehoert dem Plan. */
.plan-modus .tisch-plan-view { padding-bottom: 0; }
.plan-modus #tischOverlayGrid { padding-bottom: 0; }

/*
 * Die Kategorie-Leiste rollt, ZEIGT es aber nicht (24.08.2026).
 *
 * Auf einem schmalen Fenster passen die Kategorien nicht nebeneinander; sie muessen sich
 * schieben lassen. Die Leiste darunter nimmt aber Hoehe weg — und weil die Hoehe des Plans aus
 * genau dieser Leiste gerechnet wird, sprang der Plan bei jedem Erscheinen der Leiste. Der Wirt:
 * „чтобы столы не дергались."
 */
.tisch-kat-chips { scrollbar-width: none; -ms-overflow-style: none; }
.tisch-kat-chips::-webkit-scrollbar { width: 0; height: 0; display: none; }
.tp-view-el-base { stroke-linecap: round; }
.tp-view-fenster-glas { stroke: #ffffffcc; stroke-linecap: round; }
.tp-view-tuer-bogen { fill: none; stroke-width: 2; stroke-dasharray: 4 4; opacity: 0.6; }
.tp-view-text { text-anchor: middle; dominant-baseline: middle; user-select: none; }
/*
 * ═══ DER STUHL TRAEGT DIE FARBE SEINES TISCHES (10.09.2026) ═══
 *
 * Zuerst waren die Stuehle grau, ueberall gleich. Der Wirt hat ein Bild geschickt, auf dem
 * sie zum Tisch GEHOEREN: dieselbe Flaeche, ein Ton dunkler, mit derselben Kante.
 *
 * Der Zustand bleibt trotzdem Sache der FLAECHE — der Stuhl ist nur etwas dunkler als sie,
 * damit man ihn abzaehlen kann. Faerbte man ihn voll mit, waere ein besetzter Sechsertisch
 * ein roter Fleck ohne Kanten.
 *
 * `brightness(.82)` statt sieben eigener Farbwerte: eine Regel, die jeder neuen Zustandsfarbe
 * von selbst folgt. Wer morgen `tisch-gesperrt` hinzufuegt, muss hier nichts nachtragen.
 */
/*
 * ═══ DER STUHL WECHSELT DIE FARBE NICHT (10.09.2026, dritte Fassung) ═══
 *
 * Der Wirt: *„они не меняют цвет, они всегда полупрозрачные."*
 *
 * Ich hatte ihn die Farbe seines Tisches tragen lassen. Am Bild NACHGEMESSEN — Bildpunkte
 * ausgelesen, nicht geschaetzt — stimmt das nicht:
 *
 *     Boden                        (50, 50, 50)
 *     Stuhl am GRAUEN Tisch        (85, 85, 85)
 *     Stuhl am BERNSTEINEN Tisch   (83, 85, 84)   ← derselbe Grauton
 *     Flaeche des bernsteinen      (240, 195, 104)
 *
 * Der Stuhl ist also nicht bernstein, obwohl sein Tisch es ist. Er ist ueberall gleich, und
 * was hinter ihm liegt, scheint durch: an einem Tisch mit gruenem Kreis dahinter nimmt er
 * dessen Ton an.
 *
 * Gerechnet aus denselben Punkten: 85 = 50 + a * (255 − 50) → **a = 0,17** fuer die Fuellung.
 * Die Kontur misst rund 200 auf dem Boden und 213 auf der Tischflaeche → **a = 0,6**.
 *
 * ═══ WARUM DAS BESSER IST ═══
 *
 * Ein Stuhl sagt nichts ueber den Zustand — er sagt, wie viele Menschen hier sitzen koennen.
 * Faerbte er mit, traege dieselbe Aussage zweimal dieselbe Farbe, und der Blick haette mehr
 * zu trennen. So bleibt Farbe dem Zustand und Form der Zahl.
 */
.tp-view-tisch .tisch-stuhl {
    fill: rgba(255, 255, 255, .17);
    stroke: rgba(255, 255, 255, .6);
    stroke-width: 1.5;
}
/*
 * `.tp-view-tafel` ist die Klammer um zusammengerueckte Tische: sie traegt den Stuhlkranz
 * der ganzen Tafel und die Radarwelle, aber keine Flaeche und keine Nummer. Sie fuehrt
 * `.tp-view-tisch` nur mit, damit die Regeln oben greifen — angefasst wird sie nicht.
 */
.tp-view-tafel { pointer-events: none; }
/*
 * ═══ DER BESETZTE STUHL IST WEISS (12.09.2026, Ansage des Wirts) ═══
 *
 * So viele Stuehle, wie Hauptspeisen offen sind, sind BESETZT — sie zaehlen die Gaeste.
 *
 * Der erste Anlauf gab ihnen die FARBE DES TISCHES, so wie er es zuerst gesagt hatte
 * (*„должны принят цвет стола"*). Auf dem Bildschirm ging das nicht auf: *„они сливаются
 * со столом."* Ein bernsteinfarbener Stuhl an einer bernsteinfarbenen Flaeche ist kein
 * Stuhl mehr, sondern eine Ausbuchtung am Rand.
 *
 * Weiss steht auf allen drei Zustandsfarben (grau, bernstein, blau) gleich deutlich —
 * und das muss es, denn der besetzte Stuhl ist eine Auskunft fuer sich: wie viele Menschen
 * essen hier. Die Farbe der Flaeche sagt etwas anderes (wie weit die Kueche ist), und zwei
 * Auskuenfte in derselben Farbe sind eine zu viel.
 *
 * Die dunkle Kante gehoert dazu: ohne sie verschwaemme der weisse Stuhl mit der hellen
 * Kante der Tischflaeche.
 */
.tp-view-tisch .tisch-stuhl-belegt {
    fill: #ffffff;
    stroke: rgba(15, 23, 42, .55);
    stroke-width: 1.5;
}
/*
 * DIE FARBEN NACH DEM BILD DES WIRTS (10.09.2026, seine Entscheidung).
 *
 *   frei    grau       ein freier Tisch ist still
 *   bereit  blau       nichts mehr offen, es kann abgerechnet werden
 *   wartet  bernstein  Kueche oder Bar haben noch etwas
 *
 * Die BEDEUTUNG bleibt, nur der Ton wechselt. Bernstein statt Rot heisst nicht „weniger
 * dringend" — es heisst, dass Rot fuer etwas frei wird, das wirklich Alarm ist. Auf dem
 * Bild ist ein Tisch rot; welcher Fall das sein soll, hat der Wirt nicht gesagt, und darum
 * steht Rot vorerst nicht im Plan. Ein Ton ohne Bedeutung ist schlimmer als keiner.
 */
.tp-view-tisch-shape { stroke-width: 2; cursor: pointer; }
/*
 * ═══ BERNSTEIN ATMET (12.09.2026, Ansage des Wirts) ═══
 *
 * *„Если стол жёлтый, то клиенты ждут свой заказ, и стол должен слегка и мягко пульсировать
 * как радар."*
 *
 * Bernstein heisst: die Kueche oder die Bar haben an diesem Tisch noch etwas. Ein
 * stillstehender Fleck sagt das auch — aber er sagt es genauso laut wie jeder andere Fleck
 * auf dem Plan. Die Bewegung hebt ihn heraus, ohne eine zweite Farbe zu verbrauchen.
 *
 * WIE LEISE: die Kante wird heller und wieder dunkler, die Flaeche selbst bleibt stehen.
 * Drei Sekunden je Atemzug — schneller wirkt es wie Alarm, und Alarm ist etwas anderes als
 * „es kommt gleich". Kein Springen, keine Groessenaenderung: zwei Tische nebeneinander
 * duerfen sich nicht beruehren.
 *
 * Dieses Verzeichnis hat zweimal eine Animation gebaut und zweimal wieder entfernt (siehe
 * [[project_trommel]]). Beide Male war sie ein Selbstzweck. Diese hier hat eine Aufgabe:
 * unter zwoelf grauen Kacheln findet man die eine bernsteinfarbene schneller, wenn sie sich
 * bewegt — und genau dort steht ein Gast, der wartet.
 */
/*
 * DIE WELLE GEHT HINAUS, der Tisch steht still (12.09.2026, zweite Fassung).
 *
 * Der erste Anlauf liess die KANTE heller und dunkler werden — *„так не видно"*, und er hat
 * recht: es bewegte sich nichts, es wurde nur etwas heller. Ein Radar schickt einen Ring
 * hinaus, und einer Bewegung folgt das Auge auch dann, wenn es woanders hinsieht.
 *
 * `transform-box: fill-box` ist noetig, damit `transform-origin: center` die Mitte des
 * RINGES meint und nicht den Nullpunkt der ganzen Zeichenflaeche — sonst waendert der Ring
 * beim Wachsen quer ueber den Plan.
 *
 * Zwei Ringe mit halbem Versatz: einer laeuft hinaus, waehrend der naechste beginnt. Mit
 * einem einzigen gaebe es zwischen den Wellen eine Pause, in der gar nichts geschieht.
 */
@keyframes tisch-radar-welle {
    0%   { transform: scale(1);    stroke-opacity: .75; }
    70%  {                         stroke-opacity: .12; }
    100% { transform: scale(1.45); stroke-opacity: 0; }
}
.tp-view-radar {
    fill: none;
    stroke: #f5c65c;
    stroke-width: 3;
    /* Ohne das waechst die LINIE mit — der Ring wuerde nach aussen immer dicker statt
       duenner, und das sieht aus wie ein Fleck, nicht wie eine Welle. */
    vector-effect: non-scaling-stroke;
    pointer-events: none;
    transform-box: fill-box;
    transform-origin: center;
    animation: tisch-radar-welle 2.4s ease-out infinite;
}
.tp-view-radar-zwei { animation-delay: 1.2s; }
/*
 * Und dasselbe auf der Kachel ohne Grundriss: nicht jedes Haus hat einen Plan gemalt, und
 * die Auskunft ist dieselbe. Dort traegt ein wachsender Schatten die Welle — ein zweites
 * Element braucht es dafuer nicht.
 */
@keyframes tisch-radar-kachel {
    0%   { box-shadow: 0 0 0 0 rgba(245, 198, 92, .55); }
    100% { box-shadow: 0 0 0 16px rgba(245, 198, 92, 0); }
}
.tisch-tile.tisch-wartet { animation: tisch-radar-kachel 2.4s ease-out infinite; }
/*
 * Wer Bewegung im System abbestellt hat, bekommt sie auch hier nicht. Die Farbe allein
 * sagt weiterhin dasselbe — die Bewegung war nur das Schnellere, nie das Einzige.
 */
@media (prefers-reduced-motion: reduce) {
    .tp-view-radar { display: none; }
    .tisch-tile.tisch-wartet { animation: none; }
}
/*
 * EIN FREIER TISCH IST STILL (10.09.2026).
 *
 * Er war blau — dieselbe Aufmerksamkeit wie ein belegter. In einem vollen Raum stehen aber
 * die meisten Tische frei, und ein Plan aus lauter kraeftigen Kacheln sagt nichts mehr.
 *
 * Der Wirt hat ein Bild geschickt, auf dem die freien GRAU sind und nur die belegten Farbe
 * tragen. Das ist die richtige Reihenfolge: Farbe gehoert dem, was Aufmerksamkeit braucht.
 *
 * Die beiden anderen Zustaende bleiben, wie sie sind — was Rot bedeutet, hat der Wirt selbst
 * festgelegt (nur wenn Kueche oder Bar wirklich noch etwas haben), und das aendert man nicht
 * nebenbei an einem Abend, an dem jemand danach arbeitet.
 */
/*
 * DAS GRAU MUSSTE DUNKLER (10.09.2026, nachgerechnet).
 *
 * Der erste Ton war `#9aa3ad` — vom Foto abgenommen, das auf DUNKLEM Grund fotografiert
 * war. Gerechnet:
 *
 *   weisse Zahl darauf        2,56 : 1   (das alte Blau hatte 4,33)
 *   gegen den hellen Grund    2,44 : 1   (und der ist der STANDARD, nicht der dunkle)
 *
 * Beides unter der Grenze. Und das Erste haengt gar nicht am Thema: Weiss auf der Flaeche
 * ist ueberall gleich schlecht. Ein stiller Tisch ist gut — ein unlesbarer nicht.
 *
 * `#6b7683`: weisse Zahl 4,62 : 1 (besser als das alte Blau), hell 4,42, dunkel 3,84.
 * Still bleibt er trotzdem — neben Rot und Gruen tritt Grau von selbst zurueck.
 */
.tp-view-tisch.tisch-frei .tp-view-tisch-shape { fill: #6b7683; stroke: #838d9b; }
/*
 * ═══ WIE EIN FREIER TISCH AUSSIEHT — DER WIRT WAEHLT (13.09.2026) ═══
 *
 * *„в настройках столов выбор, когда они пустые — чтобы выбирать, какой вид хотим."*
 * Einstellung: Verwaltung → Tische → Ansicht (`tisch_frei_aussehen`, includes/tisch_ansicht.php).
 * Das Grau darueber bleibt die Vorgabe; `[data-tisch-frei]` steht am <body> der Kasse.
 *
 * DIESELBEN ZAHLEN stehen im Kellner-Programm (`TischAussehen` in Tischplan.kt). Wer eine
 * aendert, aendert beide.
 *
 *   kontur  nur der Umriss — der stillste Plan; die Nummer hell auf dem Boden (10,3 : 1)
 *   hell    helle Flaeche, dunkle Nummer (12,4 : 1) — liest sich wie Papier
 *   gruen   „frei" in der Sprache der Ampel; weisse Nummer (5,0 : 1). Gruen ist sonst an
 *           keinem Zustand vergeben — bereit ist blau, wartet bernstein.
 */
/* Deckend im Ton des Bodens, nicht durchsichtig: die Stuehle greifen unter die Flaeche (UNTERZUG),
   und durch eine leere Flaeche saehe man ihre Kanten als Striche im Tisch. */
[data-tisch-frei="kontur"] .tp-view-tisch.tisch-frei .tp-view-tisch-shape { fill: #2c3138; stroke: #9aa4af; }
[data-tisch-frei="kontur"] .tp-view-tisch.tisch-frei :is(.tp-view-tisch-label, .tp-view-tisch-sublabel, .tp-view-tisch-geld) { fill: #d6dce2; }
[data-tisch-frei="hell"] .tp-view-tisch.tisch-frei .tp-view-tisch-shape { fill: #dfe4e9; stroke: #f4f6f8; }
[data-tisch-frei="hell"] .tp-view-tisch.tisch-frei :is(.tp-view-tisch-label, .tp-view-tisch-sublabel, .tp-view-tisch-geld) { fill: #1f2328; }
[data-tisch-frei="gruen"] .tp-view-tisch.tisch-frei .tp-view-tisch-shape { fill: #2e7d4f; stroke: #4fae78; }
/* Eigene Farben (13.09.2026): die Werte rechnet der Server (tisch_frei_eigen) und setzt sie als
   Variablen an den <body> — hier werden sie nur eingesetzt. */
[data-tisch-frei="eigen"] .tp-view-tisch.tisch-frei .tp-view-tisch-shape { fill: var(--tf-flaeche, #6b7683); stroke: var(--tf-rand, #838d9b); }
[data-tisch-frei="eigen"] .tp-view-tisch.tisch-frei :is(.tp-view-tisch-label, .tp-view-tisch-sublabel, .tp-view-tisch-geld) { fill: var(--tf-schrift, #fff); }
.tp-view-tisch.tisch-wartet .tp-view-tisch-shape { fill: #e0a52e; stroke: #f5c65c; }
.tp-view-tisch.tisch-bereit .tp-view-tisch-shape { fill: #2f9fc9; stroke: #62c0e0; }
/*
 * Bernstein ist HELL: weisse Zahl darauf ergibt 2,19 : 1. Dieser eine Zustand traegt darum
 * dunkle Schrift (7,21 : 1). Keine Ausnahme aus Bequemlichkeit — auf hellem Grund ist helle
 * Schrift falsch, egal wie der Rest der Kachel aussieht.
 */
.tp-view-tisch.tisch-wartet .tp-view-tisch-label,
.tp-view-tisch.tisch-wartet .tp-view-tisch-sublabel,
.tp-view-tisch.tisch-wartet .tp-view-tisch-geld { fill: #1f2328; }
.tp-view-tisch-label { fill: #fff; font-size: 24px; font-weight: 700; text-anchor: middle; dominant-baseline: middle; pointer-events: none; user-select: none; }
.tp-view-tisch-sublabel { fill: #ffffffdd; font-size: 14px; text-anchor: middle; dominant-baseline: middle; pointer-events: none; user-select: none; }
/* Dauer und offener Betrag unten in der Tischfläche des Plans — dieselben Angaben wie auf der
   Kachel. Klein und halbtransparent, damit die Tischnummer die Fläche weiter beherrscht. */
.tp-view-tisch-fuss { fill: #ffffffcc; font-size: 12px; font-weight: 700; pointer-events: none; user-select: none; }
.tp-view-tisch-fuss-links { text-anchor: start; }
.tp-view-tisch-fuss-rechts { text-anchor: end; }
/* Zeit oben, Geld unten — beide mittig, damit sie sich auf keinem Tisch mehr begegnen. */
/* Nur noch das Geld steht auf der Flaeche — Dauer und Reservierung sind seit dem
   10.09.2026 Plaketten. Die Regeln fuer `-zeit`, die gezeichnete Uhr und den
   Reservierungspunkt sind mit ihnen gegangen: eine Regel, die niemand mehr ruft,
   sieht beim naechsten Lesen aus wie eine, die etwas tut. */
/*
 * DIE MITTE WAR MIT DEN TOTEN REGELN GEFALLEN (10.09.2026).
 *
 * `text-anchor: middle` stand in einer GEMEINSAMEN Regel fuer `-zeit` und `-geld`. Als die
 * Dauer zur Plakette wurde, habe ich die toten `-zeit`-Regeln entfernt — und dabei die Mitte
 * des Betrags mitgenommen.
 *
 * Danach begann der Text an der Mitte, statt um sie zu stehen. Gemessen: links 55 Einheiten
 * Abstand, rechts 15 — und wo er ueber die Kante hinausragte, schnitt ihn der Ausschnitt ab,
 * **zuerst das Eurozeichen, weil es hinten steht.** Genau das hat der Wirt gemeldet:
 * *„цены прилипают, и одной нет знака €."*
 *
 * Eine Regel zu entfernen, die noch ein zweites Kind hat, ist dasselbe wie eine Zeile zu
 * loeschen, die zwei Dinge tat.
 */
.tp-view-tisch-geld {
    fill: #ffffff;
    text-anchor: middle;
    font-weight: 700;
    pointer-events: none;
    user-select: none;
}
/*
 * ═══ BEIDE PLAKETTEN LIEGEN AUF DEM TISCH — ALSO BEIDE DUNKEL (10.09.2026) ═══
 *
 * Die Dauer hing kurz UEBER dem Tisch und war darum hell. Der Wirt hat es berichtigt: sie
 * gehoert AUF die Flaeche, an deren oberen Rand — er hat einen Pfeil ins Innere gezeichnet.
 *
 * Damit liegen beide auf derselben Art Grund, und beide brauchen denselben Ton. Gerechnet
 * gegen die drei Zustandsfarben:
 *
 *     dunkel #0f172a:  grau 3,86 : 1 | blau 5,89 : 1 | bernstein 8,15 : 1
 *
 * Ueber allen dreien lesbar — und das ist der Punkt: eine Plakette darf nicht mit dem Tisch
 * verschmelzen, auf dem sie liegt.
 *
 * Unterschieden werden sie nicht durch die Farbe, sondern durch den PLATZ: die Dauer oben
 * mittig mit ihrem Balken, die Reservierung unten rechts. Zwei Toene fuer zwei Plaketten
 * waeren eine Farbe, die nichts bedeutet.
 */
.tp-view-dauer-grund { fill: #0f172a; }
.tp-view-dauer-text {
    /* 12 statt 10 (12.09.2026): der Wirt hat die Plakette eingekringelt, sie war zu klein.
       Die Zahl steht ausserdem als `style` am Element — eine CSS-Regel schlaegt ein
       SVG-Attribut, und hier waere sie sonst wirkungslos. */
    fill: #ffffff; font-size: 12px; font-weight: 800;
    text-anchor: middle; dominant-baseline: middle;
    pointer-events: none; user-select: none;
}
/*
 * DIE LINIE UNTER DER PLAKETTE (12.09.2026, Ansage des Wirts: „снизу линию сделай чтобы
 * хорошо было видно").
 *
 * Sie war weisser Hauch (#ffffff33) auf der Tischflaeche — auf Bernstein kaum zu sehen.
 * Jetzt traegt sie DIESELBE dunkle Farbe wie die Plakette darueber und liest sich als deren
 * Unterstrich; die Fuellung bleibt weiss und sagt, wie weit der Abend an diesem Tisch ist.
 */
.tp-view-balken-grund { fill: #0f172a; }
.tp-view-balken { fill: #ffffff; }

.tp-view-reserv-grund { fill: #0f172a; }
.tp-view-reserv-text {
    fill: #ffffff; font-size: 14px; font-weight: 800;
    text-anchor: middle; dominant-baseline: middle;
    pointer-events: none; user-select: none;
}
.tp-view-dauer, .tp-view-reserv { pointer-events: none; }


/* Table category filter chips (bottom of the Tisch overlay) */
/*
 * DIE SAEULE DER TISCHGRUPPEN (03.09.2026, Ansage des Wirts) — links am Rand, wie die
 * Kategorienspalte der Kasse. Zugeklappt 56 breit (nur Zahl und Farbe), aufgeklappt 180 (mit
 * Namen). Der Raumplan bleibt daneben stehen; ein Fenster ueber allem war zu viel.
 *
 * `--tisch-kat-breite` sagt beiden Seiten, wie breit sie gerade ist: die Saeule sich selbst,
 * und der Flaeche daneben ihr linkes Polster. Zwei Zahlen dafuer wuerden auseinanderlaufen.
 */
.tisch-kat-filter {
    --tisch-kat-breite: 56px;
    position: fixed;
    top: var(--tisch-kopf-h, 64px);
    bottom: var(--tisch-fuss-h, 56px);
    left: 0;
    right: auto;
    width: var(--tisch-kat-breite);
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* Rundum dasselbe Polster — der Knopf oben und die Zeichen darunter stehen damit auf
       derselben Kante (das war die Bitte des Wirts: „сделай отступы"). */
    padding: 8px;
    background: var(--djk-black);
    border-right: 1px solid var(--djk-border);
    box-shadow: 8px 0 16px rgba(0, 0, 0, 0.35);
    z-index: 2;
    transition: width 140ms ease;
}
.tisch-kat-filter.offen { --tisch-kat-breite: 180px; }

/* source/style_css/255_table_plan_view_continued.css - style.css: table plan view continued, part 35 of 78 (built by werkzeuge/parts_build.php) */
/*
 * DAS KREUZ AM FUSS DER SAEULE (17.09.2026, Ansage des Wirts).
 *
 * `margin-top: auto` und sonst nichts: die Saeule ist eine Flex-Spalte, also schiebt das
 * eine Kind mit `auto` alles Uebrige nach oben und steht selbst am Boden — bei zwei Gruppen
 * wie bei zwanzig. Eine feste Zahl waere bei jeder anderen Anzahl falsch.
 *
 * Form, Hoehe und Farbe sind die des Griffs oben (`.tisch-kat-menue-btn`): die Saeule hat
 * oben und unten denselben Abschluss, und niemand muss ein zweites Aussehen lernen.
 */
/*
 * DASSELBE KREUZ WIE OBEN — DURCH DIESELBE KLASSE (19.09.2026, Ansage des Wirts).
 *
 * Hier standen eigene Farben: roter Rahmen, dunkler Grund, Ecken 5. Das obere Kreuz hat seit
 * dem 17.09. einen hellroten Grund ohne Rahmen und Ecken 12 (`.modal-close` in icons_fa.css) —
 * zwei Knoepfe fuer dieselbe Handlung sahen verschieden aus, und der Wirt hat beide
 * eingekringelt. Der Knopf traegt jetzt `modal-close` im Markup; Farbe, Grund, Ecken und
 * Hoehe kommen von dort. Hier bleibt nur, was die SAEULE braucht: im Fluss statt absolut
 * (die Grundregel in dieser Datei setzt `position: absolute`), unten angeschlagen, so breit
 * wie die Saeule. `.tisch-kat-filter` davor, weil icons_fa.css NACH dieser Datei laedt und
 * seine 44 Punkte Breite sonst gewoennen.
 */
.tisch-kat-filter .tisch-kat-zu-btn {
    position: static;
    flex-shrink: 0;
    margin-top: auto;
    width: 100%;
    gap: 8px;
}
/* Die Groesse des Zeichens teilt es mit dem Kreuz im Kopf (siehe .kategorie-overlay-header
   .modal-close) — sie erbt sie vom Knopf. */
.tisch-kat-zu-zeichen { font-size: inherit; line-height: 1; }
/* Zugeklappt steht dort nur das Zeichen, aufgeklappt auch das Wort — wie beim Griff oben. */
.tisch-kat-zu-wort { display: none; font-weight: 700; font-size: 0.8rem; }
.tisch-kat-filter.offen .tisch-kat-zu-btn { justify-content: flex-start; padding: 0 10px; }
.tisch-kat-filter.offen .tisch-kat-zu-wort { display: block; }

/* source/style_css/260_back_way_page_head_register_report.css - style.css part 36 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* „Gutscheine" steht weiter unten in voller Breite — es ist keine Gruppe. */
.tisch-gutschein-leiste {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--djk-black);
    border-top: 1px solid var(--djk-border);
    z-index: 2;
}
/*
 * ZWEI KNOEPFE NEBENEINANDER (05.09.2026) — „Gutscheine" und „Mitglieder".
 *
 * Sie standen untereinander, weil hier bis heute EIN Knopf lag und `width: 100%` genuegte.
 * Zwei volle Zeilen fressen am unteren Rand doppelt so viel Hoehe wie noetig, und der Wirt
 * hat ausdruecklich *„как на приложении"* gesagt — dort teilen sie sich eine Reihe.
 *
 * `flex: 1` statt `width: 100%`: mit EINEM Knopf sieht es aus wie vorher (er nimmt die ganze
 * Breite), mit zweien teilen sie sich. Ein Haus ohne Mitglieder-Kategorie merkt also nichts.
 */
.tisch-gutschein-leiste { display: flex; gap: 8px; }
.tisch-gutschein-leiste .tisch-kat-chip { flex: 1; width: auto; justify-content: center; }

.tisch-kat-filter-icons { display: flex; gap: 8px; }

/*
 * Hier stand bis zum 07.09.2026 `.kb-filter` — die Zahlarten als aufklappbare Saeule am
 * linken Rand. Sie ist ersatzlos weg: die Zahlarten stehen jetzt als Reihe ueber der
 * Liste (`.kb-arten`), so wie im Programm. Ein Stil ohne Markup faerbt nichts und
 * verwirrt nur den naechsten, der ihn liest.
 */

/* --- Der Weg zurueck ganz unten ----------------------------------------------------------
 *
 * „самом внизу поставь кнопку назад" — ueber die ganze Breite, damit der Daumen sie trifft,
 * ohne hinzusehen. Dieselbe Leiste kann jede Seite tragen, die einen Weg zurueck hat.
 */
.seiten-fuss-zurueck {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 4;
    display: flex;
    padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--djk-black);
    border-top: 1px solid var(--djk-border);
}
/* 46 px — dasselbe Mass wie `FussZurueck` im Programm (Umsatz.kt). Ohne Angabe richtet sich
   die Hoehe nach dem Polster des Knopfes und lag bei 52; zwei Zahlen fuer denselben Griff.
   Gemessen am 07.09.2026 auf beiden Seiten. */
.seiten-fuss-zurueck .btn { flex: 1; justify-content: center; gap: 8px; height: 46px; }

/*
 * Platz fuer die Leiste. Sie liegt `fixed` ueber der Seite; ohne diesen Zuschlag verschwindet
 * das letzte Stueck Inhalt dahinter — auf der Reservierungsseite war es die Reihe
 * „Gaeste / offen / frei", die der Wirt auf dem Foto angestrichen hat.
 *
 * 69 px ist die gemessene Hoehe der Leiste, dazu 16 Luft und der Rand des Geraets.
 */
.hat-fuss-zurueck { padding-bottom: calc(85px + env(safe-area-inset-bottom, 0px)); }

/*
 * SUMME UND ZURUECK SIND EIN FUSS (26.09.2026, Foto des Wirts vom Kassenbericht).
 *
 * Die Summe klebte als eigener Streifen UEBER der Leiste (`bottom: 69px`, gemessen an einem
 * Telefon) — zwischen beiden blieb ein Spalt, durch den die Belege durchliefen. Zwei
 * Geschwister, die aneinander rechnen, passen nie auf jedem Geraet. Jetzt steht alles, was
 * unten fest sein soll, IN der Leiste: ein Grund, kein Spalt. Die Leiste bricht um; was kein
 * Knopf ist, nimmt die ganze Zeile ueber ihm.
 */
.seiten-fuss-zurueck { flex-wrap: wrap; }
.seiten-fuss-zurueck > :not(.btn) { flex: 1 0 100%; }

/*
 * DER FESTE KOPF (26.09.2026, drei Fotos des Wirts vom iPhone).
 *
 * Titel, Unterzeile und Filter bleiben oben stehen, die Liste laeuft darunter durch. Deckender
 * Grund in der Seitenfarbe, KEINE Unschaerfe: auf dem iPhone legt Safari selbst (seit iOS 26,
 * „Scroll Edge") einen weichen Schleier ueber alles, was unter die Statusleiste rollt — genau
 * die „Muetzigkeit", die der Wirt fotografiert hat. Rollt nichts mehr darunter, weil dort ein
 * deckender Kopf steht, gibt es nichts zu verschleiern.
 *
 * Die sichere Zone oben traegt der KOPF und nicht die Seite: stuende das Polster auf der
 * Section darueber, rollte es mit weg, und der Kopf klebte hinter der Uhr.
 *
 * Der Schatten nach links und rechts verlaengert den Grund ueber den Rand des Containers;
 * `clip-path` schneidet ihn oben und unten ab, damit er nichts ueberdeckt.
 */
.kopf-fest {
    position: sticky;
    top: 0;
    z-index: 6;
    background: var(--djk-black);
    box-shadow: 0 0 0 100vmax var(--djk-black);
    clip-path: inset(0 -100vmax);
    padding-top: calc(var(--kopf-fest-luft, 16px) + env(safe-area-inset-top, 0px));
    padding-bottom: 8px;
}

/* --- Der Seitenkopf, wie ihn das Programm zeichnet (07.09.2026) ---------------------------
 *
 * `SeitenKopf` in Umsatz.kt: Sinnbild 24 dp, 10 dp Abstand, Titel in `titleLarge` (22 sp,
 * Staerke 400). Darunter — wo es eine gibt — die Unterzeile in `labelSmall` (11 sp, grau).
 * Der Wirt hat auf das Programm gezeigt: *„дизайн из приложения"*.
 */
.seiten-kopf {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 10px;
}
/*
 * 24 px — und zwar auf BEIDEN Wegen.
 *
 * `icon()` liefert je nach Zeichen ein `<svg class="icon">` ODER ein `<i class="fas fa-…">`
 * aus Font Awesome. Ein Schriftzeichen wird von `width` aber nicht groesser: es ist so gross
 * wie die SCHRIFT an dieser Stelle, und die stand hier bei 16 px (`icons_fa.css` haelt sie
 * bei `max(16px, 1em)`, und `body` setzt keine eigene). Das Sinnbild im Seitenkopf war
 * deshalb 16 px statt 24 — dasselbe Muster wie bei `.admin-seiten-kopf h2` weiter oben.
 */
.seiten-kopf .icon { flex: 0 0 auto; }
.seiten-kopf svg.icon { width: 24px; height: 24px; }
/* Die Schriftzeichen stehen in icons_fa.css — dort steht `i.icon:not([class*="icon-sm"])
   mit derselben Staerke und in einem SPAETEREN Blatt: eine Regel von hier verliert. */
.seiten-kopf h1 {
    margin: 0;
    font-size: 22px;
    font-weight: 400;
    line-height: 28px;
    color: var(--djk-white);
}
.seiten-kopf-unter {
    margin: 2px 0 0;
    font-size: 11px;
    color: var(--djk-gray);
}

/* --- Kassenbericht: dieselbe Liste wie im Programm ----------------------------------------
 *
 * Die Zahlarten als REIHE darueber (bis heute Mittag eine Saeule am linken Rand — sie schnitt
 * die Belegnummern ab), je Beleg zwei Zeilen und der Betrag rechts, unten die Summe ueber
 * einem Strich in der Hausfarbe.
 *
 * EIN Unterschied zum Programm ist Absicht und steht auf Ansage: *„чеки немного раздели,
 * чтобы красиво виднелись"* — statt einer Haarlinie zwischen den Zeilen bekommt jeder Beleg
 * eine eigene Karte mit Luft dazwischen. Dasselbe hat das Programm mitbekommen.
 */
/* Oben kein Polster: die sichere Zone traegt der feste Kopf (`.kopf-fest`). Unten Platz fuer den
   Fuss aus Summe UND Zurueck (rund 117 px). */
.kb-seite { padding-top: 0; padding-bottom: calc(135px + env(safe-area-inset-bottom, 0px)); }
.kb-seite .kopf-fest .kb-arten { margin-bottom: 0; }
.kb-arten {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: 4px;
    margin-bottom: 10px;
    scrollbar-width: none;
}
.kb-arten::-webkit-scrollbar { display: none; }
.kb-art {
    flex: 0 0 auto;
    padding: 9px 14px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: transparent;
    color: var(--djk-white);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.kb-art.active {
    border-color: var(--djk-yellow);
    color: var(--djk-yellow);
    background: color-mix(in srgb, var(--djk-yellow) 12%, transparent);
}

.kb-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.kb-leer { color: var(--djk-gray); padding: 12px 2px; }
.kb-zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 5px;
    background: var(--djk-black-card);
    cursor: pointer;
}
.kb-zeile-text { flex: 1 1 auto; min-width: 0; }
.kb-kopf { font-weight: 600; }
.kb-unten { font-size: 11px; color: var(--djk-gray); margin-top: 2px; }
.kb-offen {
    display: inline-block;
    margin-top: 4px;
    font-size: 11px;
    font-weight: 700;
    color: var(--djk-yellow);
}
.kb-betrag {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    white-space: nowrap;
}
.kb-betrag .icon { width: 18px; height: 18px; }
/* Storniert: durchgestrichen und rot — es zaehlt nicht mit, verschwindet aber auch nicht. */
.kb-zeile.ist-storniert .kb-kopf,
.kb-zeile.ist-storniert .kb-betrag { text-decoration: line-through; color: var(--djk-danger); }

/*
 * DIE SUMME KLEBT — wie im Programm.
 *
 * Dort liegt die Liste in `LazyColumn(Modifier.weight(1f))` und die Summen-Zeile DANACH: sie
 * steht immer am unteren Rand, egal wie viele Belege es sind. Im Browser stand sie im Fluss
 * am Listenende, und bei 19 Belegen musste der Kellner erst dorthin rollen, um zu sehen, was
 * er kassiert hat — genau die Zahl, wegen der er die Seite geoeffnet hat.
 *
 * 64 px ist die Hoehe von `.seiten-fuss-zurueck` darunter; eine gemeinsame Variable geht
 * nicht, die beiden sind Geschwister (dieselbe Rechnung wie bei der alten Filter-Saeule).
 */
.kb-summe {
    position: sticky;
    /* 69 px: die Hoehe von `.seiten-fuss-zurueck`, am Telefon gemessen (412x915) — mit
       64 lagen 5 px der Summe unter der Leiste und ihre Oberkante verschwand. */
    bottom: calc(69px + env(safe-area-inset-bottom, 0px));
    z-index: 3;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-top: 6px;
    padding: 10px 0;
    border-top: 2px solid var(--djk-yellow);
    background: var(--djk-black);
    font-size: 16px;
    font-weight: 800;
}
.kb-summe strong { color: var(--djk-yellow); }
/* Seit 26.09.2026 steht die Summe IN der Zurueck-Leiste — dort klebt die Leiste, nicht sie. */
.seiten-fuss-zurueck > .kb-summe { position: static; margin: 0 0 8px; padding: 2px 2px 0; border-top: 0; background: none; }
/* Der Strich in der Hausfarbe bleibt — jetzt als Oberkante des ganzen Fusses. */
.seiten-fuss-zurueck:has(> .kb-summe) { border-top: 2px solid var(--djk-yellow); }

/*
 * Der Kassenbericht ist eine LISTE, kein Warenkorb. Er trug bis zum 07.09.2026 die Klasse
 * `.cart-list` des Bons und damit deren `max-height: 340px` — gemessen auf dem Telefon: 19
 * Belege (scrollHeight 1070) in einem Kaestchen von 340 px, darunter 480 px leerer
 * Bildschirm. Jetzt heisst sie `.kb-liste` und hat das Mass nicht mehr; die Zeile bleibt als
 * Riegel stehen, falls die Klasse je zurueckkehrt. Hier rollt die SEITE.
 */
#kbList { max-height: none; overflow-y: visible; margin-bottom: 0; }

.tisch-kat-chip {
    flex-shrink: 0;
    padding: 16px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.tisch-kat-chip.active { border-color: var(--djk-yellow); color: var(--djk-yellow); background: rgba(59, 130, 246, 0.1); }

/* DIE FARBSPRACHE DER TISCHE, EINE STUFE HOEHER (03.09.2026).

   Blau frei, gruen bereit, rot es wartet noch etwas — dieselben Farben wie auf der Kachel
   (.tisch-frei/-bereit/-wartet weiter oben) und dieselben Klassennamen, damit niemand zwei
   Farbsprachen lernen muss. Der Verlauf endet hier im Grund des PLAETTCHENS
   (--djk-black-soft) statt im Grund der Karte: das Plaettchen behaelt seinen Platz in der
   Leiste, nur die Aussage kommt dazu.

   NACH `.active`, mit gleicher Staerke: das gewaehlte Plaettchen behaelt seinen Rahmen als
   Merkmal, verliert aber nicht die Farbe seiner Gruppe. Und die Schrift wird auf den
   satten Gruenden fest weiss — im hellen Erscheinungsbild ist `--djk-white` fast schwarz. */
.tisch-kat-chip.tisch-frei {
    border-color: #6b768399;
    background: linear-gradient(150deg, #6b768340, var(--djk-black-soft) 65%);
}
/* Und in der Gruppenleiste (13.09.2026) — ein Plaettchen, das anders aussieht als seine Tische,
   waere eine zweite Sprache fuer denselben Zustand. */
[data-tisch-frei="kontur"] .tisch-kat-chip.tisch-frei { border-color: #9aa4af; background: transparent; }
[data-tisch-frei="hell"] .tisch-kat-chip.tisch-frei { border-color: #c3cbd3; background: linear-gradient(150deg, #eef1f4 0%, #d3d9df 100%); color: #1f2328; }
[data-tisch-frei="gruen"] .tisch-kat-chip.tisch-frei { border-color: #4fae78; background: linear-gradient(150deg, #2e7d4f 0%, #1f5c39 100%); color: #fff; }
[data-tisch-frei="eigen"] .tisch-kat-chip.tisch-frei { border-color: var(--tf-rand, #838d9b); background: var(--tf-kachel, transparent); color: var(--tf-kachel-schrift, inherit); }
.tisch-kat-chip.tisch-bereit {
    border-color: #62c0e0;
    background: linear-gradient(150deg, #2f9fc9 0%, #1f7594 100%);
    color: #fff;
}
.tisch-kat-chip.tisch-wartet {
    border-color: #f5c65c;
    background: linear-gradient(150deg, #e0a52e 0%, #b8821c 100%);
    color: #1f2328;
}

/*
 * DAS KLEINE ZEICHEN (03.09.2026, Ansage des Wirts).
 *
 * Geschlossen traegt die Leiste je Gruppe nur ein Quadrat: ihre Farbe und die Zahl der
 * besetzten Tische. 44 ist das Mass der uebrigen Zeichenknoepfe der Kasse — so bleibt die
 * Leiste so hoch wie zuvor, und sechs Gruppen passen nebeneinander statt anderthalb.
 *
 * Der NAME steht im Fenster (Knopf im Kopf) und im `title` — auf 44 Punkten waere er ohnehin
 * nicht zu lesen.
 */
.tisch-kat-chip.tisch-kat-zeichen {
    width: 100%;
    min-height: 44px;
    padding: 0 8px;
    justify-content: center;
    gap: 8px;
}
/* Aufgeklappt steht der Name links, die Zahl rechts — wie auf der Kategorie-Kachel. */
.tisch-kat-filter.offen .tisch-kat-zeichen { justify-content: space-between; }
.tisch-kat-zeichen-name { display: none; }
.tisch-kat-filter.offen .tisch-kat-zeichen-name {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}
/* ZUGEKLAPPT ist die Zahl das Einzige, was dasteht — also gross und in der Mitte (der Wirt
   hat sie am 04.09.2026 genau so ins Quadrat geschrieben). Aufgeklappt steht sie neben dem
   Namen und tritt zurueck. */
.tisch-kat-zeichen-zahl {
    font-size: 1.1rem;
    font-weight: 800;
    line-height: 1;
}
.tisch-kat-filter.offen .tisch-kat-zeichen-zahl { font-size: 1.05rem; }

/* Der erste Buchstabe steht dort, wo sonst die Zahl staende — nur leiser: eine ZAHL ist eine
   Auskunft, ein Buchstabe nur ein Wegweiser. Aufgeklappt faellt er weg, dort steht der Name. */
.tisch-kat-zeichen-buchstabe {
    font-size: 1.1rem;
    font-weight: 800;
    line-height: 1;
    opacity: 0.75;
}
.tisch-kat-filter.offen .tisch-kat-zeichen-buchstabe { display: none; }
/*
 * Der Buchstabe steht IMMER im Markup und wird nur ausgeblendet (12.09.2026).
 *
 * Vorher entschied das PHP beim Bauen, ob er ueberhaupt dasteht. Seit die Saeule LIVE
 * mitfaerbt, muss die Auffrischung ihn ein- und ausschalten koennen, ohne den Knopf neu zu
 * bauen — ein Finger, der gerade darauf liegt, verloere ihn sonst unter sich.
 *
 * `!important`, weil `display` einer Autorenregel jedes `hidden` schlaegt (siehe Fallen).
 */
.tisch-kat-zeichen-buchstabe.stuhl-aus { display: none !important; }
/*
 * DER STERN SITZT IN DER OBEREN RECHTEN ECKE (04.09.2026, Ansage des Wirts — sein Kreis lag
 * genau dort). Links stand er dem Namen im Weg; rechts ist ohnehin Platz.
 */
/*
 * DIE START-GRUPPE STEHT AUF DERSELBEN KANTE wie die uebrigen (04.09.2026).
 *
 * Fuer die waagerechte Plaettchen-Reihe macht der Stern Platz im Text (`padding-left: 26px`).
 * In der SAEULE liegt er in der Ecke und braucht keinen — mit den geerbten Polstern begann
 * „Biergarten" 18 Punkte weiter rechts als „Gaststätte" (gemessen: x=35 gegen x=17).
 */
.tisch-kat-chip.tisch-kat-zeichen.ist-start-kat { padding-left: 8px; padding-right: 8px; }
/* Masse vom Wirt selbst (04.09.2026): enger in die Ecke. */
.tisch-kat-chip.tisch-kat-zeichen.ist-start-kat::after { top: 1px; right: 3px; left: auto; }

/* source/style_css/265_back_way_page_head_register_report_continued.css - style.css: back way page head register report continued, part 37 of 78 (built by werkzeuge/parts_build.php) */
/*
 * DIE FUELL-LINIE (04.09.2026): „если столы все заняты, то линия до конца."
 *
 * Sie liegt auf der unteren Kante des Zeichens und ist so breit wie der Anteil der besetzten
 * Tische. Die Bahn dahinter ist immer da — sonst waere bei einer leeren Gruppe nicht zu
 * sehen, dass es die Linie ueberhaupt gibt.
 *
 * Weiss statt einer eigenen Farbe: sie liegt auf Rot, Gruen und dem blauen Hauch und muss auf
 * allen dreien dasselbe bedeuten.
 */
.tisch-kat-zeichen { position: relative; overflow: hidden; }
.tisch-kat-fuellung {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 4px;
    background: rgba(255, 255, 255, 0.16);
    pointer-events: none;
}
.tisch-kat-fuellung::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--fuellung, 0%);
    background: rgba(255, 255, 255, 0.85);
}

/*
 * DER GRIFF IM KOPF DER SAEULE (03.09.2026).
 *
 * Dieselbe Breite, dieselbe Rundung und derselbe Abstand wie die Zeichen darunter — er ist
 * das erste Stueck der Saeule und keine Marke daneben. Aufgeklappt waechst er mit.
 */
.tisch-kat-menue-btn {
    flex-shrink: 0;
    width: 100%;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    cursor: pointer;
}
.tisch-kat-menue-btn .icon { width: 20px; height: 20px; }
/* Aufgeklappt sagt er auch, was er ist — sonst steht ein stummes Zeichen ueber lauter Namen. */
.tisch-kat-filter.offen .tisch-kat-menue-btn { justify-content: flex-start; padding: 0 10px; gap: 8px; }
.tisch-kat-menue-btn .tisch-kat-menue-wort { display: none; font-weight: 700; font-size: 0.8rem; }
.tisch-kat-filter.offen .tisch-kat-menue-btn .tisch-kat-menue-wort { display: block; }

/* Siehe oben: die Wahl muss auf jedem Grund sichtbar bleiben. */
.tisch-kat-chip.active.tisch-frei,
.tisch-kat-chip.active.tisch-bereit,
.tisch-kat-chip.active.tisch-wartet { border-color: var(--djk-yellow); }
.tisch-kat-chip.active.tisch-bereit,
.tisch-kat-chip.active.tisch-wartet { box-shadow: 0 0 0 2px var(--djk-yellow); }

/* source/style_css/270_receipt_window_swipe_extras.css - style.css part 38 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* DERSELBE Stern wie auf der Produkt-Kategorie (.kategorie-tile.ist-start-kat) — gleiches
   Zeichen, gleiche Farbe aus der Verwaltung, gleicher Schatten. Er bedeutet hier dasselbe:
   „damit öffnet sich die Auswahl für mich". Zwei verschiedene Marken für dieselbe Aussage
   waeren zwei Dinge zum Lernen statt einem.

   Oben rechts statt unten rechts: ein Plättchen ist nur so hoch wie seine Schrift, unten
   säße der Stern auf dem Text. Dafür bekommt das Plättchen rechts etwas mehr Luft. */
.tisch-kat-chip { position: relative; }
.tisch-kat-chip.ist-start-kat { padding-right: 26px; }
.tisch-kat-chip.ist-start-kat::after {
    content: "★";
    position: absolute;
    top: 3px;
    right: 5px;
    font-size: 0.85rem;
    line-height: 1;
    color: var(--kasse-stern, var(--djk-copper, #fbbf24));
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
    pointer-events: none;
}

/* Untereinander statt nebeneinander — und die Saeule rollt, wenn es mehr Gruppen sind, als
   auf den Bildschirm passen. */
.tisch-kat-chips {
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
    overflow-x: hidden;
    width: 100%;
    -webkit-overflow-scrolling: touch;
}

/* Die Filterleiste ist jetzt fixed (zwei Zeilen hoch) — die Tisch-Kacheln brauchen
   entsprechend Platz am unteren Rand, damit die letzte Reihe nicht verdeckt wird. */
#tischOverlayGrid { padding-bottom: 130px; }

.tisch-kat-kassenbericht-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    display: flex;
    align-items: center;
    justify-content: center;
}

.tisch-kat-kassenbericht-btn .icon { width: 20px; height: 20px; }
.tisch-kat-kassenbericht-btn:hover { border-color: var(--djk-yellow); color: var(--djk-yellow); text-decoration: none; }

/* Split-quantity stepper in the table detail (pay part of a multi-qty line) */
.posten-qty-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 6px;
}

.posten-qty-label { font-size: 0.75rem; color: var(--djk-gray); margin-right: auto; }

.posten-qty-btn {
    width: 30px;
    height: 30px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-size: 1.1rem;
    font-weight: 800;
    line-height: 1;
    cursor: pointer;
}

.posten-qty-btn:disabled { opacity: 0.35; cursor: default; }
.posten-qty-value { min-width: 46px; text-align: center; font-weight: 700; }
.posten-qty-value.selected { color: var(--djk-yellow); }

/*
 * AUSGEWÄHLT SIEHT MAN, OHNE ZU LESEN (24.08.2026).
 *
 * Beim Aufteilen wandert der Blick über zehn weisse Blätter; welche davon in die nächste Zahlung
 * gehen, stand bisher nur als Ziffer im Stepper. Der Wirt hat die Zeile eingekringelt und einen
 * Strich unter das Blatt gemalt: Farbe für „gehört dazu", Balken für „wie viel davon".
 *
 * Der Balken ist der Anteil, nicht der Betrag: bei „3× Gyros Salat" und zwei gewählten steht er
 * auf zwei Dritteln. Voll heisst: diese Zeile geht ganz mit.
 */
.cart-list li.cart-line.cart-line-gewaehlt:not(.cart-line-pending) {
    background: #eaf2fc;
    box-shadow: inset 4px 0 0 #2f7cc9;
}
.cart-list li.cart-line.cart-line-gewaehlt .cart-item-name { color: #0f2c4d; }

/* Die Spur liegt am unteren Rand des Blattes — dort, wo der Wirt den Strich gezogen hat. */
.cart-line-anteil {
    height: 4px;
    margin: 8px -14px -10px;      /* bis an die Kanten des Blattes, das 10/14 Innenabstand hat */
    background: rgba(47, 124, 201, 0.14);
    border-radius: 0 0 4px 4px;
    overflow: hidden;
}
.cart-line-anteil > span {
    display: block;
    height: 100%;
    width: 0;
    background: #2f7cc9;
    transition: width .15s ease-out;
}
/* Ganz gewählt: der Balken wird grün — „von dieser Zeile bleibt nichts stehen". */
.cart-line-ganz .cart-line-anteil > span { background: #16a34a; }
.cart-line-ganz.cart-line-gewaehlt:not(.cart-line-pending) { box-shadow: inset 4px 0 0 #16a34a; }

/* Mengen-Stepper im Produkt-Picker (Kasse) — rund, wie im Online-Shop */
/*
 * Die Kopfreihe des Auswahlfensters: links die Praefixe („Ohne | Mit"), rechts die Menge
 * und „Zum Mitnehmen". Beides gilt fuer die ganze Zeile, nicht fuer eine Zutat.
 * flex-wrap, weil auf einem Telefon neben drei Praefix-Knoepfen nichts mehr hinpasst —
 * dann rutscht die rechte Gruppe in die naechste Zeile, statt den Rand zu sprengen.
 */
.picker-kopf-reihe {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 14px;
}
.picker-kopf-reihe .praefix-options { margin: 0; }
.picker-kopf-rechts { display: flex; align-items: center; gap: 10px; margin-left: auto; flex-wrap: wrap; }
.picker-kopf-rechts .picker-qty-row { margin: 0; }
/* Steht die rechte Gruppe als Erstes in der Reihe, gibt es links nichts, wovon sie sich
   absetzen muesste — dann faengt sie einfach vorne an. */
.picker-kopf-reihe > .picker-kopf-rechts:first-child { margin-left: 0; }
/* Die Reihe mit „Kueche Divers": links die Stationen, rechts die Menge. Gibt es keine
   Station, steht die Menge als Erstes und faengt darum vorne an. */
.picker-divers-reihe { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.picker-divers-reihe .praefix-options { margin: 0; }
.picker-divers-reihe > .picker-kopf-rechts:first-child { margin-left: 0; }
.picker-qty-row { display: flex; align-items: center; gap: 14px; margin: 16px 0; }
.posten-qty-btn-round {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    font-size: 1.2rem;
}
.picker-qty-row .posten-qty-value { min-width: 24px; font-size: 1.1rem; font-weight: 800; }

/* Beilage picker */
.beilage-options {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 10px;
}

.beilage-option-btn {
    flex: 1;
    min-width: 100px;
    padding: 16px 10px;
    border-radius: 5px;
    border: 2px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-weight: 700;
    cursor: pointer;
}

.beilage-option-btn:hover { border-color: var(--djk-yellow); }

.beilage-radio {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 14px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    cursor: pointer;
    font-size: 0.88rem;
}

.beilage-radio input { accent-color: var(--djk-yellow); width: 16px; height: 16px; }

/* Checkbox picker (Beilagen + Extras, tap flow) */
.checkbox-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;
}

.checkbox-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    cursor: pointer;
    font-size: 0.9rem;
    transition: border-color var(--transition), background var(--transition);
}

/* --- Kassenbericht: Belegfenster ---------------------------------------------------------
   Kopf mit Belegnummer, Datum/Uhrzeit und Tisch; darunter die Positionen mit Haken. */
.kb-beleg-kopf {
    margin: 0 0 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--djk-border);
    font-size: 0.85rem;
    color: var(--djk-gray);
}
.kb-beleg-kopf-zeile { display: flex; justify-content: space-between; gap: 12px; }
.kb-beleg-kopf-zeile span:first-child { font-weight: 700; color: var(--djk-white); }
/* Der Haken gehört in die Zeile, auf eine Höhe mit dem Namen. */
/* .kb-pos-haken ist weg: im Kassenbericht geht immer der GANZE Beleg zurueck (15.08.2026). */
.kb-pos-zeile .cart-line-row { display: flex; align-items: center; }

/* Links Name und Extras, rechts die Preisspalte über die ganze Zeilenhöhe verteilt. */
.cart-line-haupt { display: flex; align-items: stretch; gap: 12px; }
.cart-line-links { flex: 1; min-width: 0; }
.cart-preise {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: space-between;
    flex-shrink: 0;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
/* Grau der Grundpreis, rot der Aufschlag, BLAU immer der Endbetrag. Ohne Extras steht nur der
   blaue da — so heisst Blau in dieser Spalte immer dasselbe und muss nie nachgerechnet werden. */
.cart-preis-basis { color: var(--djk-gray); font-weight: 700; }
.cart-preis-extras { color: var(--djk-danger); font-weight: 800; }
.cart-preis-gesamt { color: var(--djk-yellow); font-weight: 800; font-size: 1.02rem; }

/* Extras nach Präfix gruppiert:  "Mit:" als Überschrift, darunter je Extra eine Zeile.
   Als eine Zeile mit Kommas war bei mehreren Extras nicht zu erkennen, was zusammengehört. */
.cart-item-extras {
    margin-top: 4px;
    color: var(--djk-gray);
    font-size: 0.74rem;
    line-height: 1.45;
}
.cart-extra-praefix { font-weight: 800; }
.cart-extra-praefix:not(:first-child) { margin-top: 3px; }
.cart-extra-zeile { font-weight: 600; }

/* --- Wischen auf einer noch nicht gebuchten Warenkorbzeile ---------------------------------
   Links = entfernen (rot), rechts = bearbeiten (blau). Die Farbfläche liegt HINTER dem Inhalt
   und wird beim Ziehen freigelegt; ausgelöst wird erst über der halben Zeilenbreite. Bis dahin
   gleitet die Zeile weich an ihren Platz zurück — die Bewegung erklärt, dass nichts geschah. */
.cart-line-pending {
    position: relative;
    overflow: hidden;
    touch-action: pan-y;
}
/* Die Polsterung wandert von der Zeile in den Inhalt: nur so deckt der Inhalt die Farbfläche
   vollständig ab und schiebt sich sauber über sie hinweg. */
.cart-list li.cart-line.cart-line-pending { padding: 0; }
/* Der Inhalt braucht einen DECKENDEN Hintergrund, sonst schiene die Farbfläche durch ihn
   hindurch. Der Farbton ist derselbe wie zuvor auf der Zeile (blauer Schleier auf der
   Kartenfläche) — hier nur als Verlauf über die deckende Grundfarbe gelegt, statt halbtransparent. */
.cart-line-pending .cart-line-inhalt {
    position: relative;
    z-index: 1;
    background:
        linear-gradient(rgba(59, 130, 246, 0.12), rgba(59, 130, 246, 0.12)),
        var(--djk-black-card);
    /* Rechts Luft, damit die Preise nicht am roten Rand kleben. */
    padding: 10px 14px 10px 8px;
    will-change: transform;
}
/* Die beiden Knöpfe liegen hinter dem Inhalt, jeder auf einer Hälfte. Das Wischen deckt sie nur
   auf — gehandelt wird erst auf Knopfdruck. */
.cart-wisch-flaeche {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: flex;
    justify-content: space-between;
}
/* BEIDE Knöpfe stehen immer da, je einer auf einer Hälfte — solange nicht gewischt wird, liegt
   der Inhalt ohnehin darüber. Vorher wurde der jeweils andere auf display:none gesetzt; mit nur
   noch einem Kind verhält sich space-between wie flex-start, und der rote Knopf rutschte nach
   LINKS — genau unter den Inhalt, also unsichtbar. */
.cart-wisch-aktion {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 50%;
    border: 0;
    padding: 0;
    color: #fff;
    font-size: 0.95rem;
    font-weight: 800;
    cursor: pointer;
}
.cart-wisch-aktion .icon { width: 18px; height: 18px; }
/* Links blau wie der linke Rand der Zeile, rechts rot wie der rechte — dieselbe Farbsprache,
   damit schon der Rand verrät, in welche Richtung was passiert. */
.cart-wisch-bearbeiten { background: #1d4ed8; }
.cart-wisch-loeschen { background: #c81e1e; }

/* Verschwinden: von oben und unten zur Mitte hin zusammenschrumpfen, statt abrupt wegzuspringen.
   scaleY um die eigene Mitte macht die Bewegung, die Höhe schliesst gleichzeitig die Lücke in
   der Liste. */
.cart-line-pending {
    transition: height .28s ease, opacity .28s ease, transform .28s ease;
}
.cart-line-verschwindet {
    height: 0 !important;
    opacity: 0;
    transform: scaleY(0);
    transform-origin: center;
    border-bottom-color: transparent;
}

/* --- Extra mit Menge ("2× Kugel Eis") ---------------------------------------------------
   Die Zeile trägt rechts einen Mengenknopf; das Untermenü klappt DARUNTER auf, innerhalb der
   Liste. Ein schwebendes Menü wäre im scrollbaren Fenster nur eine weitere Quelle für
   abgeschnittene Kanten. */
.extra-zeile { display: flex; flex-direction: column; }
.extra-zeile-kopf { display: flex; align-items: stretch; gap: 8px; }
.extra-zeile-kopf .checkbox-option { flex: 1; min-width: 0; }
.extra-menge-btn {
    flex-shrink: 0;
    min-width: 52px;
    padding: 0 12px;
    border: 1px solid var(--djk-yellow);
    border-radius: 5px;
    background: var(--djk-black-card);
    color: var(--djk-yellow);
    font-size: 0.95rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
}
.extra-menge-btn:hover { background: var(--djk-yellow); color: #fff; }
/* Im Untermenü derselbe Schrittzähler wie für die Menge des Gerichts — ein zweites Bedienmuster
   für dieselbe Sache wäre nur Lernaufwand. */
.extra-menge-menue {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-top: 6px;
    padding: 8px;
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: var(--djk-black-card);
}
.extra-menge-wert {
    min-width: 34px;
    text-align: center;
    color: var(--djk-white);
    font-size: 1.05rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.checkbox-option:has(input:checked) { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.1); }

.checkbox-option input { position: absolute; opacity: 0; width: 0; height: 0; }

.checkbox-box {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border-radius: 5px;
    border: 2px solid var(--djk-border);
    display: flex;
    align-items: center;
    justify-content: center;
    color: transparent;
    transition: border-color var(--transition), background var(--transition), color var(--transition);
}

.checkbox-box .icon { width: 15px; height: 15px; }

.checkbox-option input:checked + .checkbox-box {
    border-color: var(--djk-yellow);
    background: var(--djk-yellow);
    color: var(--djk-black);
}

/* source/style_css/275_receipt_window_swipe_extras_continued.css - style.css: receipt window swipe extras continued, part 39 of 78 (built by werkzeuge/parts_build.php) */
.picker-total {
    text-align: right;
    font-size: 1.15rem;
    font-weight: 800;
    color: var(--djk-yellow);
    margin: 14px 0 10px;
}

/* Extra-Präfixe (Ohne / Mit / Statt / Nur / Viel) shown above the Extras checkboxes */
.praefix-options {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 8px;
}

.praefix-btn {
    /* 10/15 statt 8/16 — auf Ansage des Wirts: die Knoepfe sind hoeher und dafuer schmaler,
       und dann passen „Mit Statt Nur nicht Mehr" wieder in EINE Reihe. */
    padding: 10px 15px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.praefix-btn.active { border-color: var(--djk-yellow); color: var(--djk-yellow); background: rgba(59, 130, 246, 0.12); }

/* Ein Extra gehoert immer nur EINEM Praefix: "Ohne Zwiebeln" und "Mehr Zwiebeln" auf demselben
   Gericht kann die Kueche nicht zugleich tun. Unter den uebrigen Reitern steht es deshalb blass
   und laesst sich nicht antippen — mit der Notiz, wo es schon haengt. */
/* source/style_css/280_side_items_list.css - style.css part 40 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==============================================================================================
   DIE BEIGABE IN DER LISTE (28.08.2026)
   ==============================================================================================
   Der Wirt hat den Bildschirm selbst zurechtgelegt und ein Bild geschickt: „Beilagen Salat" soll
   aussehen wie „Zwiebeln" darueber — eine Zeile mit Haken, immer unter „Ohne" — und dabei EIGENE
   Farben tragen: eine im Ruhezustand, eine andere, wenn sie gewaehlt ist.

   Die Farben sagen, was passiert, und sind nicht bloss Schmuck:

     GRUEN, solange nichts angehakt ist — die Beigabe kommt mit dem Gericht. Gruen ist in diesem
     Haus die Farbe fuer „ist in Ordnung", und dieselbe Farbe trug schon die alte Taste.

     ROT, sobald der Haken sitzt — dann heisst die Zeile „OHNE Beilagen Salat", es wird also
     etwas weggenommen. Waere sie hier gelb wie jedes andere gewaehlte Extra, saehe „ohne Salat"
     aus wie „mit Salat", und der Unterschied entscheidet, was auf dem Kuechenzettel steht.

   Beides muss die allgemeine Regel `.checkbox-option:has(input:checked)` uebersteuern — die
   faerbt jede angehakte Zeile gelb. */
.extra-zeile-beigabe .checkbox-option {
    border-color: var(--djk-success);
    background: rgba(34, 197, 94, .10);
}
.extra-zeile-beigabe .checkbox-box { border-color: var(--djk-success); }

/*
 * ANGEHAKT HEISST „MIT" (03.09.2026) — gruen ist der Normalfall.
 *
 * Bis dahin stand der Haken fuer die Abwahl, und diese Regeln faerbten ihn deshalb rot. Die
 * Bedeutung hat sich im Auswahlfenster gedreht; die Farbe muss mit, sonst leuchtet die Kasse
 * bei jeder ganz normalen Bestellung rot.
 */
.extra-zeile-beigabe .checkbox-option input:checked + .checkbox-box,
.extra-zeile-zutat .checkbox-option input:checked + .checkbox-box {
    border-color: var(--djk-success);
    background: var(--djk-success);
    color: var(--djk-white);
}
/* Abgehakt = weggelassen: rot. */
.extra-zeile-beigabe-aus .checkbox-option,
.extra-zeile-beigabe .checkbox-option:has(input:not(:checked)),
.extra-zeile-zutat .checkbox-option:has(input:not(:checked)) {
    border-color: var(--djk-danger);
    background: rgba(239, 68, 68, .12);
}
.extra-zeile-beigabe-aus .checkbox-box,
.extra-zeile-beigabe .checkbox-option:has(input:not(:checked)) .checkbox-box,
.extra-zeile-zutat .checkbox-option:has(input:not(:checked)) .checkbox-box {
    border-color: var(--djk-danger);
}

/*
 * DAS REZEPT DER BEIGABE — die Zutaten des Salats, jede einzeln abwaehlbar.
 *
 * Eingerueckt und mit einer Linie an der Seite: so ist ohne ein Wort zu sehen, dass diese
 * Haken zur Zeile darueber gehoeren und nicht zum Gericht. Der Abstand ist derselbe wie
 * zwischen den Zeilen der Liste (8px); die Liste ist ein flex-Kasten mit `gap`, deshalb
 * bekommt der Kasten hier KEINEN eigenen margin-top — die beiden Abstaende addierten sich
 * sonst, wie schon einmal auf dem Brett.
 */
.beigabe-rezept {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-left: 18px;
    padding-left: 12px;
    border-left: 2px solid var(--djk-success);
}
.beigabe-rezept-zu { display: none; }

/*
 * DER EIGENE BLOCK DER BEIGABEN (03.09.2026).
 *
 * Eine Linie trennt ihn von den Extras des Gerichts — das ist der Strich, den der Wirt ins
 * Bild gemalt hat. Er steht unter JEDEM Reiter, denn eine Beigabe ist kein „mit" und kein
 * „ohne": sie kommt ohnehin mit, die Frage ist nur, ob der Gast sie will.
 */
.beigaben-block {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--djk-border);
}
.beigaben-block-titel {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--djk-gray);
    margin-bottom: 2px;
}

/*
 * DER WINKEL, DER DAS REZEPT AUF- UND ZUKLAPPT (03.09.2026).
 *
 * Fuenf Zutaten unter jeder Beigabe machten aus einer kurzen Liste eine lange; beim Oeffnen
 * des Fensters ist das Rezept deshalb ZU. Der Knopf ist so hoch wie die Zeile daneben
 * (`align-items: stretch` am Kopf), damit keine zweite Hoehe entsteht.
 */
.beigabe-rezept-schalter {
    flex: 0 0 auto;
    width: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: var(--djk-black-soft);
    color: var(--djk-success);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.beigabe-rezept-schalter:hover { border-color: var(--djk-success); }
.beigabe-rezept-schalter svg { width: 20px; height: 20px; transition: transform var(--transition); }
.beigabe-rezept-schalter.offen svg { transform: rotate(180deg); }

/*
 * Was zugeklappt fehlt — sonst waere die Automatik unsichtbar: der Zettel traegt „ohne
 * Zwiebeln", und im Fenster stuende nur „Beilagen Salat".
 */
.beigabe-ohne-kurz {
    align-self: center;
    font-size: 0.78rem;
    color: var(--djk-danger);
    max-width: 42%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.beigabe-ohne-kurz:empty { display: none; }
/* Kein Salat, keine Frage nach seinen Zutaten. */
.beigabe-kopf-aus .beigabe-rezept-schalter,
.beigabe-kopf-aus .beigabe-ohne-kurz { display: none; }
.extra-zeile-zutat .checkbox-option {
    border-color: var(--djk-success);
    background: rgba(34, 197, 94, .06);
}
.extra-zeile-zutat .checkbox-box { border-color: var(--djk-success); }

.extra-zeile-belegt { opacity: .45; }
.extra-zeile-belegt .checkbox-option { cursor: not-allowed; }
.extra-belegt-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--djk-gray);
    margin-left: 6px;
    white-space: nowrap;
}

/* Alles Gewaehlte auf einen Blick, ueber alle Praefix-Reiter hinweg — dieselbe Zusammenfassung
   wie im Bestell-Dialog der Website. Bewusst RUHIG gehalten: sie meldet einen Stand, sie ist
   kein Bedienelement. Wer hier faerbt wie bei .praefix-btn.active, laesst sie wie etwas
   aussehen, das man antippen kann. */
.picker-extra-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 10px 0 0;
}

.picker-extra-summary-chip {
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    padding: 4px 11px;
    font-size: 0.8rem;
    color: var(--djk-gray);
}

/* Cart lines with sub-details */
.cart-line-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
}

.cart-item-sub {
    font-size: 0.75rem;
    color: var(--djk-gray);
    margin-top: 2px;
    padding-left: 2px;
}

.cart-item-sub-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
}

.cart-item-sub-price { color: var(--djk-yellow); font-weight: 700; flex-shrink: 0; }

.cart-item-comment {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    color: var(--djk-blue-light);
    font-style: italic;
}

.cart-item-vorspeise { color: var(--djk-yellow); font-weight: 700; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; }

.cart-item-comment .icon { width: 18px; height: 18px; flex-shrink: 0; margin-top: 1px; }

.cart-line-total-row {
    display: flex;
    justify-content: space-between;
    font-size: 0.8rem;
    font-weight: 800;
    color: var(--djk-yellow);
    margin-top: 4px;
    padding-top: 4px;
    border-top: 1px dashed var(--djk-border);
}

/* Lock the background from scrolling while any overlay/modal/expanded cart is open */
body.scroll-locked {
    overflow: hidden;
    touch-action: none;
    overscroll-behavior: none;
}

/* Kein Markieren, kein Nachschlagen-Ballon, kein Kontextmenü — im GANZEN Kassenbildschirm.
   Vorher stand hier eine Liste einzelner Bauteile; wer lange auf etwas drückte, das nicht
   darin vorkam (Preis, Kategoriename, freie Fläche), bekam trotzdem die Sprechblase mit
   "Kopieren / Nachschlagen / Übersetzen" — und beim Buchen ist das nur im Weg.
   Umgekehrt aufgezogen ist es zuverlässiger: alles gesperrt, und die Ausnahmen sind genau die
   Stellen, an denen man wirklich Text bearbeitet (die Regel darunter). */
body.kasse-body,
body.kasse-body * {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
.product-tile, .kategorie-tile, .tisch-tile, .cart-line,
.checkbox-option, .beilage-option-btn, .pay-method-btn, .keypad-grid button, .praefix-btn,
.modal-box, .modal-box h3, .modal-box p, .modal-box label, .modal-box .hint {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
    touch-action: manipulation;
}

body.kasse-body input, body.kasse-body textarea, body.kasse-body select,
.modal-box input[type="text"], .modal-box textarea {
    -webkit-user-select: text;
    user-select: text;
    touch-action: auto;
}

/* source/style_css/290_register_big_screen_loading.css - style.css part 41 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Kasse: großer Bildschirm — eigenes Layout statt mobiler Overlays/Bottombar ----------
   Links außen (1/4): Warenkorb oben, die 3 Aktionsbuttons unten (.kasse-bottom-bar), volle Höhe.
   Rechts davon zwei Spalten, unabhängig voneinander oben/unten geteilt:
     Spalte "Auswahl" (25%-47%): oben der Ziffernblock (Zone "Zifferblat", feste Höhe
       --kasse-dial-h — Menge vorwählen), darunter der Warengruppen-Filter (Zone
       "Warengruppen", füllt den Rest der Spalte, eigener Scroll).
     Spalte "Katalog" (47%-100%, die größere): oben die Kategorien als Band (Zone "Kategorien",
       feste Höhe --kasse-catband-h, #kategorieOverlay), darunter die Produkte (Zone "Produkte",
       #kasseProductsSection, füllt den Rest — die größte Fläche des ganzen Bildschirms).
   Alles unterhalb der Suchleiste (74px). Reine CSS-Umschichtung der bestehenden Blöcke (kein
   neues Markup außer #warengruppenRow) — position:fixed ignoriert die tatsächliche
   DOM-Verschachtelung (Ziffernblock und Warengruppen-Filter liegen im Markup beide innerhalb
   von #kategorieOverlay, siehe personal/kasse.php). */
@media (min-width: 1200px) {
    /* Die vier beweglichen Kanten des großen Kassenbildschirms. Werte kommen aus
       Admin → Kasse und werden in personal/kasse.php als :root-Variablen ausgegeben (die
       stehen später im Dokument und gewinnen deshalb gegen diese Vorgaben hier).
       Aufbau von links nach rechts: Bon | Ziffernblock + Warengruppen | Kategorien + Produkte. */
    :root {
        --kasse-catband-h: 260px;   /* Höhe des Kategorien-Bands oben rechts */
        --kasse-dial-h: 360px;      /* Höhe des Ziffernblocks in der mittleren Spalte */
        --kasse-bon-breite: 25%;    /* Breite der Bon-Spalte ganz links */
        --kasse-mitte-breite: 22%;  /* Breite der mittleren Spalte */
    }
    /* Wo der Produktbereich anfängt — ergibt sich aus den beiden Spalten davor, damit die
       Kanten zusammenbleiben, wenn eine davon verschoben wird. */
    :root { --kasse-produkte-links: calc(var(--kasse-bon-breite) + var(--kasse-mitte-breite)); }

    #kategorieOverlay {
        display: block !important;
        position: fixed;
        top: var(--kasse-kopf-h, 74px);
        left: var(--kasse-produkte-links);
        right: 0;
        height: var(--kasse-catband-h);
        z-index: 40;
        padding: 14px 16px 12px;
        border-bottom: 1px solid var(--djk-border);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    #kategorieOverlay .kategorie-overlay-header { margin-bottom: 10px; }
    #kategorieOverlay .kategorie-overlay-header .modal-close { display: none; }
    /* Kachelbreite und Gummi kommen aus Admin → Kasse → Ansicht (personal/kasse.php gibt die
       Variablen aus). Die Vorgabe hier ist der alte feste Wert. */
    #kategorieOverlay .kategorie-overlay-grid {
        grid-template-columns: repeat(auto-fill, minmax(var(--kasse-kategorie-min, 90px), var(--kasse-kategorie-dehnung, 1fr)));
    }

    #kasseProductsSection {
        position: fixed;
        top: calc(var(--kasse-kopf-h, 74px) + var(--kasse-catband-h));
        right: 0;
        left: var(--kasse-produkte-links);
        bottom: 0;
        margin: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding: 16px 20px 30px;
    }
    #kasseProductsSection .container-wide { max-width: none; margin: 0; padding: 0; padding-bottom: 0; }
    #kasseProductsSection .product-grid {
        grid-template-columns: repeat(auto-fill, minmax(var(--kasse-produkt-min, 130px), var(--kasse-produkt-dehnung, 1fr)));
    }

    /* Ziffernblock: eigene feste Box oben in der linken Spalte, in fester Höhe (kein DOM-Umbau
       nötig — position:fixed positioniert relativ zum Viewport, unabhängig davon, dass das
       Element im Markup noch innerhalb von #kategorieOverlay steht). */
    .kasse-dial-panel {
        position: fixed;
        top: var(--kasse-kopf-h, 74px);
        left: var(--kasse-bon-breite);
        width: var(--kasse-mitte-breite);
        height: var(--kasse-dial-h);
        z-index: 40;
        display: flex;
        flex-direction: column;
        /* stretch statt flex-end: die Teile teilen sich die Höhe des Blocks, statt sich unten
           zu sammeln und oben Luft zu lassen. Erst dadurch passt sich der Ziffernblock an,
           wenn der Bildschirm niedriger ist oder die Höhe in Admin → Kasse geändert wird. */
        justify-content: stretch;
        gap: 8px;
        padding: 16px;
        border-right: 1px solid var(--djk-border);
        border-bottom: 1px solid var(--djk-border);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* Warengruppen-Filter: darunter, füllt den Rest der linken Spalte. Zwei Knöpfe
       nebeneinander statt untereinander — so bleiben auch bei vielen Warengruppen alle
       ohne Scrollen sichtbar. */
    .warengruppen-row {
        display: grid;
        grid-template-columns: repeat(var(--kasse-wg-spalten, 2), 1fr);
        align-content: start;
        /* Reihen zwischen 48 und 104px: bei vielen Warengruppen rücken sie zusammen, statt
           unten aus der Spalte zu laufen; bei wenigen bleiben sie groß genug zum Antippen,
           ohne auf halbe Spaltenhöhe aufzugehen. Die festen 30px Innenabstand des Knopfes
           (siehe .warengruppe-chip) konnten beides nicht. Spaltenzahl und beide Höhen sind
           seit 07.08.2026 einstellbar (Admin → Kasse → Ansicht); die Werte hier sind die alten. */
        grid-auto-rows: minmax(var(--kasse-wg-h-min, 48px), var(--kasse-wg-h-max, 104px));
        gap: 6px;
        position: fixed;
        top: calc(var(--kasse-kopf-h, 74px) + var(--kasse-dial-h));
        left: var(--kasse-bon-breite);
        width: var(--kasse-mitte-breite);
        bottom: 0;
        z-index: 40;
        padding: 12px 16px;
        border-right: 1px solid var(--djk-border);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    /* Die Höhen sind Anteile, keine festen Pixel: STORNO/Art.-Nr. bekommen etwa eine
       Tastenreihe, das Zifferngitter vier. Verändert sich die Höhe des Blocks — anderer
       Bildschirm oder anderer Wert in Admin → Kasse —, wachsen und schrumpfen alle
       gemeinsam, statt dass unten etwas herausfällt.
       `min-height: 0` ist dabei Pflicht: ohne das weigern sich Flex-Kinder, unter ihre
       Inhaltsgröße zu schrumpfen, und genau dann läuft der Block über. */
    /* Der Knopf füllt seine Rasterzeile aus, statt seine Höhe über einen festen Innenabstand
       selbst zu bestimmen — sonst hilft die Begrenzung der Zeile oben nichts. */
    .warengruppen-row .warengruppe-chip {
        height: 100%;
        padding: 6px;
        display: flex;
        align-items: center;
        justify-content: center;
        line-height: 1.25;
    }

    .kasse-dial-topbtns { display: flex; gap: 6px; flex: 1.15 1 0; min-height: 40px; }
    .kasse-dial-topbtns .btn {
        flex: 1 1 50%;
        min-height: 0;
        padding: 4px 6px;
        /* Schrift wächst ein Stück mit der Bildschirmhöhe, bleibt aber in lesbaren Grenzen. */
        font-size: clamp(0.7rem, 1.1vh + 0.28rem, 0.92rem);
    }
    .kasse-dial-display {
        background: var(--djk-black-soft);
        border: 1px solid var(--djk-border);
        border-radius: 5px;
        padding: 10px;
        text-align: center;
        font-size: 1.3rem;
        font-weight: 700;
        color: var(--djk-white);
        min-height: 24px;
        letter-spacing: 2px;
    }
    .kasse-dial-display.has-value { border-color: var(--djk-yellow); }
    .kasse-dial-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        /* Vier gleich hohe Reihen, die sich den Platz teilen — die Tastenhöhe ergibt sich
           daraus und steht nicht mehr fest im Stylesheet. */
        grid-auto-rows: 1fr;
        gap: 6px;
        flex: 4 1 0;
        /* Untergrenze statt 0: vier Reihen à 38px plus Lücken. Wird die Blockhöhe in
           Admin → Kasse sehr klein gestellt oder ist der Bildschirm sehr niedrig, schrumpfen
           die Tasten sonst rechnerisch auf 16px — mit dem Finger nicht mehr zu treffen.
           Ab hier scrollt lieber der Block (overflow-y steht oben), als dass die Kasse
           unbedienbar wird. */
        min-height: 170px;
    }
    .kasse-dial-btn {
        background: var(--djk-black-soft);
        border: 1px solid var(--djk-border);
        border-radius: 5px;
        color: var(--djk-white);
        /* Ziffern skalieren mit der Bildschirmhöhe statt bei 1.1rem festzukleben. */
        font-size: clamp(0.85rem, 1.7vh, 1.3rem);
        font-weight: 600;
        /* Kein Innenabstand mehr: die Höhe kommt aus der Rasterzeile. Ein fester Wert addierte
           sich zur Zeilenhöhe und schob den Block über den unteren Rand. (Alten Wert absichtlich
           nicht zitiert — eine Suche danach soll keine Treffer mehr liefern.) */
        padding: 0;
        min-height: 0;
        cursor: pointer;
        transition: background var(--transition), border-color var(--transition);
    }
    .kasse-dial-btn:hover { background: var(--djk-border); }
    .kasse-dial-btn-muted { color: var(--djk-gray); font-size: 0.9rem; }
    /* Im Ruhezustand wie jede andere Taste — nur der Rand in der Akzentfarbe sagt, dass sie
       etwas anderes tut als eine Ziffer. Vorher war sie flächig eingefärbt und trug zwei
       Wörter; im Ziffernblock sah das aus wie ein Fremdkörper.
       Schriftgröße, Grund und Farbe kommen jetzt von .kasse-dial-btn — deshalb steht hier
       nichts davon mehr. */
    .kasse-dial-btn-menge { border-color: var(--djk-yellow); font-weight: 700; }
    /* Gefüllt, sobald eine Menge vorgewählt ist. Das ist die EINZIGE Rückmeldung an der Taste
       selbst, seit die Aufschrift nicht mehr wechselt — zusammen mit dem "3x" im Anzeigefeld
       darüber. */
    .kasse-dial-btn-menge.active {
        background: var(--djk-yellow);
        border-color: var(--djk-yellow);
        color: #ffffff;
    }

    .kasse-bottom-bar {
        position: fixed;
        top: var(--kasse-kopf-h, 74px);
        left: 0;
        right: auto;
        width: var(--kasse-bon-breite);
        bottom: 0;
        z-index: 45;
        display: flex;
        flex-direction: column;
        border-top: none;
        border-right: 1px solid var(--djk-border);
        border-radius: 0;
        box-shadow: none;
        padding: 14px 16px;
    }
    .kasse-cart-summary { cursor: default; flex: 0 0 auto; }
    /* Auf dem grossen Kassenbildschirm gibt es kein Auf- und Zuklappen: die Liste steht immer
       da, und die Summe steht neben der Tischnummer. Die grosse Summe der schmalen Ansicht
       wuerde hier nur eine der fuenf Flaechen wegnehmen, die der Wirt sich eingeteilt hat. */
    .kasse-summe-gross { display: none; }
    #cartList {
        display: block !important;
        flex: 1 1 auto;
        /*
         * OHNE DIESE ZEILE SCHRUMPFT SIE NICHT.
         *
         * Ein Flex-Kind hat `min-height: auto` — darunter geht es nicht, auch mit
         * `flex-shrink: 1` nicht. Die Liste behielt ihre volle Inhaltshoehe und schob
         * die Knopfreihe 38 px unter den Bildschirmrand (gemessen 22.08.2026; genau
         * das hatte der Wirt auf dem Foto eingekringelt).
         */
        min-height: 0;
        max-height: none;
        overflow-y: auto;
        overscroll-behavior: contain;
        margin: 8px 0 14px;
        /* Hier wird nichts bewegt — sonst zappelte die Spalte bei jedem Neuzeichnen. */
        opacity: 1;
        transform: none;
        transition: none;
    }
    .kasse-bottom-actions {
        flex: 0 0 auto;
        flex-wrap: nowrap;
        flex-direction: column;
        padding-bottom: 0;
        /* Und das Gegengewicht dazu. Ohne diese Zeile belegt die Reihe 52 px weniger,
           als sie hoch ist, und haengt 38 px unter dem Bildschirmrand — die Polsterung,
           die sie ausgleichen soll, gibt es hier gar nicht. */
        margin-bottom: 0;
    }
    .kasse-bottom-actions .btn { flex: 0 0 auto; min-width: 0; padding: 14px 8px; font-size: 0.9rem; white-space: normal; }
    /* Kategorien und Warengruppen sind auf dem großen Bildschirm dauerhaft als eigene Spalten
       sichtbar — beide Buttons sind dort überflüssig, anders als auf Mobil (siehe
       .kasse-bottom-actions oben). */
    #kategorienBtn, #warengruppenBtnMobile { display: none; }
}

/* ---------- Globales Lade-Overlay (assets/js/loading-overlay.js) ---------- */
.djk-loading-overlay {
    position: fixed;
    inset: 0;
    background: rgba(10, 20, 33, 0.6);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 99999;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
    padding: 20px;
}
.djk-loading-overlay.active { opacity: 1; pointer-events: all; }

.djk-loading-box {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    padding: 28px 36px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    box-shadow: var(--shadow);
    max-width: 320px;
}

.djk-loading-spinner {
    width: 42px;
    height: 42px;
    border: 4px solid rgba(59, 130, 246, 0.25);
    border-top-color: var(--djk-yellow);
    border-radius: 50%;
    animation: djk-spin 0.8s linear infinite;
    flex-shrink: 0;
}
@keyframes djk-spin { to { transform: rotate(360deg); } }

.djk-loading-text {
    color: var(--djk-white);
    font-weight: 600;
    font-size: 0.92rem;
    text-align: center;
    line-height: 1.4;
}

.product-tile img, .kategorie-tile img, .tisch-tile img {
    -webkit-user-drag: none;
    pointer-events: none;
}

/* source/style_css/300_reservations.css - style.css part 42 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Reservierungen ---------- */
.reservierungen-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.reserv-kalender-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}

.reserv-kalender-monat {
    font-weight: 800;
    font-size: 1.05rem;
    color: var(--djk-white);
    text-align: center;
    flex: 1;
}

.reserv-kalender-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
    margin-bottom: 6px;
    text-align: center;
    color: var(--djk-gray);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
}

.reserv-kalender-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
    margin-bottom: 22px;
}

.reserv-kalender-day {
    position: relative;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    color: var(--djk-white);
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}

.reserv-kalender-day:hover { background: var(--djk-black-soft); border-color: var(--djk-yellow); }
.reserv-kalender-day-empty { background: none; border: none; cursor: default; }
.reserv-kalender-day-today { border-color: var(--djk-yellow); color: var(--djk-yellow); }
.reserv-kalender-day-selected { background: var(--djk-yellow); border-color: var(--djk-yellow); color: var(--djk-black); }
.reserv-kalender-day-selected:hover { background: var(--djk-yellow); }

.reserv-kalender-day-badge {
    position: absolute;
    bottom: 3px;
    right: 3px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--djk-yellow);
    color: var(--djk-black);
    font-size: 0.62rem;
    font-weight: 800;
    display: flex;
    align-items: center;
    justify-content: center;
}
.reserv-kalender-day-selected .reserv-kalender-day-badge { background: var(--djk-black); color: var(--djk-yellow); }

/* Tag mit noch unbestätigten Online-Anfragen: bleibt auffällig gelb mit weisser Zahl, bis das
   Personal jede Anfrage bestätigt oder abgesagt hat. Der ausgewählte Tag ist sonst ebenfalls
   gelb — damit beides unterscheidbar bleibt, hat der offene Tag weisse statt schwarzer Ziffern
   und der ausgewählte zusätzlich einen Ring. */
.reserv-kalender-day-offen,
.reserv-kalender-day-offen:hover {
    background: #f59e0b;
    border-color: #f59e0b;
    color: #ffffff;
}
.reserv-kalender-day-offen .reserv-kalender-day-num { color: #ffffff; font-weight: 800; }
.reserv-kalender-day-offen.reserv-kalender-day-selected { box-shadow: 0 0 0 2px var(--djk-yellow) inset; }
/* Auf dem orangen Grund wäre das gelbe Badge kaum zu lesen. */
.reserv-kalender-day-offen .reserv-kalender-day-badge { background: #ffffff; color: #b45309; }

/* Abgesagte Reservierungen: Anzahl unten links, roter Kreis mit weisser Schrift —
   bewusst die andere Ecke als die bestätigten (unten rechts), damit man beide
   Zahlen auf einen Blick auseinanderhält. */
.reserv-kalender-day-badge-ab {
    right: auto;
    left: 3px;
    background: #dc2626;
    color: #ffffff;
}
.reserv-kalender-day-selected .reserv-kalender-day-badge-ab,
.reserv-kalender-day-offen .reserv-kalender-day-badge-ab {
    background: #dc2626;
    color: #ffffff;
}

.reserv-tag-panel {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    padding: 16px;
}

.reserv-tag-panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.reserv-eintrag {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px;
    background: var(--djk-black-soft);
    border-radius: 8px;
    margin-bottom: 8px;
}

.reserv-eintrag-zeit {
    font-weight: 800;
    color: var(--djk-yellow);
    font-size: 0.95rem;
    min-width: 52px;
    text-align: center;
}

.reserv-eintrag-body { flex: 1; min-width: 0; }
.reserv-eintrag-name { font-weight: 700; color: var(--djk-white); }
.reserv-eintrag-nummer { color: var(--djk-gray); font-weight: 500; font-size: 0.78rem; }
.reserv-eintrag-meta { color: var(--djk-gray); font-size: 0.82rem; margin-top: 2px; }

.reserv-eintrag-clickable { cursor: pointer; transition: background var(--transition), border-color var(--transition); border: 1px solid transparent; }
.reserv-eintrag-clickable:hover { background: var(--djk-black-card); border-color: var(--djk-yellow); }

/* Reservierung für heute, deren Uhrzeit noch nicht erreicht ist — hebt sich farblich ab, bis sie
   automatisch (nach Ablauf der Zeit) in die Historie wandert. */
.reserv-eintrag-heute { background: rgba(76, 175, 80, 0.14); border-color: rgba(76, 175, 80, 0.5); }
.reserv-eintrag-heute .reserv-eintrag-zeit { color: var(--djk-success); }
.reserv-eintrag-heute:hover { background: rgba(76, 175, 80, 0.22); }

.reserv-eintrag-abgesagt { opacity: 0.6; }
.reserv-eintrag-abgesagt .reserv-eintrag-name { text-decoration: line-through; }

/* Online eingegangen, wartet noch auf Bestätigung/Ablehnung durchs Personal. */
.reserv-eintrag-unbestaetigt { background: rgba(245, 158, 11, 0.14); border-color: rgba(245, 158, 11, 0.5); }
.reserv-eintrag-unbestaetigt:hover { background: rgba(245, 158, 11, 0.22); }

.reserv-eintrag-tag {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--djk-danger);
    color: #fff;
    font-size: 0.66rem;
    font-weight: 800;
    text-decoration: none;
    vertical-align: middle;
    margin-left: 4px;
}
.reserv-eintrag-tag-unbestaetigt { background: #f59e0b; }

.reserv-liste-toolbar { margin-bottom: 16px; }
.reserv-liste-search { width: 100%; }

.reserv-liste-search input {
    width: 100%;
    padding: 14px 42px 14px 44px;   /* Symbol links, Löschkreuz rechts */
    font-size: 1rem;
}
.reserv-liste-search input::placeholder { color: var(--djk-gray); }
.reserv-liste-search .input-icon-glyph { left: 16px; }
.reserv-liste-search .input-icon-glyph .icon { width: 20px; height: 20px; }
.reserv-liste-search .password-toggle { right: 10px; }

@media (max-width: 780px) {
    .reserv-kalender-day { font-size: 0.8rem; }
    .reserv-eintrag { flex-wrap: wrap; }
    .reserv-eintrag-zeit { min-width: auto; }
}

/* Kasse: Hinweis, dass eine Bestellung/Zahlung wegen schwacher Verbindung noch in der lokalen
   Outbox wartet und automatisch nachgesendet wird (siehe assets/js/kasse.js sendResilient). */
.outbox-badge {
    display: none;
    position: fixed;
    left: 50%;
    bottom: 14px;
    transform: translateX(-50%);
    z-index: 9000;
    align-items: center;
    gap: 8px;
    background: #2a1f00;
    color: var(--djk-yellow);
    border: 1px solid var(--djk-yellow);
    border-radius: var(--radius);
    padding: 8px 16px;
    font-size: 0.85rem;
    font-weight: 700;
    box-shadow: 0 4px 16px rgba(0,0,0,0.35);
}
.outbox-badge-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--djk-yellow);
    animation: outboxPulse 1.2s ease-in-out infinite;
}
/* Ohne Verbindung: dieselbe Sprechblase, andere Aussage — sie sagt dann, wie viel auf
   diesem Gerät liegt und auf das Netz wartet. */
.outbox-badge.kein-netz {
    background: #3a0d0d;
    color: #fecaca;
    border-color: var(--djk-danger);
}
.outbox-badge.kein-netz .outbox-badge-dot { background: var(--djk-danger); }
@keyframes outboxPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
}

/* MwSt-Auswahl im Admin (Kategorie- und Produkt-Formular): Schnellwahl 0/7/19 plus freies
   Eingabefeld für abweichende Sätze. Die Presets schreiben nur in das Feld — gespeichert wird
   immer der Feldwert (siehe parse_mwst_satz()). */
.mwst-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.mwst-preset {
    padding: 8px 14px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.mwst-preset:hover { border-color: var(--djk-yellow); }
.mwst-preset.active { background: var(--djk-yellow); border-color: var(--djk-yellow); color: #ffffff; }
.mwst-input {
    width: 92px;
    padding: 8px 10px;
    font-size: 0.9rem;
    font-weight: 600;
    text-align: center;
}

/* ---------------------------------------------------------------- Warengruppen
   Eigene Klassen statt admin-mini-card: dessen Raster ist auf schmale Kacheln
   (minmax 160px) und zentrierten Text ausgelegt. Eine Warengruppe zeigt aber eine
   Liste von Kategorien — die wurde dort zu einer hohen, mittig gebrochenen
   Textsäule. Hier deshalb breite Karten, linksbündig, Kategorien als Chips. */
.wg-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 14px;
    margin-bottom: 16px;
}

.wg-card {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    text-align: left;
    box-shadow: var(--shadow);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.wg-card:hover {
    border-color: var(--djk-yellow);
    box-shadow: 0 6px 20px rgba(37, 99, 235, 0.12);
}

.wg-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.wg-name {
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--djk-white);
    line-height: 1.2;
}

/* Der Steuersatz ist die eigentliche Aussage der Karte — als Pille hervorgehoben. */
.wg-satz {
    flex-shrink: 0;
    background: var(--djk-sidebar-bg-active);
    color: var(--djk-yellow-dark);
    border: 1px solid rgba(37, 99, 235, 0.25);
    border-radius: 999px;
    padding: 4px 12px;
    font-size: 0.8rem;
    font-weight: 800;
    white-space: nowrap;
}

/* Kennzeichnet die Warengruppe, mit der die Kasse beim Anmelden/Tisch-Wechsel startet
   (siehe warengruppen.ist_standard, applyDefaultWarengruppe() in kasse.js). */
.wg-standard-badge {
    align-self: flex-start;
    background: var(--djk-yellow);
    color: #ffffff;
    border-radius: 999px;
    padding: 3px 10px;
    font-size: 0.68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .03em;
}

.wg-kats {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.wg-kat {
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    padding: 4px 10px;
    font-size: 0.74rem;
    color: var(--djk-gray);
    white-space: nowrap;
}

.wg-leer {
    font-size: 0.78rem;
    color: var(--djk-gray);
    font-style: italic;
}

/* Knöpfe unten bündig, egal wie viele Kategorien die Karte darüber hat. */
.wg-actions {
    display: flex;
    gap: 8px;
    margin-top: auto;
    padding-top: 4px;
}

.wg-actions > * { flex: 1 1 0; margin: 0; min-width: 0; }
.wg-actions form { display: flex; }
.wg-actions .btn { width: 100%; padding: 8px 6px; font-size: 0.78rem; }

@media (max-width: 640px) {
    .wg-grid { grid-template-columns: 1fr; gap: 12px; }
    .wg-card { padding: 14px; }
}

/* source/style_css/305_reservations_continued.css - style.css: reservations continued, part 43 of 78 (built by werkzeuge/parts_build.php) */
/* Steuersatz je Tischkategorie: Umschalter oben, darunter alle Warengruppen */
.wg-tk-block {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 18px;
    margin-bottom: 18px;
    box-shadow: var(--shadow);
}
.wg-tk-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.wg-tk-tab {
    text-decoration: none;
    padding: 8px 16px;
    border-radius: 999px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-gray);
    font-size: 0.84rem;
    font-weight: 700;
    transition: all var(--transition);
}
.wg-tk-tab:hover { border-color: var(--djk-yellow); color: var(--djk-yellow-dark); }
.wg-tk-tab.active {
    background: var(--djk-yellow);
    border-color: var(--djk-yellow);
    color: #ffffff;
}
.wg-tk-basis { flex: 0 0 auto; font-size: 0.74rem; color: var(--djk-gray); }
.wg-tk-form { margin: 0; }

/* Steuersatz-Matrix je Tischkategorie im Warengruppen-Formular */
.wg-tk-liste { display: flex; flex-direction: column; gap: 6px; }
.wg-tk-zeile {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 6px 10px;
}
.wg-tk-name { flex: 1 1 auto; font-size: 0.82rem; font-weight: 600; color: var(--djk-white); }
.wg-tk-zeile .mwst-input { flex: 0 0 90px; width: 90px; text-align: right; }
.wg-tk-einheit { flex: 0 0 auto; font-size: 0.8rem; color: var(--djk-gray); }

/* source/style_css/310_qr_scanner_shop_discounts.css - style.css part 44 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------------------------------------------------------------- QR-Scanner (Kasse)
   Der Gast zeigt den Code aus seiner Bestätigungs-Mail, das Personal scannt ihn und landet
   direkt bei der Reservierung bzw. Bestellung. */
.qr-scan-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1200;
    background: rgba(0, 0, 0, 0.75);
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.qr-scan-overlay.active { display: flex; }
.qr-scan-box {
    position: relative;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 14px;
    padding: 22px;
    width: 100%;
    max-width: 420px;
    max-height: 92vh;
    overflow-y: auto;
}
.qr-scan-titel { margin: 0 0 14px; font-size: 1.05rem; }
.qr-scan-video-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 1;
    background: #000;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 12px;
}
#qrScanVideo { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Zielrahmen: hilft dem Personal, den Code mittig zu halten. */
.qr-scan-rahmen {
    position: absolute;
    inset: 18%;
    border: 3px solid rgba(255, 255, 255, 0.85);
    border-radius: 10px;
    pointer-events: none;
}
.qr-scan-status { font-size: 0.88rem; color: var(--djk-gray); text-align: center; margin-bottom: 10px; }
.qr-scan-status-ok { color: #16a34a; font-weight: 700; }
.qr-scan-status-fehler { color: #dc2626; font-weight: 700; }
.qr-scan-treffer {
    background: rgba(22, 163, 74, 0.12);
    border: 1px solid rgba(22, 163, 74, 0.4);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 12px;
}
.qr-scan-treffer-titel { font-weight: 800; color: var(--djk-white); }
.qr-scan-treffer-zeile { font-size: 0.84rem; color: var(--djk-gray); margin-top: 3px; }
.qr-scan-treffer-nummer { font-size: 0.76rem; color: var(--djk-gray); margin-top: 3px; }
.qr-scan-manuell { border-top: 1px solid var(--djk-border); padding-top: 14px; }
.qr-scan-manuell label { display: block; font-size: 0.78rem; color: var(--djk-gray); margin-bottom: 6px; }
.qr-scan-manuell-zeile { display: flex; gap: 8px; }
.qr-scan-manuell-zeile input { flex: 1; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
/* Klartext-Diagnose im Scanner-Fenster: nennt beim Fehlschlag die konkrete Ursache. */
.qr-scan-diagnose {
    font-size: 0.72rem;
    color: var(--djk-gray);
    background: var(--djk-black-soft);
    border-radius: 8px;
    padding: 8px 10px;
    margin-bottom: 12px;
    line-height: 1.6;
}
/* Vom QR-Scanner angesteuerte Online-Bestellung kurz hervorheben. */
.admin-mini-card.ob-treffer {
    border-color: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, .28);
    animation: obTreffer 1s ease-in-out 2;
}
@keyframes obTreffer {
    0%, 100% { box-shadow: 0 0 0 3px rgba(245, 158, 11, .28); }
    50%      { box-shadow: 0 0 0 7px rgba(245, 158, 11, .12); }
}

/* --- Shop-Verfügbarkeit ---------------------------------------------------------------- */
/* Tagesschalter auf der Produktkachel: "steht gerade im Bestell-Shop". */
.produkt-shop-schalter {
    display: flex; align-items: center; gap: 8px;
    margin: 8px 0 4px; padding: 6px 8px; cursor: pointer;
    border-radius: 5px; background: rgba(255, 255, 255, .05);
}
.produkt-shop-schalter input { position: absolute; opacity: 0; pointer-events: none; }
.produkt-shop-schalter-spur {
    flex: 0 0 auto; width: 34px; height: 19px; border-radius: 999px;
    background: #94a3b8; position: relative; transition: background .15s ease;
}
.produkt-shop-schalter-spur::after {
    content: ''; position: absolute; top: 2px; left: 2px; width: 15px; height: 15px;
    border-radius: 50%; background: #fff; transition: transform .15s ease;
}
.produkt-shop-schalter input:checked + .produkt-shop-schalter-spur { background: #16a34a; }
.produkt-shop-schalter input:checked + .produkt-shop-schalter-spur::after { transform: translateX(15px); }
.produkt-shop-schalter input:focus-visible + .produkt-shop-schalter-spur { outline: 2px solid var(--djk-yellow); outline-offset: 2px; }
.produkt-shop-schalter-text { font-size: 0.7rem; font-weight: 700; color: var(--djk-gray); }
.produkt-shop-hinweis { margin: 8px 0 4px; font-size: 0.66rem; color: var(--djk-gray); opacity: .75; }

/* Ausgeschaltetes Gericht bleibt sichtbar, tritt aber deutlich zurück. */
.admin-produkt-card.produkt-aus { opacity: .55; }
.admin-produkt-card.produkt-aus .product-tile-photo { filter: grayscale(1); }
.admin-produkt-card.produkt-aus .produkt-shop-schalter-text { color: #dc2626; }
.admin-produkt-card.produkt-aus .produkt-shop-schalter-text::after { content: ' — aus'; }

/* Warengruppen-Liste im Bestellungen-Reiter "Speisekarte". */
.shop-kat-liste { display: flex; flex-direction: column; gap: 6px; }
.shop-kat-zeile {
    display: flex; align-items: center; gap: 10px; cursor: pointer;
    padding: 10px 12px; border-radius: 5px;
    border: 1px solid var(--djk-border); background: var(--djk-black-soft);
    transition: border-color .15s ease, background .15s ease;
}
.shop-kat-zeile:hover { border-color: var(--djk-gray); }
.shop-kat-zeile.aktiv { border-color: #16a34a; background: rgba(22, 163, 74, .08); }
.shop-kat-zeile input { width: 17px; height: 17px; accent-color: #16a34a; flex: 0 0 auto; }
.shop-kat-punkt { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.shop-kat-name { font-weight: 700; font-size: 0.9rem; flex: 1 1 auto; }
.shop-kat-zahl { font-size: 0.72rem; color: var(--djk-gray); white-space: nowrap; }
@media (max-width: 560px) {
    .shop-kat-zahl { font-size: 0.66rem; }
}

/* Gesperrtes Produkt: sichtbar, damit der Service weiß, dass es das Gericht gibt —
   aber grau und nicht antippbar (Admin → Produkte → Schalter "Bestellbar"). */
.product-tile[data-gesperrt="1"] {
    position: relative;
    filter: grayscale(1);
    opacity: .5;
    cursor: not-allowed;
}
.product-tile[data-gesperrt="1"]::after {
    /* Das Wort kommt aus der Sprache der Kasse (personal/kasse.php, --kachel-gesperrt-wort). */
    content: var(--kachel-gesperrt-wort, 'gesperrt');
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) rotate(-8deg);
    background: rgba(20, 20, 20, .82);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: 4px;
    pointer-events: none;
}

/* Verwaltung: Produkt ist sichtbar, aber gesperrt (Schalter "Bestellbar" aus). */
.admin-produkt-card.produkt-gesperrt { outline: 2px dashed rgba(200, 80, 40, .55); outline-offset: -2px; }
.admin-produkt-card.produkt-gesperrt .admin-produkt-price { text-decoration: line-through; }

/* Schlichte Datentabelle (Verwaltung → Aktionen → Rabatte). */
.admin-table-wrap {
    overflow-x: auto;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
}
.admin-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.admin-table th {
    text-align: left;
    font-size: 0.68rem;
    letter-spacing: .07em;
    text-transform: uppercase;
    opacity: .7;
    padding: 11px 12px;
    border-bottom: 1px solid var(--djk-border);
    white-space: nowrap;
}
.admin-table td { padding: 11px 12px; border-bottom: 1px solid var(--djk-border); vertical-align: middle; }
.admin-table tr:last-child td { border-bottom: 0; }
.admin-toggle { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }

/* ---------- Aktionen → Rabatte ---------- */
.rabatt-kopf { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.rabatt-kopf-zahl { font-size: 0.82rem; opacity: .65; }

.rabatt-form { padding: 0; overflow: hidden; }
.rabatt-form-kopf { padding: 18px 20px 14px; border-bottom: 1px solid var(--djk-border); }
.rabatt-form-kopf h3 { margin: 0 0 6px; font-size: 1.05rem; }
.rabatt-form-kopf .hint { margin: 0; }

.rabatt-abschnitt { padding: 16px 20px; border-bottom: 1px solid var(--djk-border); }
.rabatt-abschnitt-titel {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700;
    font-size: 0.9rem;
    margin-bottom: 12px;
}
.rabatt-abschnitt-titel > span:first-child {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 5px;
    background: var(--djk-yellow, #2563eb);
    color: #fff;
    font-size: 0.74rem;
}

.rabatt-raster { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 14px 18px; }
.rabatt-feld { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.rabatt-feld > span:first-child { font-size: 0.82rem; font-weight: 600; }
.rabatt-feld input,
.rabatt-feld select { width: 100%; }
.rabatt-feld .hint { font-size: 0.75rem; }
.rabatt-feld-breit { grid-column: 1 / -1; }

.rabatt-wert-zeile { display: flex; align-items: center; gap: 8px; }
.rabatt-wert-zeile input { flex: 1; min-width: 0; }
.rabatt-einheit {
    flex: 0 0 auto;
    min-width: 34px;
    text-align: center;
    font-weight: 700;
    opacity: .7;
}
.rabatt-code { text-transform: uppercase; }
.rabatt-code::placeholder { text-transform: none; }

/* source/style_css/320_discount_targets.css - style.css part 45 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---- Auswahl: worauf der Rabatt gilt ----
   Achtung Spezifität: ".field label" (0,1,1) und ".rabatt-feld input" (0,1,1) stehen weiter oben
   und würden eine einfache Klasse (0,1,0) schlagen — dann steht der Haken über dem Text und ist
   über die ganze Breite gezogen. Deshalb hier durchgehend zweistufige Selektoren. */
.rabatt-ziel-block { min-width: 0; }

.rabatt-wahl-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.rabatt-wahl-titel {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--djk-yellow);
}
.rabatt-wahl-werkzeug { display: flex; align-items: center; gap: 8px; }
.rabatt-zaehler {
    font-size: 0.76rem;
    color: var(--djk-gray);
    font-variant-numeric: tabular-nums;
}
.rabatt-mini {
    border: 1px solid var(--djk-border);
    background: transparent;
    color: var(--djk-gray);
    border-radius: 999px;
    padding: 4px 11px;
    font-size: 0.74rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background var(--transition);
}
.rabatt-mini:hover { border-color: var(--djk-yellow); color: var(--djk-yellow-dark); background: var(--djk-sidebar-bg-active); }

/* Ein Kasten statt eines nackten Satzes — sonst wirkt "alle Produkte" wie ein vergessenes Feld. */
.rabatt-hinweis {
    border: 1px dashed var(--djk-border);
    border-radius: 8px;
    background: var(--djk-black-soft);
    padding: 14px 16px;
    font-size: 0.85rem;
    color: var(--djk-gray);
    line-height: 1.5;
}
.rabatt-hinweis strong { color: var(--djk-white); display: block; margin-bottom: 2px; }

/* Eigener Haken: der Standard-Kasten ist je nach Browser unterschiedlich groß und lässt sich
   nicht einfärben — hier soll die Auswahl aber auf einen Blick erkennbar sein. */
.rabatt-chips input[type="checkbox"],
.rabatt-produktliste input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin: 0;
    padding: 0;
    position: relative;
    border: 1.5px solid var(--djk-border);
    border-radius: 4px;
    background: var(--djk-black-card);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.rabatt-chips input[type="checkbox"]:checked,
.rabatt-produktliste input[type="checkbox"]:checked {
    background: var(--djk-yellow-dark);
    border-color: var(--djk-yellow-dark);
}
.rabatt-chips input[type="checkbox"]:checked::after,
.rabatt-produktliste input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 5px;
    top: 1px;
    width: 4px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.rabatt-chips input[type="checkbox"]:focus-visible,
.rabatt-produktliste input[type="checkbox"]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
}

/* Gleich breite Kacheln statt einer ausgefransten Reihe. "grid-auto-rows: 1fr" gibt allen
   Reihen die Höhe der höchsten — sonst stünden ein- und zweizeilige Namen ungleich hoch. */
.rabatt-chips {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    grid-auto-rows: 1fr;
    gap: 8px;
}
.rabatt-chips label.rabatt-chip {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 10px 12px;
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    background: var(--djk-black-card);
    color: var(--djk-white);
    font-size: 0.86rem;
    font-weight: 500;
    line-height: 1.25;
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition), box-shadow var(--transition);
}
.rabatt-chips label.rabatt-chip:hover { border-color: var(--djk-yellow); }
.rabatt-chips label.rabatt-chip:has(input:checked) {
    border-color: var(--djk-yellow-dark);
    background: var(--djk-sidebar-bg-active);
    box-shadow: inset 0 0 0 1px var(--djk-yellow-dark);
}
.rabatt-chip-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rabatt-chip-name { font-weight: 600; overflow-wrap: anywhere; }
.rabatt-chip-gruppe { font-size: 0.71rem; font-weight: 400; color: var(--djk-gray); }

/* Produktauswahl: die ganze Karte auf einmal ist zu viel — deshalb Suchfeld und Rollkasten. */
.rabatt-suche { position: relative; margin-bottom: 8px; }
.rabatt-suche svg {
    position: absolute;
    left: 13px;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 17px;
    color: var(--djk-gray);
    pointer-events: none;
}
.rabatt-suche input[type="search"] {
    width: 100%;
    padding: 11px 14px 11px 38px;   /* Lupe links */
    font-size: 0.9rem;
}

.rabatt-produktliste {
    max-height: 340px;
    overflow-y: auto;
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    background: var(--djk-black-card);
    padding: 0 6px 6px;
}
.rabatt-produkt-leer { padding: 22px 10px; text-align: center; color: var(--djk-gray); font-size: 0.85rem; }
.rabatt-produkt-gruppe-titel {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--djk-black-card);
    border-bottom: 1px solid var(--djk-border);
    margin-bottom: 4px;
    padding: 10px 6px 6px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--djk-gray);
}
.rabatt-produktliste label.rabatt-produkt-zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 7px 8px;
    border-radius: 6px;
    color: var(--djk-white);
    font-size: 0.86rem;
    font-weight: 400;
    cursor: pointer;
    transition: background var(--transition);
}
.rabatt-produktliste label.rabatt-produkt-zeile:hover { background: var(--djk-black-soft); }
.rabatt-produktliste label.rabatt-produkt-zeile:has(input:checked) {
    background: var(--djk-sidebar-bg-active);
    font-weight: 600;
}
.rabatt-produkt-name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.rabatt-produkt-preis { flex: 0 0 auto; color: var(--djk-gray); font-variant-numeric: tabular-nums; }

/* Bei vielen Zielen soll die Zelle die Tabelle nicht auseinanderziehen. */
.rabatt-ziel-zelle { max-width: 260px; }

.rabatt-haken { flex-direction: row; align-items: center; gap: 9px; cursor: pointer; }
.rabatt-haken input { width: auto; }
.rabatt-haken > span { font-size: 0.88rem; }

.rabatt-aktionen { display: flex; gap: 10px; padding: 16px 20px; }

/* Schalter in der Liste: An/Aus auf einen Blick, ohne Text zu lesen. */
.rabatt-schalter {
    width: 42px;
    height: 24px;
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    background: rgba(120, 120, 120, .18);
    position: relative;
    cursor: pointer;
    padding: 0;
}
.rabatt-schalter > span {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
    transition: left .15s ease;
}
.rabatt-schalter.an { background: var(--djk-success, #3f8f5c); border-color: transparent; }
.rabatt-schalter.an > span { left: 21px; }
.rabatt-zeile-aus { opacity: .55; }

@media (max-width: 700px) {
    .rabatt-abschnitt,
    .rabatt-form-kopf,
    .rabatt-aktionen { padding-left: 14px; padding-right: 14px; }
    .rabatt-raster { grid-template-columns: 1fr; }
}
.rabatt-raster .field { margin-bottom: 0; }
.rabatt-raster .field label { margin-bottom: 6px; }
.rabatt-haken { flex-direction: row !important; align-items: center; gap: 9px; cursor: pointer; }
.rabatt-haken input { width: auto; }

/* ------------------------------------------------------------------------------------------
   KENNZEICHEN AUF DER PRODUKTKACHEL — „alkoholfrei", „vegetarisch", „scharf", …

   Der Wirt legt sie selbst an (Einstellungen → Kasse → Zeichen & Farben) und schaltet sie bei
   der Kategorie und/oder beim einzelnen Produkt ein. Ecke und Größe gehören dem EINZELNEN
   Kennzeichen und stehen deshalb als Stil am Element, nicht hier: zwei Zeichen auf derselben
   Kachel dürfen verschieden groß in verschiedenen Ecken sitzen.
   ------------------------------------------------------------------------------------------ */
.produkt-kennzeichen {
    position: absolute;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: 4px;
    pointer-events: none;          /* darf den Tipp auf die Kachel nicht schlucken */
    line-height: 0;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45));
    /* Damit das Kürzel ohne Bild mit dem Zeichen wächst (siehe .kennzeichen-text): das Zeichen
       wird zum Maßstab für seinen eigenen Inhalt. Seine Größe steht ja als Stil am Element. */
    container-type: size;
}
.produkt-kennzeichen img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Ohne Bild der Name als Kürzel auf einer Farbfläche — ein Kennzeichen ohne Bild soll nie
   unsichtbar sein, und für „vegetarisch" reicht oft schon ein grüner Fleck mit drei Buchstaben.
   Die Farbe gehört dem EINZELNEN Kennzeichen und steht deshalb als Stil am Element (siehe
   kennzeichen_verlauf()); der Verlauf hier ist nur der Werkswert für alles, was ohne Stil kommt. */
.kennzeichen-text {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: linear-gradient(205deg, rgb(101 102 255 / 40%), rgba(92, 92, 92, .7));
    color: #ffffff;
    /* Zwei Zeilen mit Absicht: die Buchstaben sollen mit dem Zeichen wachsen (38 % seiner
       Breite — drei Großbuchstaben füllen es dann zu gut vier Fünfteln). Kann ein altes Gerät
       die Maßeinheit nicht, bleibt es bei der festen Größe darüber, statt gar nichts zu zeigen. */
    font-size: 0.6rem;
    font-size: 38cqw;
    font-weight: 800;
    line-height: 1;
    letter-spacing: .02em;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
    text-transform: uppercase;
}

/* Die Zeile in der Verwaltung, in der ein Kennzeichen gepflegt wird. */
.kennzeichen-zeile {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) 130px 74px 46px auto auto;
    align-items: center;
    gap: 8px;
    padding: 7px 0;
    border-bottom: 1px solid var(--djk-black-soft);
}
.kennzeichen-zeile:last-of-type { border-bottom: 0; }
.kennzeichen-zeile > * { min-width: 0; }
.kennzeichen-zeile input[type="text"],
.kennzeichen-zeile select { width: 100%; }
.kennzeichen-bild {
    width: 44px;
    height: 44px;
    border: 1px dashed var(--feld-rand);
    border-radius: var(--feld-radius);
    background: var(--feld-grund);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
}
.kennzeichen-bild img { width: 100%; height: 100%; object-fit: contain; }
/* Das Bildfeld mit dem kleinen × zum Entfernen. Das × steht NEBEN dem <label>, nicht darin:
   alles innerhalb eines Labels öffnet beim Klick den Dateiwähler — auch ein Knopf. */
.kennzeichen-bild-feld { position: relative; display: block; width: 44px; height: 44px; }
.kennzeichen-bild-weg {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 1px solid var(--feld-rand);
    border-radius: 50%;
    background: var(--djk-white, #fff);
    color: var(--djk-red, #dc2626);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}
.kennzeichen-bild-weg:hover { background: var(--djk-red, #dc2626); color: #fff; }
.kennzeichen-zeile input[type="color"] { width: 46px; height: 34px; padding: 2px; }
/* Am Telefon drei Zeilen statt einer: Bild und Name oben, die Ecke darunter, zuletzt Größe,
   Farbe, Schalter und Entfernen nebeneinander. */
@media (max-width: 700px) {
    .kennzeichen-zeile { grid-template-columns: 44px minmax(0, 1fr) 46px auto auto; }
    .kennzeichen-zeile input[type="text"]:nth-of-type(1),
    .kennzeichen-zeile select { grid-column: 2 / -1; }
    .kennzeichen-zeile input[type="text"]:nth-of-type(2) { grid-column: 2 / 3; }
    .kennzeichen-zeile input[type="color"] { grid-column: 3 / 4; }
}

/* Ein Bestellterminal in der Verwaltung: Name, Schalter, wann es zuletzt gelebt hat, Entfernen —
   und darunter über die volle Breite die Adresse, die auf dem Gerät hinterlegt wird. */
.terminal-zeile {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    align-items: center;
    gap: 10px;
    padding: 12px 0;
    border-bottom: 1px solid var(--djk-black-soft);
}
.terminal-zeile:last-of-type { border-bottom: 0; }
.terminal-zeile input[type="text"] { width: 100%; }
.terminal-gesehen { font-size: 0.78rem; white-space: nowrap; }
.terminal-adresse {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.terminal-adresse code {
    flex: 1 1 260px;
    min-width: 0;
    padding: 6px 10px;
    border-radius: var(--feld-radius);
    background: var(--feld-grund);
    font-size: 0.75rem;
    word-break: break-all;
}
@media (max-width: 700px) {
    .terminal-zeile { grid-template-columns: minmax(0, 1fr) auto auto; }
    .terminal-gesehen { grid-column: 1 / -1; }
}

/* Aktionspreis auf der Kachel: erst der alte, durchgestrichene Preis, dann der neue. */
.product-tile-price { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }

/* source/style_css/325_discount_targets_continued.css - style.css: discount targets continued, part 46 of 78 (built by werkzeuge/parts_build.php) */
/* ------------------------------------------------------------------------------------------
   DER PREIS STEHT IMMER UNTEN RECHTS — egal, wie groß die Kachel gerade ist.

   Die Kachelgröße kommt aus der Verwaltung (Kasse → Ansicht → „Wie viel passt in einen Block")
   und wächst zusätzlich mit dem Raster. Vorher lief der Preis einfach hinter dem Namen mit:
   bei einer hohen Kachel klebte er mitten in der Fläche, bei einer flachen unten — von Kachel
   zu Kachel woanders, und beim Überfliegen einer Spalte sprang das Auge.

   Gelöst über die Kachel als Spalte plus `margin-top: auto` und NICHT über `position:absolute`:
   so bleibt der Platz für den Preis reserviert. Absolut gesetzt würde er sich bei großer Schrift
   (bis 40px sind einstellbar) über den Produktnamen schieben.

   Nur echte Produktkacheln: Kategorie- und Tischkacheln teilen sich zwar die Klasse, haben aber
   keinen Preis und eigene Anordnungen (die Kategorie im Überblick liegt sogar als Zeile vor). */
.product-tile:not(.kategorie-tile):not(.tisch-tile) {
    display: flex;
    flex-direction: column;
}
.product-tile:not(.kategorie-tile):not(.tisch-tile) .product-tile-name { flex: none; }
.product-tile:not(.kategorie-tile):not(.tisch-tile) .product-tile-price {
    margin-top: auto;
    justify-content: flex-end;
    text-align: right;
}
/* Liegt die Ware im Warenkorb, sitzt unten rechts der Minus-Knopf (36px + 5px Rand). Dann
   rückt der Preis davor, statt darunter zu verschwinden.

   `margin-right` und NICHT `padding-right`: den Innenabstand des Preises setzt weiter oben
   `body.kasse-body #kasseProductsSection .product-tile-price` mit einer ID im Selektor und
   damit ungleich schwerer — ein `padding` hier verlöre den Streit lautlos (dieselbe Ursache
   wie bei der Schriftgröße, die in der Kasse nie ankam). Der Außenabstand steht in diesem
   Streit gar nicht drin. */
.product-tile.in-cart:not(.kategorie-tile):not(.tisch-tile) .product-tile-price {
    margin-right: 41px;
}
/* Der alte Preis steht ÜBER dem neuen, nicht daneben.
   Auf einer Kachel von 150 px ist neben "10,00 €" kein Platz mehr für "12,00 €" — die beiden
   ruecken zusammen und werden zu einer einzigen unlesbaren Zeile. Uebereinander hat jeder
   seine Zeile, und der Blick geht von oben (war) nach unten (ist).

   Keine `opacity` mehr: durchsichtig auf einer farbigen Kachel ergibt eine Farbe, die niemand
   eingestellt hat und die auf hellen Kacheln verschwindet. Durchgestrichen sagt schon alles. */
.product-tile .product-tile-price { flex-direction: column; align-items: flex-end; gap: 0; }
.product-tile .preis-alt {
    text-decoration: line-through;
    color: var(--kasse-preis, inherit);
    font-weight: 600;
    font-size: 0.72rem;
    line-height: 1.15;
}
.product-tile .preis-neu { color: var(--kasse-preis-aktion, var(--djk-danger, #d64545)); }
/* Die Speisenummer rutscht unter die Aktions-Marke. Ohne das liegt die Marke auf ihr, und
   gerade bei einer Aktion will man wissen, WELCHE Nummer man dem Gast nennt. */
.product-tile[data-aktion]:not([data-aktion='']) .product-tile-name { padding-top: 16px; }
.product-tile:not([data-alt-preis='']) .preis-neu { font-weight: 900; }
.product-tile[data-aktion]:not([data-aktion='']) { position: relative; }
.product-tile[data-aktion]:not([data-aktion=''])::before {
    content: attr(data-aktion);
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 2;
    background: var(--djk-danger, #d64545);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 900;
    letter-spacing: .02em;
    padding: 2px 6px;
    border-radius: 5px;
    pointer-events: none;
}

/* source/style_css/330_station_head_vouchers_split_payment.css - style.css part 47 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Kopfzeile des Küche/Bar-Boards mit Bestellstopp-Schalter ---------- */
.board-kopf {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
/* Der Schalter steht rechts außen — dort, wo am Pass die Hand ohnehin hinfährt, und weit genug
   von den Tickets entfernt, dass ihn niemand im Vorbeigehen erwischt. */
.stopp-schalter {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    color: var(--djk-white);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    touch-action: manipulation;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.stopp-schalter:disabled { opacity: .6; cursor: default; }
.stopp-schalter-lampe {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--djk-success, #3f8f5c);
    flex: none;
}
/* Angehalten: rot und deutlich — das ist ein Zustand, den man nicht vergessen darf. */
.stopp-schalter.ist-an {
    background: rgba(214, 69, 69, 0.14);
    border-color: var(--djk-danger);
    color: var(--djk-danger);
}
.stopp-schalter.ist-an .stopp-schalter-lampe {
    background: var(--djk-danger);
    animation: stopp-puls 1.6s ease-in-out infinite;
}
@keyframes stopp-puls {
    0%, 100% { opacity: 1; }
    50% { opacity: .35; }
}
@media (prefers-reduced-motion: reduce) {
    .stopp-schalter.ist-an .stopp-schalter-lampe { animation: none; }
}
/* Nur das Zeichen (26.09.2026): ein runder Knopf mit der Lampe, zwischen Titel und den Wegen
   Kueche/Bar. Die Lampe ist groesser als im Wort-Knopf — sie traegt den Zustand jetzt allein.
   Steht er VOR den Wegen, nimmt er den freien Platz, und die Wege ruecken an ihn heran. */
.stopp-schalter-zeichen { width: 40px; height: 40px; padding: 0; justify-content: center; flex: 0 0 auto; }
.stopp-schalter-zeichen .stopp-schalter-lampe { width: 16px; height: 16px; box-shadow: 0 0 0 3px color-mix(in srgb, var(--djk-success, #3f8f5c) 25%, transparent); }
.stopp-schalter-zeichen.ist-an .stopp-schalter-lampe { box-shadow: 0 0 0 3px color-mix(in srgb, var(--djk-danger) 25%, transparent); }
.board-kopf > :is(.stopp-schalter-zeichen, .stopp-hinweis) + .board-stationen { margin-left: 0; }
.board-kopf.kopf-fest { margin-bottom: 6px; flex-wrap: nowrap; }
.board-kopf.kopf-fest > h2 { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Am Telefon passt der Titel sonst nicht neben Lampe und Wege (gemessen: „Offene Bestellun…“). */
@media (max-width: 520px) {
    .board-kopf.kopf-fest { gap: 8px; }
    .board-kopf.kopf-fest > h2 { font-size: 1.15rem; }
}
/* Wer nur zusehen darf, sieht den Zustand ohne Schalter. */
.stopp-hinweis {
    margin-left: auto;
    padding: 6px 12px;
    border-radius: 999px;
    background: rgba(214, 69, 69, 0.14);
    color: var(--djk-danger);
    font-size: 0.8rem;
    font-weight: 700;
}

/* ---------- Öffnungszeiten für den Rechnungskopf ---------- */
/* Je Zeile ein Wochentagsbereich, darunter beliebig viele Zeitspannen. Bewusst zweistufig:
   die Tage bestimmen die Zeile, die Zeiten hängen daran — in einer Reihe würde beides bei
   drei Spannen unlesbar. */
.oz-zeile {
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--djk-black-soft);
}
.oz-zeile-kopf {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.oz-zeile-kopf select {
    flex: 0 1 150px;
    min-width: 0;
}
.oz-zusatz {
    flex: 1 1 180px;
    min-width: 0;
}
.oz-bis {
    color: var(--djk-gray);
    font-size: 0.85rem;
    flex: none;
}
.oz-spannen {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--djk-border);
}
.oz-spanne {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
/* 140 statt 116 (19.09.2026): seit das Zeichen im Feld steht (ui_feld.js, 40 px links), blieb
   von „17:00“ nur „17:(“ uebrig — gemessen auf Rechnungen → Oeffnungszeiten. */
.oz-spanne input[type="time"] {
    width: 140px;
}
.oz-zeile-kopf .admin-chip-remove { margin-left: auto; }
/* Vorschau: zeigt dasselbe Bild wie später das Papier. */
.oz-vorschau {
    margin-top: 14px;
    padding: 12px 14px;
    border: 1px dashed var(--djk-border);
    border-radius: var(--feld-radius);
    font-family: 'Courier New', Courier, monospace;
    font-size: 0.86rem;
    line-height: 1.5;
}
.oz-vorschau-titel {
    font-family: inherit;
    font-weight: 700;
    font-size: 0.72rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--djk-gray);
    margin-bottom: 6px;
}
@media (max-width: 560px) {
    .oz-zeile-kopf select, .oz-zusatz { flex: 1 1 100%; }
    .oz-zeile-kopf .admin-chip-remove { margin-left: 0; }
    .oz-spanne input[type="time"] { width: 132px; }
}

/* ---------- Gutschein verkaufen ---------- */
/* Beschriftung über dem Feld, Feld über die volle Breite: nebeneinander wurde das Eingabefeld
   auf dem Handy so schmal, dass ein dreistelliger Betrag nicht mehr hineinpasste. */
.gs-feld {
    margin-bottom: 12px;
}
.gs-feld label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--djk-gray);
}
.gs-optional {
    font-weight: 400;
    opacity: .75;
}
.gs-feld input {
    width: 100%;
    padding: 12px 14px;
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 1rem;
}
.gs-feld input:focus {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}
/* Der Betrag ist die Hauptsache in diesem Fenster und darf entsprechend groß stehen. */
.gs-betrag-rahmen {
    position: relative;
}
.gs-feld .gs-betrag {
    padding-right: 42px;
    text-align: right;
    font-size: 1.6rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}
.gs-euro {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--djk-gray);
    pointer-events: none;
}
/* Schnellwahl aus der Verwaltung: so breit wie nötig, umbrechend statt abgeschnitten. */
.gs-schnellwahl {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 6px;
    margin-bottom: 10px;
}
.gs-schnell-btn {
    padding: 12px 6px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 0.95rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    user-select: none;
    touch-action: manipulation;
    transition: background var(--transition), border-color var(--transition);
}
.gs-schnell-btn:hover {
    background: var(--djk-border);
}
.gs-schnell-btn.ist-gewaehlt {
    background: var(--djk-yellow);
    border-color: var(--djk-yellow);
    color: #fff;
}
.gs-feld-name {
    margin-top: 14px;
}

/* ---------- Code eingeben oder scannen (Gutschein, Promo-Code) ---------- */
/* Beide Wege stehen nebeneinander: tippen für den, der die Nummer vor sich hat, scannen für
   den, der ein Handy hingehalten bekommt. */
.code-eingabe {
    display: flex;
    gap: 8px;
    align-items: stretch;
}
.code-eingabe .input-icon {
    flex: 1;
    min-width: 0;
    margin: 0;
}
.code-scan-btn {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.code-scan-btn .icon {
    width: 20px;
    height: 20px;
}
/* Auf schmalen Geräten untereinander — sonst wird das Eingabefeld unbrauchbar kurz. */
@media (max-width: 420px) {
    .code-eingabe { flex-direction: column; }
    .code-scan-btn { justify-content: center; }
}

/* Angerechneter Gutschein über der Zahlungsart-Auswahl. */
.pay-vorab {
    margin: 0 0 12px;
    padding: 8px 10px;
    border-radius: var(--feld-radius);
    background: rgba(59, 130, 246, 0.12);
    border: 1px solid var(--djk-yellow);
    font-size: 0.85rem;
}

/* Gefundener Promo-Code: was er ist und was er bringt, bevor er übernommen wird. */
.promo-treffer {
    margin-top: 12px;
    padding: 10px 12px;
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    background: var(--djk-black-soft);
}
.promo-treffer-name {
    font-weight: 700;
}
.promo-treffer-zeile {
    margin-top: 2px;
    color: var(--djk-gray);
    font-size: 0.85rem;
}
.promo-treffer-summe {
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
}
.promo-ersparnis {
    margin-left: 6px;
    color: var(--djk-success, #3fae5a);
    font-weight: 700;
}

/* Rabattierte Zeile in der Positionsliste. */
.cart-item-rabatt {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    color: var(--djk-success, #3fae5a);
    font-weight: 600;
}
.cart-line-rabattiert {
    border-left: 3px solid var(--djk-success, #3fae5a);
}

/* ---------- Aufteilen einer Zahlung: Zeilen und Ziffernblock ---------- */
/* Eine Zeile ist eine Spalte: oben Zahlungsart + Betrag nebeneinander, darunter — nur beim
   Gutschein — die Nummernsuche. Deshalb steht das flex jetzt an .split-zeile und nicht mehr
   an der Zeile selbst. */
.allocation-row {
    margin-bottom: 8px;
}
.split-zeile {
    display: flex;
    gap: 8px;
    align-items: center;
}
/* Die Felder einer Zeile tragen jetzt den gemeinsamen Satz Merkmale (weiß, 1px, 5px), statt
   ihn sich per style-Attribut selbst zu geben — vorher waren sie die einzigen grauen Felder. */
.allocation-row .split-za,
.allocation-row .split-betrag {
    padding: 10px 12px;
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 0.95rem;
    appearance: none;
    -webkit-appearance: none;
}
.allocation-row .split-za {
    flex: 1;
    min-width: 0;
    padding-right: 34px;
    background-image: var(--feld-pfeil);
    background-repeat: no-repeat;
    background-position: right 10px center;
    cursor: pointer;
}
.allocation-row .split-betrag {
    width: 104px;
    flex: none;
    text-align: right;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.allocation-row .split-za:focus,
.allocation-row .split-betrag:focus {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}
/* Solange die Gutschein-Nummer fehlt, nimmt das Betragsfeld nichts an — das muss man ihm
   ansehen, sonst wirkt die Kasse kaputt statt konsequent. */
.allocation-row .split-betrag:disabled {
    background: var(--djk-black-soft);
    color: var(--djk-gray);
    cursor: not-allowed;
}
/* Kurzes rotes Aufblitzen, wenn ein Betrag über die Rechnung oder das Guthaben hinausgeht. */
.allocation-row .split-betrag.ist-zuviel {
    border-color: var(--djk-danger);
    box-shadow: 0 0 0 3px rgba(214, 69, 69, 0.22);
}
.split-warnung {
    margin: 10px 0 0;
    padding: 8px 10px;
    border-radius: var(--feld-radius);
    background: rgba(214, 69, 69, 0.12);
    border: 1px solid var(--djk-danger);
    color: var(--djk-danger);
    font-size: 0.85rem;
    font-weight: 600;
}

/* source/style_css/340_voucher_split_line.css - style.css part 48 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Gutschein-Zeile innerhalb der Aufteilung ---------- */
.split-gutschein {
    margin-top: 6px;
    padding: 8px;
    border: 1px dashed var(--djk-border);
    border-radius: var(--feld-radius);
}
.split-gs-suche {
    width: 100%;
    padding: 10px 12px;
    background: var(--feld-grund);
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 0.95rem;
}
.split-gs-suche:focus {
    outline: none;
    border-color: var(--djk-yellow);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}
.split-gs-hinweis {
    margin: 8px 0 0;
    color: var(--djk-gray);
    font-size: 0.82rem;
}
.split-gs-treffer:not(:empty) {
    margin-top: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.split-gs-treffer-zeile {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 10px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 0.88rem;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}
.split-gs-treffer-zeile:hover {
    background: var(--djk-border);
    border-color: var(--djk-yellow);
}
.split-gs-code {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.split-gs-name {
    color: var(--djk-gray);
    /* Ein langer Name darf die Zeile nicht auseinanderdrücken — das Guthaben rechts ist
       wichtiger und muss sichtbar bleiben. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.split-gs-guthaben {
    margin-left: auto;
    flex: none;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
/* Nach der Auswahl: Nummer links, "150,00 € → 149,60 €" daneben, rechts der Weg zurück. */
.split-gs-gewaehlt {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.88rem;
}
/* Muss sein: das display:flex oben ist eine Regel dieser Datei und wiegt damit schwerer als
   das display:none, das der Browser einem hidden-Element von Haus aus gibt. Ohne diese Zeile
   bliebe der Kasten sichtbar, obwohl im Skript hidden gesetzt ist. Gleiches gilt für die
   Treffer-Liste, sobald sie leer ist. */
.split-gs-gewaehlt[hidden] {
    display: none;
}
.split-gs-stand {
    color: var(--djk-gray);
    font-variant-numeric: tabular-nums;
}
.split-gs-wechseln {
    margin-left: auto;
    padding: 4px 10px;
    background: none;
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    color: var(--djk-gray);
    font-size: 0.8rem;
    cursor: pointer;
}
.split-gs-wechseln:hover {
    border-color: var(--djk-yellow);
    color: var(--djk-white);
}

/* Ziffernblock unter "+ Zeile". Drei Spalten wie auf jeder Kasse; die Löschtaste sitzt
   rechts unten neben der Null, wo der Daumen sie ohne Hinsehen findet. */
.split-pad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
    margin-top: 10px;
}
.split-pad-taste {
    padding: 14px 0;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    color: var(--djk-white);
    font-size: 1.15rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    /* Kein Textmarkieren beim schnellen Tippen — sonst wird beim zweiten Tipp die Ziffer
       markiert statt eingegeben. */
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
    transition: background var(--transition), border-color var(--transition);
}
.split-pad-taste:hover { background: var(--djk-border); }
.split-pad-taste:active { background: var(--djk-yellow); border-color: var(--djk-yellow); color: #fff; }
.split-pad-loeschen { color: var(--djk-danger); font-size: 1.25rem; }

/* ==========================================================================================
   TABELLEN: ZWEI ANSICHTEN — "Kompakt" (Werkszustand) und "Luftig"

   Umgeschaltet wird über EINE Klasse am <body> (`tabellen-luftig`), gesetzt von
   admin/includes/header.php aus der Einstellung `admin_tabellen_stil`. Kein zweites
   Stylesheet, keine geänderte Ausgabe in einer PHP-Datei: dieselben Tabellen, ein anderer
   Satz Regeln darüber. Wer morgen eine neue Tabelle anlegt, bekommt beide Ansichten geschenkt.

   Was "Luftig" anders macht: ruhige graue Kopfzeile statt blauer Versalien, hohe Zeilen,
   feine Trennlinien, weiche Ecken mit leichtem Schatten, die erste Spalte kräftiger als der
   Rest. Weniger Zeilen auf einen Blick, dafür leichter zu lesen.

   **Der ganze Block liegt in `min-width: 701px`, und das ist Bedingung, nicht Zierde.**
   Ab 700px abwärts wird aus jeder Tabellenzeile eine Karte (der Block direkt darunter). Diese
   Regeln hier wiegen mit zwei Klassen schwerer als die Kartenregeln mit einer — ohne die
   Grenze würden sie die Karten auf dem Handy still wieder zu Tabellenzellen machen. Genau
   dafür steht die Warnung unten: neue Tabellenregeln VOR den Kartenblock, und wenn sie nur
   den großen Bildschirm meinen, dann auch nur dort.
   ========================================================================================== */

/* Die Umschalter selbst — in der Kopfleiste, die es nur am großen Bildschirm gibt.
   Dieselbe Machart für beide Gruppen (Klassisch/Warm und Kompakt/Luftig). */
.ansicht-schalter {
    display: flex;
    gap: 2px;
    padding: 2px;
    background: rgba(255, 255, 255, .55);
    border: 1px solid rgba(15, 23, 42, .10);
    border-radius: 999px;
    flex-shrink: 0;
}
.ansicht-schalter-taste {
    border: 0;
    background: transparent;
    /* `--djk-white` ist im hellen Schema die SCHRIFTfarbe (#0f172a) — die Namen sind hier
       verdreht. Vorher stand `--djk-black` (#f8fafc) da: fast weiß auf fast weiß. */
    color: var(--djk-white);
    opacity: .7;
    font: inherit;
    font-size: 0.76rem;
    font-weight: 700;
    padding: 5px 13px;
    border-radius: 999px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition), opacity var(--transition);
}
.ansicht-schalter-taste:hover { opacity: 1; }
.ansicht-schalter-taste.aktiv {
    background: var(--djk-black-card);
    color: var(--djk-yellow);
    opacity: 1;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .12);
}

@media (min-width: 701px) {
    /*
     * Auch die echten Tabellen sind Karten-Zeilen — dieselbe Sprache wie bei den Rastern:
     * je Zeile eine eigene Fläche mit 15px Ecken und 5px Abstand, keine Hülle darum, keine
     * Trennlinien.
     *
     * Der Trick dabei ist `border-collapse: separate` mit `border-spacing: 0 5px`. Nur so
     * bekommt eine Tabellenzeile Abstand zur nächsten; mit `collapse` (dem Werkszustand jeder
     * Tabelle hier) teilen sich benachbarte Zellen ihre Kanten und ein Abstand ist nicht
     * vorgesehen. Und weil eine `<tr>` selbst keine runden Ecken annimmt, tragen sie die
     * ÄUSSEREN Zellen: links die erste, rechts die letzte.
     */
    .tabellen-luftig .table-wrap,
    .tabellen-luftig .admin-table-wrap {
        background: none;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    .tabellen-luftig .clients-table,
    .tabellen-luftig .admin-table {
        border-collapse: separate;
        border-spacing: 0 5px;
    }

    /* Kopfzeile: sie soll die Spalte benennen, nicht um Aufmerksamkeit werben. Ohne Linie
       darunter — zwischen ihr und der ersten Karte steht ohnehin schon Luft. */
    .tabellen-luftig .clients-table th,
    .tabellen-luftig .admin-table th {
        text-transform: none;
        letter-spacing: 0;
        font-size: 0.8rem;
        font-weight: 700;
        color: var(--djk-gray);
        opacity: 1;
        padding: 4px 12px 6px;
        border-bottom: 0;
    }
    .tabellen-luftig .clients-table th:first-child,
    .tabellen-luftig .admin-table th:first-child { padding-left: 20px; }

    .tabellen-luftig .clients-table tbody td,
    .tabellen-luftig .admin-table tbody td {
        background-color: var(--zeilen-grund);
        padding: 10px 12px;
        border-bottom: 0;
        color: var(--djk-gray);
    }
    .tabellen-luftig .clients-table tbody td:first-child,
    .tabellen-luftig .admin-table tbody td:first-child {
        /* Die erste Spalte ist der Name der Zeile — sie trägt den Blick, alles Übrige
           begleitet. Sie rundet zugleich die linke Seite der Karte. */
        color: var(--djk-white);
        font-weight: 600;
        padding-left: 20px;
        border-radius: 15px 0 0 15px;
    }
    .tabellen-luftig .clients-table tbody td:last-child,
    .tabellen-luftig .admin-table tbody td:last-child {
        padding-right: 20px;
        border-radius: 0 15px 15px 0;
    }
    /* Der Grund liegt auf den Zellen, nicht auf der Zeile — ein `tr:hover { background }`
       verschwände hinter ihnen. */
    .tabellen-luftig .clients-table tbody tr:hover td,
    .tabellen-luftig .admin-table tbody tr:hover td { background-color: var(--djk-black-soft); }

    /* ------------------------------------------------------------------------------------
       DIE RASTER WERDEN ZEILENLISTEN

       Produkte, Kategorien, Extras, Größen, Warengruppen — und ebenso Tische und
       Tischkategorien, die dieselben Raster benutzen — sind keine Tabellen, sondern Kacheln
       mit Foto. „Luftig" macht daraus dasselbe, was es aus einer Tabelle macht: EINE weiße
       Fläche mit weichen Ecken, darin je Eintrag eine Zeile mit feiner Trennlinie.

       Aus dem Raster wird dafür ein Block, aus jeder Kachel eine Flex-Zeile. Die Reihenfolge
       der Angaben bleibt die des Quelltextes — Foto, Name, Nebenangaben, Preis, Schalter,
       Knöpfe —, sie stehen nur nebeneinander statt untereinander. Keine PHP-Datei ändert
       dafür ihre Ausgabe.
       ------------------------------------------------------------------------------------ */
    /*
     * Die Liste selbst ist nur noch eine Reihenfolge — sie hat weder Grund noch Rand noch
     * Ecken. Bis zum 10.08.2026 war sie EINE Fläche mit Trennlinien darin; jetzt ist jede
     * Zeile eine eigene Karte, und eine Fläche hinter Karten wäre eine Fläche zu viel.
     * `overflow: hidden` bleibt: es macht aus der Liste einen eigenen Formatierungsbereich,
     * damit der obere Abstand der ersten Zeile nicht aus ihr herausfällt.
     */
    .tabellen-luftig .admin-mini-grid,
    .tabellen-luftig .admin-produkt-grid,
    .tabellen-luftig .wg-grid,
    .tabellen-luftig .groessen-liste {
        display: block;
        gap: 0;
        overflow: hidden;
    }

    .tabellen-luftig .admin-mini-card,
    .tabellen-luftig .admin-produkt-card,
    .tabellen-luftig .wg-card,
    .tabellen-luftig .groessen-chip {
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 14px;
        height: auto;
        padding: 10px 20px;
        margin: 5px 0;
        text-align: left;
        border: 0;
        border-radius: 15px;
        box-shadow: none;
        /* Die ganze Zeile öffnet die Bearbeitung (data-edit-href) — der Zeiger soll es sagen. */
        cursor: pointer;
    }

    /* Der Sprung nach oben beim Überfahren gehört zur Kachel, nicht zur Zeile: eine Liste,
       in der die Zeilen hüpfen, liest sich unruhig. */
    .tabellen-luftig .admin-mini-card:hover,
    .tabellen-luftig .admin-produkt-card:hover,
    .tabellen-luftig .wg-card:hover,
    .tabellen-luftig .groessen-chip:hover {
        transform: none;
        box-shadow: none;
        border-color: transparent;
    }

    /* Das Foto wird zum Vorschaubild am Zeilenanfang. `aspect-ratio: auto` muss sein: sonst
       zwänge das Quadrat aus .product-tile-photo die Zeile wieder auf Kachelhöhe. */
    .tabellen-luftig .admin-mini-card .product-tile-photo,
    .tabellen-luftig .admin-produkt-card .product-tile-photo {
        flex: none;
        width: 44px;
        height: 44px;
        aspect-ratio: auto;
        margin: 0;
        border-radius: 6px;
    }

    /* Der Name trägt die Zeile — einzeilig mit Auslassung, statt wie in der Kachel auf zwei
       Zeilen umzubrechen.

       Die Verhältnisse hier sind nicht Geschmack, sondern Notwendigkeit: eine Produktzeile
       trägt Foto, Name, Kategorie, Merkmale, Preis, zwei Schalter und zwei Knöpfe. Ist alles
       davon unnachgiebig (`flex: none`), gibt der einzige nachgiebige Teil alles her — beim
       ersten Versuch schrumpfte der Produktname auf EIN Pixel, während die Merkmalsliste
       ungekürzt stehen blieb. Der Name bekommt deshalb einen Sockel und den größten Anteil,
       Kategorie und Merkmale dürfen kürzen. Kürzen sollen die Nebenangaben, nie die Hauptsache. */
    .tabellen-luftig .admin-mini-card h3,
    .tabellen-luftig .admin-produkt-card h3 {
        display: block;
        flex: 4 1 220px;
        min-width: 150px;
        min-height: 0;
        margin: 0;
        font-size: 0.9rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Schrumpffaktor 5 gegen die 1 des Namens: wird der Platz knapp, geben zuerst diese hier
       nach. Ohne das Gefälle kürzt der Browser alle gleichmäßig — und die Merkmalsliste
       „Küche · Salat · Weiterleitbar" stünde vollständig da, während der Produktname
       abgeschnitten wäre. */
    .tabellen-luftig .admin-mini-card .hint,
    .tabellen-luftig .admin-produkt-card .hint,
    .tabellen-luftig .admin-mini-card .tag,
    .tabellen-luftig .admin-produkt-card span.tag {
        flex: 0 5 auto;
        min-width: 0;
        /* `max-content` statt einer festen Zeichenzahl: die Angabe nimmt genau so viel, wie sie
           braucht, und kürzt erst, wenn der Platz knapp wird. 26 Zeichen waren eine geratene
           Zahl und schnitten kurze Angaben unnötig ab. */
        max-width: max-content;
        margin: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .tabellen-luftig .admin-mini-card .kat-abweichung-marke,
    .tabellen-luftig .admin-produkt-card .kat-abweichung-marke {
        flex: none;
        margin: 0;
        white-space: nowrap;
    }

    /* Was in einer Zeile nicht mitkann. Beschreibung und Allergene sind Fließtext, die
       Extras-Liste wird mit jeder Zuordnung länger — zu dritt schöben sie Preis und Schalter
       aus dem Bild. Sie stehen unverändert in der Kachelansicht und im Formular; die Zeile ist
       die Übersicht zum Finden und Umschalten, nicht das ganze Produkt. */
    .tabellen-luftig .admin-produkt-card .admin-produkt-beschreibung,
    .tabellen-luftig .admin-produkt-card .admin-produkt-allergene,
    .tabellen-luftig .admin-produkt-card div.tag { display: none; }

    /* source/style_css/345_voucher_split_line_continued.css - style.css: voucher split line continued, part 49 of 78 (built by werkzeuge/parts_build.php) */
    .tabellen-luftig .admin-produkt-price {
        flex: none;
        margin: 0;
        min-width: 78px;
        text-align: right;
    }
    .tabellen-luftig .admin-produkt-card .produkt-shop-schalter { flex: none; }
    .tabellen-luftig .admin-produkt-card .produkt-shop-hinweis {
        flex: none;
        max-width: 160px;
        font-size: 0.62rem;
    }
    /* Das Kästchen der Massenänderung sitzt in der Kachel in der Ecke (position:absolute).
       In der Zeile bekommt es einen eigenen Platz ganz vorn. */
    body.massen-modus.tabellen-luftig .massen-kasten { position: static; flex: none; }

    /* Knöpfe ans rechte Ende, nebeneinander statt als Zweierraster. */
    .tabellen-luftig .admin-mini-card-actions,
    .tabellen-luftig .wg-actions {
        display: flex;
        flex: none;
        gap: 6px;
        margin: 0 0 0 auto;
        padding: 0;
    }
    .tabellen-luftig .admin-mini-card-actions > *,
    .tabellen-luftig .wg-actions > * { flex: none; }
    .tabellen-luftig .admin-mini-card-actions .btn,
    .tabellen-luftig .wg-actions .btn { width: auto; padding: 6px 12px; }

    /* Warengruppen: Name und Steuersatz vorn, die zugeordneten Kategorien füllen die Mitte
       und laufen bei zu vielen aus dem Bild statt umzubrechen — sonst wäre die Zeile
       wieder eine Kachel. */
    .tabellen-luftig .wg-card-head { flex: none; gap: 12px; }
    .tabellen-luftig .wg-standard-badge { flex: none; align-self: center; }
    .tabellen-luftig .wg-kats {
        flex: 1 1 auto;
        min-width: 0;
        flex-wrap: nowrap;
        overflow: hidden;
    }
    .tabellen-luftig .wg-leer { flex: 1 1 auto; }

    .tabellen-luftig .groessen-chip-name { flex: 1 1 auto; }
}

/* source/style_css/350_admin_warm_theme.css - style.css part 50 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==========================================================================================
   ERSCHEINUNGSBILD „WARM" — die zweite Fassung der Verwaltungsfläche

   Umgeschaltet über `body.ansicht-warm` (Kopfleiste, siehe includes/admin_ansicht.php). Der
   Werkszustand „Klassisch" braucht keine einzige Regel: er ist das, was ohnehin dasteht.

   Der Gedanke: statt einer durchgehenden hellen Fläche liegt ein warmer Grund darunter, und
   Menü wie Inhalt schweben darauf als eigene gerundete Flächen mit dunkler Kopfleiste.

   Bewusst NICHT übernommen aus dem Entwurf: `.admin-main-area * { background: … }`. Ein
   solcher Selektor färbt buchstäblich jedes Element darin ein — auch Schalter, Abzeichen und
   Farbfelder, deren Grund etwas bedeutet. Dass es im Entwurf trotzdem passabel aussah, lag
   allein daran, dass die Knöpfe zufällig später im Stylesheet stehen. Hier bekommt die Fläche
   ihren Ton, nicht jedes Ding darauf.
   ========================================================================================== */
body.ansicht-warm {
    background: #b77a00;
}
/*
 * Der RAHMEN — schwebendes Menü, schwebende Fläche, dunkle Kopfleiste — gehört ausschließlich
 * dem großen Bildschirm, und diese Klammer ist der Grund dafür:
 *
 * Auf dem Handy ist dasselbe `.admin-sidebar-nav` kein Menü an der Seite, sondern ein
 * Vollbild-Überlagerer (`position: fixed; inset: 0`), den der Knopf „Mehr" einblendet. Vorher
 * standen diese Regeln außerhalb und wurden für das Handy in einem zweiten Block wieder
 * zurückgenommen — mit `background: none` und `height: auto`. Beides traf den Überlagerer:
 * er wurde DURCHSICHTIG und verlor seine volle Höhe, das Menü lag lesbar über der Seite
 * darunter. Ein Zurücknehmen ist eben nicht dasselbe wie ein Nichtsetzen.
 */
@media (min-width: 901px) {
    body.ansicht-warm .admin-sidebar-nav {
        background: rgba(255, 255, 255, .71);
        border-right: 0;
        border-radius: 15px;
        margin: 10px;
        /* Ohne die Rechnung stünde das Menü 20px zu hoch und der untere Rand fiele aus dem Bild. */
        height: calc(100vh - 20px);
    }
}
/*
 * Dunklere Menüschrift, aber über die VARIABLE und nicht an einer einzelnen Regel.
 *
 * Das durchscheinende Weiß über dem warmen Grund ergibt kein Weiß, sondern einen hellen
 * Sandton (etwa #ead8b5). Das schiefergraue #475569 steht darauf zwar noch lesbar, wirkt aber
 * ausgewaschen. #232323 ist der Ton, den der Wirt dafür gewählt hat.
 *
 * Sein Entwurf setzte ihn nur an `.admin-sidebar-submenu-toggle` — dann wären die aufklappbaren
 * Punkte dunkler gewesen als die einfachen daneben und als ihre eigenen Unterpunkte. Über die
 * Variable bekommen Punkte, Umschalter, Unterpunkte und das Suchfeld denselben Ton; genau das
 * ist die stehende Vorgabe („везде одинаковые"). Im klassischen Bild bleibt es beim Schiefer:
 * dort steht die Schrift auf Weiß und hat Kontrast genug.
 */
body.ansicht-warm { --djk-sidebar-text: #232323; }
/*
 * KEIN `overflow: hidden` hier, so verlockend es ist.
 *
 * Der Entwurf hatte es, damit die Kopfleiste nicht über die runde Ecke der Fläche hinausragt.
 * Nachgemessen: damit wird die Fläche zum Scrollbehälter, und `position: sticky` seiner Kinder
 * hört auf zu wirken — Kopfleiste UND Filterleiste rutschten beim Scrollen mit nach oben weg
 * (gemessen: Kopfleiste bei −1190px statt bei 0). Die Ecken stimmen auch ohne: die Kopfleiste
 * trägt oben denselben Radius wie die Fläche, unten reicht selten etwas bis in die Ecke.
 */
@media (min-width: 901px) {
    body.ansicht-warm .admin-main-area {
        margin: 10px 10px 10px 0;
        border-radius: 15px;
        background: rgba(238, 241, 245, .66);
    }
    body.ansicht-warm .admin-topbar {
        background: #353535;
        border-radius: 15px 15px 0 0;
    }
    /* Auf dem dunklen Grund kehren sich Schrift und Symbole um. Nur dort: im Menüfuß des
       Handys stehen dieselben Schalter auf hellem Grund, weiße Schrift wäre unsichtbar. */
    body.ansicht-warm .admin-topbar-title,
    body.ansicht-warm .admin-topbar-icon { color: #ffffff; }
    body.ansicht-warm .admin-topbar .ansicht-schalter {
        background: rgba(255, 255, 255, .14);
        border-color: rgba(255, 255, 255, .22);
    }
    body.ansicht-warm .admin-topbar .ansicht-schalter-taste { color: #ffffff; }
    body.ansicht-warm .admin-topbar .ansicht-schalter-taste.aktiv { color: var(--djk-yellow); }
}

/* Auf dem getönten Grund braucht eine Karte etwas mehr Deckung, sonst schimmert der Ton durch
   und die Schrift verliert ihren ruhigen Untergrund. `--zeilen-grund` ist derselbe Ton für
   Karten UND Tabellenzeilen — er steht als Variable, damit beide nie auseinanderlaufen. */
body.admin-body { --zeilen-grund: var(--djk-black-card); }
body.ansicht-warm { --zeilen-grund: rgba(255, 255, 255, .82); }

body.ansicht-warm .form-card,
body.ansicht-warm .admin-karte,
body.ansicht-warm .admin-mini-card,
body.ansicht-warm .admin-produkt-card,
body.ansicht-warm .wg-card {
    background-color: var(--zeilen-grund);
}
/* Die Hülle einer Tabelle ist nur in der kompakten Ansicht eine Fläche; in „Luftig" tragen die
   Zeilen selbst den Grund, und eine Fläche hinter Karten wäre eine Fläche zu viel. */
body.ansicht-warm:not(.tabellen-luftig) .table-wrap,
body.ansicht-warm:not(.tabellen-luftig) .admin-table-wrap {
    background-color: var(--zeilen-grund);
}

/*
 * Auf dem Handy: kein Rahmen, keine schwebenden Flächen — aber der warme Ton muss zu SEHEN sein.
 *
 * Zuerst war er es nicht: der Grund der Seite stand zwar auf Warm, lag aber vollständig unter
 * der undurchsichtigen Inhaltsfläche. Beide Schalter änderten damit auf dem Telefon nichts
 * Sichtbares — für den Wirt hieß das zu Recht „die Knöpfe gehen nicht", obwohl sie schalteten
 * und speicherten. Ein Schalter ohne sichtbare Wirkung ist ein kaputter Schalter.
 *
 * Deshalb bekommt die Inhaltsfläche denselben durchscheinenden Ton wie am großen Bildschirm;
 * der warme Grund scheint hindurch. Das Menü (derselbe Knoten, dort ein Vollbild-Überlagerer)
 * bleibt bewusst unangetastet und behält seinen deckenden weißen Grund.
 */
@media (max-width: 900px) {
    body.ansicht-warm .admin-main-area { background: rgba(238, 241, 245, .66); }
}

/* ---------- Verwaltung: EINE Breite, durchscheinende Blöcke, lesbare Schrift ----------
 *
 * Der Wirt hat ein Bildschirmfoto angezeichnet: links und rechts eine Handbreit leer, die
 * Einstellungen als schmale Säule in der Mitte. Der Grund war nicht eine Zahl, sondern ein
 * Dutzend: 600, 640, 760, 1100, 1180 — jede Seite brachte ihre eigene mit, viele davon als
 * style="" direkt am Element (39 Stellen allein für Karten und Formulare). Dieselbe Verwaltung
 * sah je nach Reiter anders breit aus.
 *
 * Ab hier gilt eine Breite für alle Seiten, und die Karten füllen sie. Das `!important` steht
 * hier ausnahmsweise zu Recht: eine Regel an EINER Stelle ist ehrlicher als sechzig Änderungen
 * in einem Dutzend Dateien, von denen die nächste Seite eine vergisst.
 */
body.admin-body { --admin-breite: 1500px; }
body.admin-body .admin-content .container { max-width: var(--admin-breite); }
body.admin-body .admin-content .form-card,
body.admin-body .admin-content .admin-karte,
body.admin-body .admin-content .admin-collapsible,
body.admin-body .admin-content .form-card > form,
body.admin-body .admin-content .admin-karte > form { max-width: none !important; }

/*
 * Ein Block ist eine Fläche, kein Rahmen um Luft: durchscheinendes Weiß, damit der Ton der
 * Seite darunter zu sehen bleibt. Vorher lag dort ein Hauch Blau-Schwarz (2,5 %) — auf dem
 * warmen Grund war das ein schmutziger Schleier statt einer Karte.
 * NICHT im dunklen Erscheinungsbild: dort wäre eine weiße Fläche ein Loch.
 */
body.admin-body:not(.thema-dunkel) .admin-collapsible { background: rgba(255, 255, 255, .55); }
body.admin-body:not(.thema-dunkel) .admin-collapsible[open] { background: rgba(255, 255, 255, .72); }

/*
 * Schriftfarben auf hellem Grund — nachgemessen, nicht geschätzt.
 *
 * Auf der Startseite der Bestell-Website standen 35 Texte unter dem Wert, ab dem Schrift als
 * lesbar gilt (4,5:1 nach WCAG): die Hinweise mit 2,8:1, die Überschriften der Blöcke sogar
 * mit 2,2:1 — hellblau auf hellbeige. Am Schreibtisch bei gutem Licht geht das durch; im Lokal,
 * schräg von der Seite, auf einem Telefon in der Sonne nicht mehr.
 *
 * Nur die Textfarben werden dunkler, NICHT die Variable --djk-yellow selbst: sie ist zugleich
 * der Grund der blauen Knöpfe und die aktive Farbe in der dunklen Kopfleiste — dort würde ein
 * dunkleres Blau seinerseits verschwinden.
 */
body.admin-body:not(.thema-dunkel) { --djk-gray: #4b5563; }
body.admin-body:not(.thema-dunkel) .admin-collapsible summary { color: #1e40af; }
/* Der Knopf mit Rand hat KEINE Fläche — seine Schrift steht auf dem Kartengrund und muss
   deshalb so dunkel sein wie ein Link. Nicht `.btn-text` färben: dieselbe Klasse trägt auch die
   Beschriftung IM blauen Knopf, und dort wurde aus Weiß-auf-Blau prompt Blau-auf-Blau. */
body.admin-body:not(.thema-dunkel) .btn-outline { color: #1e40af; }
body.admin-body:not(.thema-dunkel) .hint a,
/* `.seiten-reiter-knopf` ausgenommen (22.09.2026): dieser Reiter ist kein Verweis im Text,
   sondern ein Knopf, und traegt die Schriftfarbe bzw. im gewaehlten Zustand Weiss auf der
   Hausfarbe. Gemessen: ohne diese Ausnahme gewann hier rgb(30,64,175) mit Nachdruck. */
body.admin-body:not(.thema-dunkel) .admin-content a:not(.btn):not(.admin-nav-link):not(.admin-tab):not(.seiten-reiter-knopf):not(.finanz-knopf.aktiv):not(.veranst-fuer-chip),
body.admin-body:not(.thema-dunkel) .admin-karte-text a { color: #1e40af !important; }

/*
 * „Luftig" auf dem Handy. Dort sind Tabellen ohnehin Karten und die Raster zweispaltig — die
 * Zeilenlisten des großen Bildschirms gibt es nicht. Bleibt die Sprache: weiche Ecken und Luft
 * zwischen den Karten, genau wie oben. Ohne das schaltete „Kompakt/Luftig" auf dem Telefon ins
 * Leere.
 */
@media (max-width: 700px) {
    .tabellen-luftig .table-wrap tr,
    .tabellen-luftig .admin-table-wrap tr {
        border-radius: 15px;
        margin-bottom: 10px;
    }
    .tabellen-luftig .admin-mini-grid,
    .tabellen-luftig .admin-produkt-grid,
    .tabellen-luftig .wg-grid { gap: 10px; }
    .tabellen-luftig .admin-mini-card,
    .tabellen-luftig .admin-produkt-card,
    .tabellen-luftig .wg-card,
    .tabellen-luftig .groessen-chip { border-radius: 15px; }
}

/* ==========================================================================================
   SYMBOLE AUF DEN KNÖPFEN

   Aufgehängt werden sie von assets/js/knopf_symbole.js, die Zuordnung steht in
   includes/icons.php. Hier nur, wie sie sitzen.

   `.btn-nur-symbol` versteckt die Beschriftung, LÖSCHT sie aber nicht: sie bleibt im Dokument
   für die Sprachausgabe und steht zusätzlich als `title` am Knopf. Ein Knopf ohne jeden Text
   ist für den, der ihn nicht sieht, ein leerer Knopf.
   ========================================================================================== */
.btn-mit-symbol {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
}
.btn-symbol {
    width: 17px;
    height: 17px;
    flex: none;
}
.btn-sm .btn-symbol,
.btn-sm.btn-mit-symbol .btn-symbol { width: 15px; height: 15px; }

.btn-nur-symbol { padding-left: 10px; padding-right: 10px; }
.btn-nur-symbol .btn-text {
    /* Nicht `display:none` — vorgelesen werden soll er weiterhin. */
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}
.btn-nur-symbol .btn-symbol { width: 17px; height: 17px; }

/* Der folgende Block steht bewusst GANZ AM ENDE der Datei.
   Grund: seine Selektoren (.table-wrap td) wiegen genauso schwer wie die weiter oben
   stehenden (.clients-table td). Bei gleicher Gewichtung entscheidet die Reihenfolge —
   und `table.clients-table { min-width: 720px }` sowie `.clients-table td
   { white-space: nowrap }` stehen ab Zeile ~2900. Solange der Block davor lag, wurde
   sein Zurücksetzen still überstimmt: die Karten bildeten sich, aber die Tabelle blieb
   720px breit und die Werte rutschten aus dem Bild. Neue Tabellenregeln bitte VOR
   diesem Block einfügen. */
/* ==========================================================================================
   TABELLEN AUF DEM HANDY — aus jeder Zeile wird eine Karte.

   Eine Tabelle mit sechs Spalten passt auf kein Telefon. Bisher blieb sie eine Tabelle und
   man schob sie seitwärts: die Spaltenköpfe verschwanden dabei nach links, und ohne Kopf ist
   "18,50" nur eine Zahl. Deshalb ab hier ein Gesetz für alle Tabellen in einem .table-wrap:
   Kopfzeile weg, jede Zeile eine Karte, in der Karte je Wert eine Zeile mit seiner
   Beschriftung davor.

   Die Beschriftung kommt aus `data-label`, das assets/js/tabellen_mobil.js aus der Kopfzeile
   überträgt — automatisch, für jede Tabelle, ohne dass eine einzige PHP-Datei etwas davon
   wissen muss. Deshalb wirkt die Regel auch für Tabellen, die es noch gar nicht gibt.

   Nicht betroffen sind Tabellen ohne .table-wrap — das sind die Belegdrucke, die absichtlich
   eine echte Tabelle bleiben.
   ========================================================================================== */
@media (max-width: 700px) {
    .table-wrap,
    .admin-table-wrap {
        overflow-x: visible;      /* nichts mehr zum Wegschieben */
        background: transparent;
        border: 0;
        border-radius: 0;
    }
    .table-wrap table,
    .table-wrap tbody,
    .table-wrap tr,
    .table-wrap td,
    .admin-table-wrap table,
    .admin-table-wrap tbody,
    .admin-table-wrap tr,
    .admin-table-wrap td {
        display: block;
        width: 100%;
        /* Beides MUSS hier zurückgesetzt werden, sonst hilft die Kartenform gar nichts:
           `table.clients-table` trägt min-width:720px und die Zellen white-space:nowrap.
           Das eine hält die Tabelle künstlich breit, das andere verbietet den Umbruch —
           zusammen schoben sie die Werte aus dem Bild und erzeugten genau den seitlichen
           Balken, den die Karten abschaffen sollen. */
        min-width: 0;
        white-space: normal;
        overflow-wrap: anywhere;
    }

    .table-wrap thead,
    .admin-table-wrap thead { display: none; }

    .table-wrap tr,
    .admin-table-wrap tr {
        background: var(--djk-black-card);
        border: 1px solid var(--djk-border);
        border-radius: 8px;
        margin-bottom: 8px;
        padding: 4px 0;
    }
    /* Die Zeile wird angeklickt wie vorher — das kommt aus .clickable-row und bleibt. */
    .table-wrap td,
    .admin-table-wrap td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 14px;
        border: 0;
        padding: 7px 14px;
        text-align: right;
    }
    .table-wrap td::before,
    .admin-table-wrap td::before {
        content: attr(data-label);
        flex: 0 0 38%;
        text-align: left;
        color: var(--djk-gray);
        font-size: 0.7rem;
        font-weight: 700;
        letter-spacing: .05em;
        text-transform: uppercase;
        line-height: 1.5;
    }
    /* Ohne Beschriftung (Aktionsspalte, leere Zelle) nimmt der Wert die volle Breite. */
    .table-wrap td:not([data-label])::before,
    .table-wrap td[data-label=""]::before,
    .admin-table-wrap td:not([data-label])::before,
    .admin-table-wrap td[data-label=""]::before { content: none; }
    .table-wrap td:empty,
    .admin-table-wrap td:empty { display: none; }
    /* Die erste Zelle ist in allen Listen der Name oder die Nummer — sie trägt die Karte. */
    .table-wrap td:first-child,
    .admin-table-wrap td:first-child {
        font-weight: 700;
        font-size: 1rem;
        text-align: left;
        border-bottom: 1px solid var(--djk-border);
        padding-bottom: 9px;
        margin-bottom: 3px;
    }
    .table-wrap td:first-child::before,
    .admin-table-wrap td:first-child::before { display: none; }

    /* Such- und Filterleisten stapeln sich: jedes Feld über die volle Breite. Eine halb breite
       Auswahlliste neben einem vollen Suchfeld sieht nach Versehen aus.
       ZWEI Klassen, weil es die Leiste zweimal gibt: `.admin-filter-bar` in den meisten
       Listen und `.admin-toolbar` unter anderem bei Mitglieder & Kunden. Genau das war der
       Grund, warum die Liste dort trotz der Regel schmal blieb — sie stand in der anderen.
       Die Mindestbreiten (170px am Filter, 200px am Suchfeld) müssen dabei mit weg. */
    .admin-filter-bar,
    .admin-toolbar {
        flex-direction: column;
        align-items: stretch;
        flex-wrap: nowrap;
    }
    .admin-filter-bar > *,
    .admin-toolbar > * { width: 100%; min-width: 0; }
    .admin-filter-bar select,
    .admin-filter-bar input,
    .admin-toolbar select,
    .admin-toolbar input,
    .admin-toolbar .toolbar-search,
    .admin-toolbar .toolbar-search input,
    .admin-toolbar .toolbar-filter select { min-width: 0; width: 100%; }
}

/* source/style_css/355_admin_warm_theme_continued.css - style.css: admin warm theme continued, part 51 of 78 (built by werkzeuge/parts_build.php) */
/* ==========================================================================================
   Verlauf: Karten, die nach Beleg aussehen
   ------------------------------------------------------------------------------------------
   Auf dem Handy wird aus jeder Tabellenzeile eine Karte. Vorher standen dort nur nackte Werte
   untereinander — "3,80 €" und "Bar 3,80 €" waren nicht auseinanderzuhalten und das Ganze sah
   nach nichts aus. Jetzt liest es sich wie ein Bon: Nummer und Datum im Kopf, darunter die
   Angaben mit ihrer Beschriftung, der Betrag hervorgehoben.

   Gilt für alle drei Reiter (Küche, Bar, Fertige Bestellungen) — die Küchen-Listen sind zwar
   keine Belege, brauchen aber dieselbe Lesbarkeit.
   ========================================================================================== */
@media (max-width: 700px) {
    .beleg-karten tr {
        border-radius: 0;
        border-color: var(--djk-border);
        padding: 0;
        overflow: hidden;
    }
    /* Erste Zelle = Kopf des Bons: gross, dunkel abgesetzt, mit Trennlinie darunter. */
    .beleg-karten td:first-child {
        background: var(--djk-black-soft);
        padding: 10px 14px;
        border-bottom: 1px dashed var(--djk-border);
        font-size: 1.02rem;
        font-weight: 800;
        font-variant-numeric: tabular-nums;
        letter-spacing: .01em;
        color: var(--djk-white);
    }
    .beleg-karten td:first-child::before {
        font-size: 0.65rem;
        align-self: center;
    }
    /* Zahlen ruhig ausrichten — auf einem Bon steht nichts krumm untereinander. */
    .beleg-karten td { font-variant-numeric: tabular-nums; }
    /* Der Betrag ist das, wonach gesucht wird. */
    .beleg-karten td:nth-child(4) {
        font-size: 1.05rem;
        font-weight: 800;
        color: var(--djk-yellow);
    }
    /* Letzte Zeile wie der Fuss eines Bons: abgesetzt, leiser. */
    .beleg-karten td:last-child {
        border-top: 1px dashed var(--djk-border);
        color: var(--djk-gray);
        padding-top: 9px;
        padding-bottom: 10px;
    }
}

/* Stornierter Beleg: bleibt stehen — er gehört zum Nachweis —, ist aber auf den ersten Blick
   als ungültig zu erkennen und zählt nicht mehr zum Umsatz. */
.beleg-storniert { opacity: .62; }
.beleg-storniert td:nth-child(4) { text-decoration: line-through; }
.beleg-storno-marke {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 7px;
    border: 1px solid var(--djk-danger);
    color: var(--djk-danger);
    font-size: 0.68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    vertical-align: middle;
}

/* Der Storno-Beleg selbst — die Gegenbuchung mit negativen Beträgen. Er ist gültig (nicht
   ausgegraut wie der zurückgenommene Verkauf), sein Betrag steht aber rot da, weil er von der
   Tagessumme abgeht. Die vierte Spalte ist der Betrag, siehe Kopfzeile in personal/verlauf.php. */
.beleg-storno-zeile td:nth-child(4) { color: var(--djk-danger); font-weight: 700; }

/* source/style_css/360_register_view_history_reservations.css - style.css part 52 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Verwaltung → Kasse → Ansicht: Aufteilung des großen Bildschirms ----------
   Die Vorschau ist zugleich das Bedienfeld: die fünf Blöcke lassen sich darin tauschen. Sie
   bildet dieselben fünf Plätze ab wie der echte Kassenbildschirm (includes/kasse_layout.php).
   `touch-action: none` ist keine Feinheit, sondern Bedingung — sonst deutet der Browser das
   Ziehen mit dem Finger als Scrollen und der Block bleibt liegen. */
.kdp-raster {
    display: grid;
    gap: 4px;
    height: 210px;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 4px;
    background: var(--djk-black-soft);
}
.kdp-spalte { display: grid; gap: 4px; }
.kdp-platz { min-height: 0; display: flex; }
.kdp-block {
    flex: 1 1 auto;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-size: 0.7rem;
    font-weight: 700;
    padding: 2px;
    cursor: grab;
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
    transition: box-shadow var(--transition), border-color var(--transition);
}
.kdp-block:hover { border-color: var(--djk-yellow); }
/* Der gezogene Block folgt dem Finger und liegt über allem — ohne die Umschaltung auf
   `position: relative` bliebe er in der Stapelreihenfolge seines Platzes gefangen. */
.kdp-block.kdp-zieht {
    position: relative;
    z-index: 5;
    cursor: grabbing;
    opacity: 0.9;
    border-color: var(--djk-yellow);
    box-shadow: var(--shadow);
}
.kdp-platz.kdp-ziel .kdp-block {
    border-color: var(--djk-yellow);
    border-style: dashed;
}

/* ---------- Kasse: Verlauf im Produktbereich (#verlaufBtn oben in der Suchleiste) ----------
   Legt sich über die Produkte, statt die Seite zu wechseln: an der Kasse will man nachsehen und
   weiterarbeiten. Gilt für Handy UND großen Bildschirm — der Produktbereich ist auf beiden die
   größte Fläche. Umgeschaltet wird über eine Klasse am <body> und nicht über [hidden]: eine
   Anzeige-Regel des Autors schlägt [hidden], das wäre eine stille Falle. */
#kasseVerlaufPanel { display: none; }
/* Unten KEIN Polster mehr: dort klebt die Leiste mit dem Weg zurueck, und sie bringt ihr
   eigenes mit. Blieben die 30 px stehen, sahe man darunter den naechsten Beleg durch. */
/* Oben kein Polster: seit 26.09.2026 traegt der feste Kopf (`.kasse-verlauf-fest`) Luft und
   sichere Zone — ein Polster hier rollte weg, und Belege liefen ueber dem Kopf durch. */
body.kasse-verlauf-offen #kasseVerlaufPanel { display: flex; flex-direction: column; padding: 0 14px 0; }
.kasse-verlauf-fest { --kopf-fest-luft: 24px; padding-bottom: 0; }
body.kasse-verlauf-offen #kasseProductsSection > .container-wide { display: none; }
/* Der Knopf oben zeigt, dass die Ansicht offen ist — sonst sucht man den Weg zurück. */
#verlaufBtn.active { border-color: var(--djk-yellow); color: var(--djk-yellow); }

/* Der Kopf traegt seit dem Abend des 07.09.2026 `.seiten-kopf` — den Kopf des Programms.
   Hier bleibt nur, was diese Seite zusaetzlich braucht. */
.kasse-verlauf-kopf { margin-bottom: 4px; }
.kasse-verlauf-kopf .modal-close { position: static; }

/* --- Verlauf: Menue oben, Weg zurueck unten (07.09.2026) ---------------------------------
 *
 * Der Wirt hat es am Kassenbericht aufgemalt und dazu gesagt: *„кстати ты можешь Verlauf тоже
 * сделать как на фото 2"*. Also dieselbe Ordnung: die Spalte daneben ist weg, oben die drei
 * Striche, die sie holen, unten ueber die ganze Breite der Weg zurueck.
 *
 * Nur auf dem schmalen Bildschirm: auf dem grossen Kassen-Bildschirm ist die linke Spalte der
 * BON und nicht das Menue — der darf nicht verschwinden, waehrend man nachsieht.
 */
@media (max-width: 1199px) {
    /*
     * Die Spalte ist eine SPUR im Raster des <body>. Sie bloss auf `display: none` zu setzen
     * genuegt nicht: die Spur bleibt stehen, und der Verlauf hoerte weiter bei 255 von 412 px
     * auf (gemessen).
     *
     * Die Spur schmaler zu machen half auch nicht: `grid-template-columns` am <body> zu
     * aendern blieb wirkungslos, selbst inline und mit `!important` (gemessen: 142px 270px
     * blieb 142px 270px). Also nicht an den Spuren drehen, sondern den Bereich ueber BEIDE
     * legen — das ist ohnehin die ehrlichere Ansage: der Verlauf nimmt die ganze Zeile.
     */
    body.kasse-verlauf-offen #kasseProductsSection { grid-column: 1 / -1; }
    body.kasse-verlauf-offen .kasse-spalte-links { display: none; }
    /*
     * UND UEBER DEN GANZEN BILDSCHIRM (07.09.2026, Ansage des Wirts: *„как на приложении, имею
     * ввиду на весь экран"*).
     *
     * Im Programm ist „Buchung" ein eigener Bildschirm: keine Suchleiste darueber, keine
     * Warenkorb-Leiste darunter, nur Titel, Suche, Liste und „Zurück". Im Browser lag sie
     * dazwischen — oben der Tisch mit der Produktsuche, unten „Bezahlen" (gemessen: 139 px
     * oben, 72 px unten, 704 von 915 blieben uebrig).
     *
     * Beide Leisten sind Zeilen im Raster des <body> (`auto minmax(0,1fr) auto`). Nimmt man
     * sie weg, fallen ihre Zeilen auf null zusammen und die mittlere bekommt alles — ohne dass
     * an der Buchungsseite selbst etwas gerechnet werden muss.
     *
     * Der Weg zurueck bleibt: der Knopf ganz unten — und von dort der Wuerfel, wie im
     * Programm. (Der Menue-Knopf oben rechts stand hier einen halben Tag lang; der Wirt hat
     * ihn durchgestrichen, sobald die Seite den ganzen Bildschirm bekam.)
     */
    body.kasse-verlauf-offen .kasse-search-bar,
    body.kasse-verlauf-offen .kasse-bottom-bar { display: none; }
    /* Die Sprechblase „wird gesendet" sass ueber der Warenkorb-Leiste. Die ist jetzt weg —
       ohne diese Zeile laege sie auf dem Knopf „Zurück". */
    body.kasse-verlauf-offen .outbox-badge { bottom: 86px; }
    /* Ohne die Suchleiste darueber beginnt die Seite ganz oben — in der installierten App
       liegt dort die Statusleiste des Telefons. Dasselbe Polster, das sonst die Suchleiste
       traegt. */
    body.kasse-verlauf-offen #kasseVerlaufPanel {
        padding-top: 0;   /* die sichere Zone traegt `.kopf-fest` (26.09.2026) */
    }
}
.kasse-verlauf-fuss {
    /* „самом внизу" heisst: immer sichtbar, nicht am Ende einer langen Liste. `sticky` klebt
       ihn an den unteren Rand der Flaeche, solange man rollt — mit eigenem Grund, sonst
       laesen die Karten darunter durch. */
    position: sticky;
    /* -16px, weil die Flaeche darum (section) 16 px Polster unten hat: `bottom: 0` klebte den
       Streifen an die POLSTERKANTE, und im Polster darunter sah man den naechsten Beleg
       durchlaufen. Gemessen: Leiste endete bei 827, die Flaeche bei 843. */
    bottom: -16px;
    margin-top: auto;
    padding: 14px 0 30px;
    display: flex;
    background: var(--djk-black);
}
.kasse-verlauf-fuss .btn { flex: 1; justify-content: center; gap: 8px; }

/* Die Reiter sind bewusst dieselben Bauteile wie auf der Verlauf-Seite (.admin-tabs /
   .admin-tab-btn) — es ist dieselbe Auswahl, sie soll auch gleich aussehen. */
#kasseVerlaufTabs { margin: 12px 0 14px; }

.kasse-verlauf-inhalt { display: flex; flex-direction: column; gap: 10px; }
/* Eine Karte je Eintrag — dieselbe Machart wie die Verlauf-Seite auf dem Handy, wo aus jeder
   Tabellenzeile eine Karte wird (assets/js/tabellen_mobil.js). Hier direkt so gebaut, statt
   erst eine Tabelle zu erzeugen, die anschließend umgeformt wird. */
.kasse-verlauf-karte {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    overflow: hidden;
    width: 100%;
    text-align: left;
    color: inherit;
    font: inherit;
    padding: 0;
}
button.kasse-verlauf-karte { cursor: pointer; }
.kasse-verlauf-karte-kopf {
    padding: 8px 12px;
    border-bottom: 1px solid var(--djk-border);
    font-weight: 700;
    font-size: 0.85rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.kasse-verlauf-zeile {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 7px 12px;
    font-size: 0.82rem;
}
.kasse-verlauf-zeile + .kasse-verlauf-zeile { border-top: 1px dashed var(--djk-border); }
.kasse-verlauf-zeile > span:first-child { opacity: 0.7; text-transform: uppercase; font-size: 0.7rem; letter-spacing: .03em; }
.kasse-verlauf-zeile > span:last-child { font-weight: 600; text-align: right; }
.kasse-verlauf-zeile.hervor > span:last-child { color: var(--djk-yellow); font-weight: 800; }
/* Zurückgenommener Verkauf und Gegenbuchung — dieselbe Sprache wie in der Verlauf-Liste. */
.kasse-verlauf-karte.ist-storniert { opacity: 0.62; }
.kasse-verlauf-karte.ist-storniert .kvz-betrag { text-decoration: line-through; }
.kasse-verlauf-karte.ist-storno .kvz-betrag { color: var(--djk-danger); }
.kasse-verlauf-leer { opacity: 0.6; padding: 10px 2px; }

/* Aufklappbare Verlauf-Karte: der Pfeil dreht sich, die Positionen erscheinen darunter. */
.kasse-verlauf-karte .kvk-pfeil { transition: transform var(--transition); opacity: 0.6; }
.kasse-verlauf-karte.ist-offen .kvk-pfeil { transform: rotate(180deg); }
.kasse-verlauf-posten { display: none; }
.kasse-verlauf-karte.ist-offen .kasse-verlauf-posten {
    display: block;
    border-top: 1px solid var(--djk-border);
    padding: 6px 12px 10px;
}
.kvp-zeile { display: flex; gap: 8px; padding: 3px 0; font-size: 0.82rem; }
.kvp-zeile .kvp-menge { font-weight: 700; flex: 0 0 auto; }
.kvp-zeile small { display: block; opacity: 0.7; font-size: 0.72rem; }

/* Mein Profil: drei änderbare Felder, alles andere steht als Karte darüber. */
.kasse-profil-feld { display: flex; flex-direction: column; gap: 4px; }
.kasse-profil-feld label { font-size: 0.78rem; font-weight: 600; opacity: 0.75; }

.kasse-verlauf-abmelden {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 20px;
    align-self: stretch;
}

/* Storno-Vermerk auf dem Bon selbst: sichtbar, aber ohne Farbfläche — der Beleg ist ein
   Dokument, kein Warnschild. */
.beleg-storno-hinweis {
    margin: -8px 0 14px;
    padding: 6px 8px;
    border: 1px solid var(--djk-danger);
    color: var(--djk-danger);
    font-size: 0.78rem;
    text-align: center;
    line-height: 1.35;
}

/* In der Betriebsart "Extras erst beim langen Drücken" (Verwaltung → Kasse) wird die
   Produktkachel gehalten. Ohne diese Zeilen fängt Android dabei an, den Produktnamen zu
   markieren, und blendet die Auswahl-Sprechblase ein — der lange Druck fühlt sich dann kaputt
   an, obwohl er funktioniert. Das Kontextmenü selbst unterdrückt bereits kasse.js. */
.product-tile {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

/* ---------- Reservierungen: Tageszahlen, Status, Handgriffe ----------
   Der Tag ist die Arbeitsebene im Service — der Monat beantwortet "wann ist noch frei", der Tag
   "was passiert heute Abend". Deshalb stehen die drei Zahlen über der Liste und die Handgriffe
   direkt an der Zeile, statt hinter einem Fenster. */
.reserv-tag-zahlen {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    margin-bottom: 12px;
}
.reserv-tag-zahl {
    background: var(--djk-black-soft);
    border-radius: var(--radius);
    padding: 8px 10px;
}
.reserv-tag-zahl span { display: block; font-size: 0.72rem; opacity: 0.7; }
.reserv-tag-zahl strong { font-size: 1.25rem; font-weight: 700; }

/* --- Die Spitze des Tages (05.09.2026) --------------------------------------------------
 * Ein Satz und ein Balken unter den drei Kacheln: "Am vollsten um 19:00 - 24 von 240".
 * Vier Kacheln passen auf einem Telefon nicht in eine Zeile, und die Spitze ist ohnehin
 * ein Satz - erst der Vergleich mit den Plaetzen macht die Zahl lesbar.
 * Farben aus den vorhandenen Variablen; nichts Neues erfunden.
 */
.reserv-spitze { margin-top: 10px; }
.reserv-spitze-text { font-size: 0.86rem; opacity: 0.85; }
.reserv-spitze-text strong { font-weight: 700; opacity: 1; }
.reserv-spitze-spur {
    margin-top: 5px; height: 6px; border-radius: 999px;
    background: var(--border-color, rgba(148,163,184,.25));
    overflow: hidden;
}
.reserv-spitze-spur i {
    display: block; height: 100%; border-radius: 999px;
    background: var(--primary-color, #3b82f6);
}
/* Eingefärbt wird nur, was jemand tun muss. */
.reserv-tag-zahl.ist-offen { background: rgba(245, 158, 11, 0.14); }
.reserv-tag-zahl.ist-offen span,
.reserv-tag-zahl.ist-offen strong { color: var(--djk-copper); opacity: 1; }

.reserv-eintrag-ende { display: block; font-size: 0.68rem; opacity: 0.65; font-weight: 400; }

/* Farbe am linken Rand = Zustand auf einen Blick, ohne den Text zu lesen. */
.reserv-eintrag.reserv-status-da { border-left: 4px solid var(--djk-success); }
.reserv-eintrag.reserv-status-fertig { opacity: 0.65; }
.reserv-eintrag.reserv-status-nicht_erschienen { border-left: 4px solid var(--djk-danger); opacity: 0.75; }

/* Die Grundform des Chips ist ein VOLL gefüllter roter Pillenknopf mit weißer Schrift (siehe
   .reserv-eintrag-tag weiter oben). Ein Modifikator muss deshalb den Grund mitsetzen — nur die
   Textfarbe zu ändern ergäbe grüne Schrift auf rotem Grund. */
.reserv-eintrag-tag.reserv-tag-da { background: var(--djk-success); color: #fff; }
.reserv-eintrag-tag.reserv-tag-fertig { background: var(--djk-gray); color: #fff; }
.reserv-eintrag-tag.reserv-tag-nicht_erschienen { background: var(--djk-danger); color: #fff; }

.reserv-eintrag-aktionen { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.reserv-eintrag-aktionen .btn { flex: 1 1 auto; min-width: 104px; padding: 7px 10px; font-size: 0.78rem; }
.reserv-eintrag-aktionen .reserv-aktion-warnung { border-color: var(--djk-danger); color: var(--djk-danger); }

/* ---------- Reservierungen: Belegungsband, Gästehistorie, Warteliste ----------
   Das Band ist die Ansicht, mit der jedes Reservierungsprogramm arbeitet: Tische senkrecht,
   Zeit waagerecht. Es ist der Grund, warum eine Reservierung eine Dauer braucht — erst dadurch
   wird aus einem Zeitpunkt ein Balken. */
.reserv-band-wrap { overflow-x: auto; overscroll-behavior-x: contain; margin-bottom: 14px; }
.reserv-band { min-width: 420px; }
.reserv-band-zeile { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.reserv-band-tisch { flex: 0 0 46px; font-size: 0.72rem; color: var(--djk-gray); }
.reserv-band-spur {
    position: relative;
    flex: 1 1 auto;
    height: 26px;
    background: var(--djk-black-soft);
    border-radius: var(--radius);
}
.reserv-band-kopf .reserv-band-stunde {
    flex: 1 1 0;
    font-size: 0.68rem;
    color: var(--djk-gray);
    text-align: left;
}
/* Der Balken sitzt absolut auf der Spur — Anfang und Breite kommen als Prozent aus der
   Uhrzeit, damit sich die Skala mit dem Abend selbst dehnt. */
.reserv-band-balken {
    position: absolute;
    top: 3px;
    bottom: 3px;
    display: flex;
    align-items: center;
    padding: 0 6px;
    border-radius: var(--radius);
    background: var(--djk-yellow);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
}
.reserv-band-balken.reserv-band-unbestaetigt { background: var(--djk-copper); }
.reserv-band-balken.reserv-band-da { background: var(--djk-success); }
.reserv-band-balken.reserv-band-fertig { background: var(--djk-gray); }
.reserv-band-balken.reserv-band-warteliste { background: var(--djk-blue); }

.reserv-block-titel {
    font-size: 0.78rem;
    font-weight: 700;
    opacity: 0.7;
    margin: 4px 0 8px;
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* Was wir über den Gast wissen — leise, aber lesbar: es soll die Zeile ergänzen, nicht mit ihr
   um Aufmerksamkeit streiten. */
.reserv-gast-historie { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.reserv-gast-stamm, .reserv-gast-warnung {
    font-size: 0.68rem;
    font-weight: 700;
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid var(--djk-border);
}
.reserv-gast-stamm { color: var(--djk-success); border-color: var(--djk-success); }
.reserv-gast-warnung { color: var(--djk-danger); border-color: var(--djk-danger); }

.reserv-eintrag.reserv-status-warteliste { border-left: 4px solid var(--djk-blue); }
.reserv-eintrag-tag.reserv-tag-warteliste { background: var(--djk-blue); color: #fff; }

/* source/style_css/370_reservations_day_cards.css - style.css part 53 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Reservierungen: Tag zuerst ----------
   Kopfzeile mit Wochentag, darunter der Streifen aus fünf Tagen. Der Monat steckt hinter dem
   Kalender-Symbol: er beantwortet "wann ist noch frei", der Tag "was passiert heute Abend" —
   und im Dienst zählt die zweite Frage. */
.reserv-tag-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}
.reserv-tag-kopf h3 { margin: 0; font-size: 1.05rem; }
.reserv-monat-knopf {
    flex: 0 0 auto;
    background: none;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 7px 9px;
    color: inherit;
    cursor: pointer;
    line-height: 0;
}
.reserv-monat-knopf.active { border-color: var(--djk-yellow); color: var(--djk-yellow); }

.reserv-tagstreifen { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; margin-bottom: 14px; }
.reserv-streifen-tag {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    padding: 8px 2px;
    color: inherit;
    font: inherit;
    cursor: pointer;
}
.reserv-streifen-tag .rst-wochentag { font-size: 0.62rem; opacity: 0.6; letter-spacing: .05em; }
.reserv-streifen-tag .rst-zahl { font-size: 1rem; font-weight: 700; }
/* Die Gästezahl steht klein darunter — leer, wenn nichts los ist: eine 0 an jedem freien Tag
   wäre nur Rauschen. */
.reserv-streifen-tag .rst-gaeste { font-size: 0.68rem; opacity: 0.7; min-height: 1em; }
.reserv-streifen-tag.active {
    background: var(--djk-yellow);
    border-color: var(--djk-yellow);
    color: #fff;
}
.reserv-streifen-tag.active .rst-wochentag,
.reserv-streifen-tag.active .rst-gaeste { opacity: 0.9; }
/* Ein Tag mit unbestätigten Anfragen bekommt einen Punkt — dort muss jemand etwas tun. */
.reserv-streifen-tag.hat-offen { border-color: var(--djk-copper); }

/* Die Woche mit Anfang und Ende, und zwei Pfeilen daneben. Sieben Kacheln passen auf ein
   Telefon, wenn man ihnen die Luft nimmt - deshalb weniger Abstand und ein kleinerer Rand. */
.reserv-wochenleiste { display: flex; align-items: center; gap: 4px; margin-bottom: 12px; }
.reserv-wochenleiste .reserv-tagstreifen { flex: 1; margin-bottom: 0; }
.reserv-wochenleiste .btn { flex: 0 0 auto; padding: 6px 8px; line-height: 1; }
.reserv-streifen-tag { padding: 8px 1px; }
/* Wie voll der Tag wird - gemessen an den Plaetzen des Hauses. Ein Strich sagt das schneller
   als eine Zahl, die man erst ins Verhaeltnis setzen muss. */
.rst-last { display: block; width: 80%; height: 3px; border-radius: 2px; background: var(--djk-border); overflow: hidden; margin-top: 3px; }
.rst-last i { display: block; height: 100%; background: var(--djk-yellow); }
.reserv-streifen-tag.active .rst-last { background: rgba(255, 255, 255, 0.35); }
.reserv-streifen-tag.active .rst-last i { background: #fff; }
/* Heute bekommt eine ruhige Kante - ohne sie sucht man in der Woche den heutigen Tag. */
.reserv-streifen-tag.ist-heute { border-color: var(--djk-yellow); }


/* Die Karte ist jetzt gestapelt, nicht mehr zweispaltig: die Grundregel weiter oben stellt sie
   als flex-Zeile auf (Zeit links, Rest rechts) — das war der alte Aufbau. */
.reserv-eintrag {
    display: block;
    border-left: 4px solid transparent;
}
.reserv-eintrag-kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.reserv-eintrag-titel { font-size: 0.95rem; font-weight: 700; }
.reserv-eintrag-tisch { flex: 0 0 auto; font-size: 0.78rem; opacity: 0.7; white-space: nowrap; }
.reserv-eintrag-ende { font-size: 0.72rem; opacity: 0.6; }

/* Vorschau im Reservierungs-Formular: was die Eingabe bedeutet, bevor gespeichert wird. */
.reserv-form-folge {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    background: var(--djk-black-soft);
    border-radius: var(--radius);
    padding: 8px 10px;
    font-size: 0.8rem;
    opacity: 0.9;
}
.reserv-form-folge .reserv-form-warnung { color: var(--djk-danger); font-weight: 700; opacity: 1; }

/* ---------- Reservierungs-Karte: ruhig, Farbe nur an der Kante ----------
   Die Grundregeln weiter oben färben die ganze Karte ein (grün für heute, orange für
   unbestätigt). Bei drei Karten untereinander wird der Bildschirm dadurch zum Farbkasten und
   der Blick findet nichts mehr. Die Aussage steckt in der Kante links und im Chip — beide
   reichen, und der Text bleibt gut lesbar. */
.reserv-tag-panel .reserv-eintrag,
.reserv-tag-panel .reserv-eintrag-heute,
.reserv-tag-panel .reserv-eintrag-unbestaetigt {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
}
.reserv-tag-panel .reserv-eintrag-heute:hover,
.reserv-tag-panel .reserv-eintrag-unbestaetigt:hover { background: var(--djk-black-soft); }
.reserv-tag-panel .reserv-eintrag-unbestaetigt { border-left: 4px solid var(--djk-copper); }
.reserv-tag-panel .reserv-eintrag.reserv-status-da { border-left: 4px solid var(--djk-success); }
.reserv-tag-panel .reserv-eintrag.reserv-status-warteliste { border-left: 4px solid var(--djk-blue); }

/* Die Handgriffe: klein genug, dass zwei nebeneinander passen — sonst steht unter jeder Karte
   ein Knopfturm und die nächste Reservierung rutscht aus dem Bild. */
.reserv-eintrag-aktionen .btn {
    flex: 1 1 40%;
    min-width: 0;
    padding: 6px 8px;
    font-size: 0.72rem;
}

/* Kopfzahlen kompakter — sie sind Beiwerk, nicht die Hauptsache. */
.reserv-tag-zahl { padding: 6px 8px; }
.reserv-tag-zahl strong { font-size: 1.05rem; }

/* "+ Neue Reservierung" gehört an den Rand, nicht über die volle Breite. */
.reserv-tag-panel-header { display: flex; justify-content: flex-end; margin-bottom: 10px; }

/* ---------- Reservierungs-Karte (Detailfenster) ----------
   Kopf, Gast, Kontakt, Felder, Handlungen — in dieser Reihenfolge, weil man die Karte so liest:
   erst wer und woher, dann was zu ändern ist, zuletzt was zu tun ist. */
.reserv-detail-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin: 0 0 6px;
}
.reserv-detail-kopf h3 { margin: 0; font-size: 1.05rem; }
.reserv-detail-marken { display: flex; gap: 6px; flex-wrap: wrap; }
.reserv-detail-marken .reserv-eintrag-tag { margin-left: 0; }

.reserv-detail-gast { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.reserv-detail-gast .rdg-name { font-size: 1.1rem; font-weight: 700; }
.reserv-detail-gast .reserv-gast-historie { margin-top: 0; }

/* Kontakt als Knöpfe: "anrufen" ist die häufigste Handlung an dieser Karte. */
.reserv-detail-kontakt { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.reserv-detail-kontakt .btn { padding: 6px 12px; font-size: 0.8rem; }
.reserv-detail-kontakt .rdk-wert { font-size: 0.82rem; opacity: 0.7; }

/* Die Nachricht des Gastes steht für sich — sie enthält oft das Entscheidende. */
.reserv-detail-nachricht {
    background: var(--djk-black-soft);
    border-left: 3px solid var(--djk-border);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: 8px 12px;
    margin-bottom: 14px;
    font-size: 0.85rem;
    line-height: 1.5;
}

/* Die Handlungen bleiben unten stehen, auch wenn die Karte lang wird. */
.reserv-detail-aktionen {
    position: sticky;
    bottom: 0;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 16px;
    /* Rundum 12px statt nur oben: die Leiste hat einen eigenen Grund, und ohne seitliches
       Polster klebten die Knöpfe am Rand des Fensters. */
    padding: 12px;
    border-top: 1px solid var(--djk-border);
    /* Fester Grund, kein `inherit`: der Elternteil ist das <form>, und das ist durchsichtig —
       die haftende Leiste liess deshalb den Inhalt hinter sich durchscrollen. Der Wert ist der
       des Fensters selbst (.modal-box), damit die Leiste als dessen Boden gelesen wird. */
    background: #dedede;
}
.reserv-detail-aktionen .btn { flex: 1 1 auto; }
.reserv-detail-aktionen .reserv-detail-absagen { color: var(--djk-danger); border-color: var(--djk-danger); }

/* Zwei Spalten, sobald Platz ist: Datum/Zeit und Personen/Tisch gehören paarweise zusammen. */
@media (min-width: 480px) {
    #reservDetailForm .form-grid,
    #reservForm .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
    #reservDetailForm .form-grid > .field:nth-child(3),
    #reservDetailForm .form-grid > .reserv-form-folge,
    #reservForm .form-grid > .reserv-form-folge { grid-column: 1 / -1; }
}

/* Herkunfts-Marke: neutral, nicht alarmrot. Sie erbte die Grundform des Storno-Chips
   (voll gefülltes Rot) — "kommt von der Webseite" ist aber eine Auskunft, keine Warnung. */
#reservDetailHerkunftBadge { background: var(--djk-yellow); color: #fff; }

/* [hidden] gewinnt NICHT gegen ein display des Autors — dieselbe Falle wie beim Kassen-Menü.
   Ohne diese Zeile stand die Vorschau als leerer grauer Balken im Formular, obwohl sie
   ausgeblendet sein sollte. */
.reserv-form-folge[hidden] { display: none; }

/* Freie Tische als Knoepfe, nicht als Liste: ein Tipp, und der Tisch steht im Feld. Die Zahl
   im Chip sind die Plaetze - sie beantwortet die einzige Rueckfrage, die sonst kommt. */
.reserv-tischvorschlag {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}
.reserv-tischvorschlag[hidden] { display: none; }
.rtv-titel { flex: 1 0 100%; font-size: 0.78rem; opacity: 0.7; }
.rtv-titel.rtv-warn { color: var(--djk-danger); opacity: 1; font-weight: 700; }
.rtv-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    background: var(--djk-black-soft);
    color: inherit;
    font: inherit;
    font-size: 0.82rem;
    line-height: 1.2;
    cursor: pointer;
}
.rtv-chip:hover { border-color: var(--djk-yellow); }
.rtv-chip.aktiv { background: var(--djk-yellow); border-color: var(--djk-yellow); color: #fff; }
.rtv-plaetze { font-size: 0.72rem; opacity: 0.75; }
.rtv-rest { font-size: 0.76rem; opacity: 0.6; align-self: center; }

/* Gast ohne Reservierung: der Kasten oeffnet sich unter dem Knopf und schliesst sich, sobald
   der Gast sitzt. Er ist bewusst kein Fenster - ein Fenster nimmt die Sicht auf das Band. */
.reserv-walkin { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 6px 0 10px; }
.reserv-walkin[hidden] { display: none; }
.reserv-walkin input[type="number"] { width: 5rem; }
.reserv-walkin-knopf { margin-right: 6px; }

.rtv-chip.aktiv .rtv-plaetze { opacity: 0.95; }

/* Das Belegungsband ist eine Arbeitsfläche, kein Bild: der Balken öffnet die Karte, die freie
   Spur legt an dieser Stelle an. Deshalb sehen beide anfassbar aus. */
.reserv-band-balken { border: none; cursor: pointer; font-family: inherit; }
.reserv-band-balken:hover { filter: brightness(1.08); }

/* Ziehen: der Finger soll den Balken bewegen und nicht die Seite scrollen. */
.reserv-band-balken { touch-action: none; }
.reserv-band-balken.zieht { opacity: 0.35; }
.reserv-band-geist {
    pointer-events: none;
    z-index: 9999;
    opacity: 0.92;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
    left: 0;
    top: 0;
}
/* Die Zeile, auf der er landen wuerde. Ohne diese Markierung trifft man auf dem Telefon
   regelmaessig eine Zeile daneben - der Finger verdeckt genau die Stelle, um die es geht. */
.reserv-band-spur.ziel { background: rgba(255, 193, 7, 0.18); outline: 1px dashed var(--djk-yellow); }

.reserv-band-spur { cursor: crosshair; }
.reserv-band-umschalter {
    background: none;
    border: none;
    padding: 2px 0 10px;
    color: var(--djk-yellow);
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
    text-decoration: underline;
}

/* ---------- Reservierungen: kantig und leise ----------
   Zwei Änderungen nach dem Entwurf:

   1. Keine runden Ecken. Die Kasse ist im übrigen Haus schon kantig (Bon-Leiste, Modale) —
      die Reservierungen waren die letzte Ecke mit Radius.
   2. Die Status-Chips waren voll gefüllte, kräftige Pillen. Sie erbten die Form des
      Storno-Chips, und bei drei Karten untereinander schrie der Bildschirm. Jetzt: zarter Grund
      in der Farbe, Schrift in derselben Farbe kräftig — lesbar, ohne den Namen des Gastes zu
      übertönen. Die Farbe bleibt dieselbe, nur die Lautstärke sinkt. */
.reserv-eintrag,
.reserv-tag-zahl,
.reserv-streifen-tag,
.reserv-band-spur,
.reserv-band-balken,
.reserv-detail-nachricht,
.reserv-form-folge,
.reserv-eintrag-aktionen .btn,
.reserv-detail-kontakt .btn { border-radius: 0; }

.reserv-eintrag-tag {
    border-radius: 0;
    padding: 2px 8px;
    font-weight: 700;
    /* Grundton: neutral. Jeder Status setzt darunter seinen eigenen. */
    background: rgba(100, 116, 139, 0.14);
    color: var(--djk-gray);
}
.reserv-eintrag-tag-unbestaetigt,
.reserv-eintrag-tag.reserv-tag-unbestaetigt { background: rgba(245, 158, 11, 0.18); color: #b45309; }
.reserv-eintrag-tag.reserv-tag-da { background: rgba(16, 185, 129, 0.16); color: #047857; }
.reserv-eintrag-tag.reserv-tag-fertig { background: rgba(100, 116, 139, 0.14); color: var(--djk-gray); }
.reserv-eintrag-tag.reserv-tag-abgesagt,
.reserv-eintrag-tag.reserv-tag-nicht_erschienen { background: rgba(239, 68, 68, 0.14); color: #b91c1c; }
.reserv-eintrag-tag.reserv-tag-warteliste { background: rgba(139, 92, 246, 0.16); color: #6d28d9; }
#reservDetailHerkunftBadge { background: rgba(59, 130, 246, 0.16); color: var(--djk-yellow-dark); }

/* Auch die Gäste-Chips leiser: sie stehen unter dem Namen und sollen ihn nicht überstimmen. */
.reserv-gast-stamm, .reserv-gast-warnung { border-radius: 0; border: none; padding: 2px 8px; }
.reserv-gast-stamm { background: rgba(16, 185, 129, 0.14); color: #047857; }
.reserv-gast-warnung { background: rgba(239, 68, 68, 0.13); color: #b91c1c; }

/* Der Storno-Chip in der Beleg-Liste bleibt, wie er war — dort IST er eine Warnung. */

/* ---------- Dunkles Erscheinungsbild (Verwaltung → Kasse → App & Bedienung) ----------
   Nur ein Satz getauschter Variablen, kein zweites Stylesheet: der gesamte Staff-Bereich ist
   auf --djk-black / --djk-black-soft / --djk-black-card / --djk-white / --djk-border aufgebaut,
   und wer die tauscht, dreht damit die ganze Oberfläche um.

   Die Reihenfolge der Stufen bleibt dieselbe wie im Hellen — black = Seitengrund (am dunkelsten),
   soft = leicht abgesetzte Fläche, card = die Karte darüber (am hellsten). Nur die Richtung
   kehrt sich um. Dadurch stimmen alle bestehenden Regeln weiter, ohne dass eine davon weiß,
   dass es überhaupt zwei Erscheinungsbilder gibt.

   Die Akzentfarben werden eine Spur heller: dieselben Töne wie im Hellen wirken auf dunklem
   Grund matt und verlieren an Kontrast zur Schrift. */
body.thema-dunkel {
    --djk-black: #16181d;
    --djk-black-soft: #1e2128;
    --djk-black-card: #242830;
    --djk-white: #e9ecf2;
    --djk-gray: #949cab;
    --tisch-stuhl: #7c8aa0;
    --tisch-stuhl-rand: #9aa6b6;
    --djk-border: #333a46;
    --djk-yellow: #60a5fa;
    --djk-yellow-dark: #3b82f6;
    --djk-blue: #a78bfa;
    --djk-blue-light: #c4b5fd;
    --djk-danger: #f87171;
    --djk-success: #34d399;
    --djk-copper: #fbbf24;
    --shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
}
/* Der Seitengrund selbst hängt an html/body und wird oben fest gesetzt — hier nachziehen.
   Am <html> steht der Wert AUSGESCHRIEBEN und nicht als var(--djk-black): die dunklen Variablen
   liegen auf `body.thema-dunkel`, und ein Elternteil erbt nichts von seinem Kind. `html` bekam
   deshalb den HELLEN Wert (#f8fafc) — auf dem großen Bildschirm sah man das als weißen Streifen
   über der Kasse, überall dort, wo der Body nicht ganz bis an den Rand reicht. */
body.thema-dunkel { background: var(--djk-black); }
html:has(body.thema-dunkel) { background: #16181d; }

/* Eingabefelder tragen im Hellen einen weißen Grund fest verdrahtet (Abschnitt BEDIENELEMENTE).
   Ohne diese Zeilen stünden schneeweiße Kästen in einer dunklen Oberfläche. */
body.thema-dunkel {
    --feld-grund: #1b1e25;
    --feld-rand: #3a4250;
    /* Der Pfeil der Auswahllisten wird über DIESE Variable getauscht, nicht über eine eigene
       background-image-Regel. Sonst greift man an der Grundregel vorbei, die auch
       background-repeat und -position setzt — und der Pfeil kachelt sich über das ganze Feld. */
    --feld-pfeil: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23949cab' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}
/* background-COLOR, nicht die Kurzform: `background` würde Bild, Wiederholung und Position
   mit zurücksetzen — genau daran kachelte der Pfeil quer durchs Auswahlfeld. */
body.thema-dunkel input,
body.thema-dunkel select,
body.thema-dunkel textarea {
    background-color: #1b1e25;
    color: var(--djk-white);
    border-color: #3a4250;
}
body.thema-dunkel input::placeholder,
body.thema-dunkel textarea::placeholder { color: #6b7382; }

/* Die Status-Chips der Reservierungen haben im Hellen dunkle Schrift auf zartem Grund — auf
   dunklem Grund braucht es umgekehrt helle Schrift. */
body.thema-dunkel .reserv-eintrag-tag-unbestaetigt,
body.thema-dunkel .reserv-eintrag-tag.reserv-tag-unbestaetigt { color: #fcd34d; }
body.thema-dunkel .reserv-eintrag-tag.reserv-tag-da,
body.thema-dunkel .reserv-gast-stamm { color: #6ee7b7; }
body.thema-dunkel .reserv-eintrag-tag.reserv-tag-abgesagt,
body.thema-dunkel .reserv-eintrag-tag.reserv-tag-nicht_erschienen,
body.thema-dunkel .reserv-gast-warnung { color: #fca5a5; }
body.thema-dunkel .reserv-eintrag-tag.reserv-tag-warteliste { color: #c4b5fd; }
body.thema-dunkel #reservDetailHerkunftBadge { color: #93c5fd; }

/* source/style_css/375_reservations_day_cards_continued.css - style.css: reservations day cards continued, part 54 of 78 (built by werkzeuge/parts_build.php) */
/* Zwei Flächen tragen ihren Grund fest verdrahtet, weil sie durchscheinend sind (Milchglas):
   die obere Leiste und die untere Navigation. Ein Variablentausch erreicht sie nicht — sie
   blieben als helle Balken in einer dunklen App stehen. */
body.thema-dunkel .site-header { background: rgba(22, 24, 29, 0.92); }
/* Die Kopfleiste der Personal-Seiten (Kueche/Bar am grossen Schirm) ohne Unschaerfe und deckend
   (26.09.2026) — dieselbe Regel wie `.kopf-fest`: was darunter durchrollt, verschwimmt nicht. */
body.personal-body .site-header { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--djk-black); }
body.thema-dunkel .bottom-nav { background: rgb(22 24 29 / 88%); }
/* A-/A+ tragen kein Sinnbild und damit auch keine ikon-Farbe -- im dunklen Thema waeren
   sie sonst dunkelgrau auf dunkelgrau. */
body.thema-dunkel .bottom-nav-zeichen { color: var(--djk-text, #e8eaed); }
/*
 * Die Beschriftungen HELLER im dunklen Thema (25.08.2026).
 *
 * `--djk-gray` ist #64748b und stand damit auf einem fast schwarzen Grund -- auf dem Foto des
 * Wirts war "Kueche" kaum zu lesen. In der Kueche schaut niemand zweimal hin: entweder das
 * Wort ist da oder der Knopf ist es nicht. Die Sinnbilder darueber behalten ihre Farbe.
 */
body.thema-dunkel .bottom-nav--voll a,
body.thema-dunkel .bottom-nav--voll button { color: #cbd5e1; }
body.thema-dunkel .bottom-nav--voll a.active { color: var(--djk-yellow); }

/* Der Produktbereich der Kasse trägt einen fest verdrahteten hellen Verlauf (heller Himmel oben,
   weiß unten). Im Dunkeln dieselbe Idee, nur andersherum. */
body.thema-dunkel.kasse-body #kasseProductsSection {
    background: linear-gradient(180deg, #1a1f2b 0%, var(--djk-black) 65%);
}
/* Offener Verlauf (26.09.2026): die rollende Flaeche ohne Polster oben und ohne Verlauf im Grund.
   Das Polster (10 px) lag UEBER dem festen Kopf — dort liefen die Belege durch; und gegen den
   Farbverlauf haette sich der deckende Kopf als Kasten abgesetzt. Die Luft traegt jetzt der Kopf. */
body.kasse-body.kasse-verlauf-offen #kasseProductsSection { padding-top: 0; background: var(--djk-black); }
/* Die Farbe der Produkt- und Kategorie-Kacheln kommt aus der Verwaltung (akzent_farbe je
   Produkt/Kategorie) und bleibt in beiden Erscheinungsbildern dieselbe — sie ist eine
   Zuordnung, kein Design. Kacheln OHNE eigene Farbe erben den Grund der Karte.

   UND WER EINE ZUSTANDSFARBE TRAEGT, BEHAELT SIE AUCH (03.09.2026): blau frei, gruen
   bereit, rot es wartet noch etwas. Die steht in der KLASSE statt inline — ohne die Ausnahme
   gewann diese Regel (0,3,1 gegen 0,2,0) und loeschte mit der Kurzform `background:` sogar
   den Verlauf. Im Dunkeln sah dann jeder Tisch gleich aus.

   Ausgenommen wird der ZUSTAND, nicht der Klassenname: die Tischkachel, das Gruppen-Zeichen
   und die Kachel im Gruppen-Fenster tragen dieselben drei Klassen, und die naechste Stelle,
   die diese Farbsprache spricht, ist damit von selbst dabei. */
body.thema-dunkel .product-tile:not([style*="background"]):not(.tisch-frei):not(.tisch-bereit):not(.tisch-wartet) { background: var(--djk-black-card); }

/* Das Suchfeld hat jetzt in BEIDEN Erscheinungsbildern einen dunklen Grund. Schrift, Platzhalter
   und Lupe müssen deshalb fest hell sein: `var(--djk-white)` ist im hellen Erscheinungsbild
   dunkel — der Text wäre dort unlesbar geworden. */
.kasse-search-bar .input-icon input { color: #f2f4f8; }
.kasse-search-bar .input-icon input::placeholder { color: #9aa3b2; }
.kasse-search-bar .input-icon .input-icon-glyph { color: #9aa3b2; }
.kasse-search-bar .input-icon .password-toggle { color: #cfd5df; }

/* source/style_css/380_dark_theme_journal.css - style.css part 55 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Dunkles Erscheinungsbild: Flächen der Bedienelemente ----------
   Kacheln, Warenkorbzeilen, Zahlungsarten, Ziffernblock, Präfix-Knöpfe und die Fenster selbst
   bekommen einen eigenen, ruhigen Grund.

   NUR im dunklen Erscheinungsbild. Im hellen ist die Schrift dieser Bauteile dunkel
   (--djk-white ist dort fast schwarz) — auf #20201f wäre sie schlicht weg. Wer beides will,
   nimmt die Klasse vorn heraus; dann muss aber jede dieser Schriftfarben mitgezogen werden. */
/* Wer eine ZUSTANDSFARBE traegt, ist hier ausgenommen (03.09.2026) — und zwar unter beiden
   Namen, denn eine Tischkachel traegt `product-tile kategorie-tile tisch-tile` zugleich. Ihr
   Grund sagt den Zustand (blau frei, gruen bereit, rot es wartet noch etwas); ein ruhiger
   Grund darueber macht aus drei Auskuenften eine. */
body.thema-dunkel .product-tile:not(.tisch-frei):not(.tisch-bereit):not(.tisch-wartet),
body.thema-dunkel .kategorie-tile:not(.tisch-frei):not(.tisch-bereit):not(.tisch-wartet),
body.thema-dunkel .cart-line,
body.thema-dunkel .checkbox-option,
body.thema-dunkel .beilage-option-btn,
body.thema-dunkel .pay-method-btn,
body.thema-dunkel .keypad-grid button,
body.thema-dunkel .praefix-btn,
body.thema-dunkel .modal-box {
    background: #20201f;
}
/* Überschriften, Absätze und Hinweise IM Fenster erben den Grund des Fensters — sie brauchen
   keinen eigenen, sonst stünden dunkle Kästen um jede Textzeile, sobald das Fenster einmal
   anders eingefärbt wird. */
body.thema-dunkel .modal-box h3,
body.thema-dunkel .modal-box p,
body.thema-dunkel .modal-box label,
body.thema-dunkel .modal-box .hint {
    background: transparent;
}
/* Der Beleg bleibt schwarz auf weiß — er ist ein Dokument, kein Bedienelement. */
body.thema-dunkel .modal-box.kassenbeleg-box { background: #ffffff; }

/* Die haftende Handlungsleiste der Reservierungs-Karte: eine Spur dunkler als das Fenster,
   damit sie als dessen Boden gelesen wird. */
body.thema-dunkel .reserv-detail-aktionen { background: #1e2127; }

/* --- Trennlinien einer Kategorie (Verwaltung → Produkte → Kategorien) ---------------------
   Sechs Bedienelemente NEBENeinander passen nicht: das Fenster ist 560 px breit, für die Zeile
   bleiben 472 — und gemessen beanspruchte allein das Namensfeld seine Mindestbreite von 202 px
   (ein <input> misst ohne `min-width: 0` immer 20 Zeichen). Die Zeile stand damit 90 px über
   den Rand hinaus: Schalter und Kreuz lagen NEBEN dem Fenster, auf dem Telefon hing
   „vorne/hinten" 95 px daneben.
   Deshalb zwei Zeilen: oben der Abschnitt selbst (Position · Name · sichtbar · weg), darunter
   eingerückt, was auf den ZETTEL gehört (Zusatz · vorne/hinten). Raster statt Flex, damit die
   Namensfelder aller Zeilen gleich breit sind und untereinander stehen — mit Flex richtet sich
   die Breite nach dem längsten Namen und die Spalte wackelt bei jedem Tippen. */
.trennlinie-zeile {
    display: grid;
    grid-template-columns: 64px minmax(0, 1fr) auto auto;
    grid-template-areas:
        "pos name   an     weg"
        ".   zettel zettel zettel";
    align-items: center;
    /* Die beiden Zeilen EINER Linie stehen enger beieinander als zwei Linien zueinander —
       sonst sieht die Liste aus wie vier gleichwertige Reihen, und niemand erkennt, welcher
       Zusatz zu welchem Namen gehört. */
    gap: 6px 8px;
    margin-bottom: 16px;
}
/* Ohne das behält jedes Feld seine inhaltsabhängige Mindestbreite und schiebt die Zeile aus
   dem Fenster — das war die eigentliche Ursache des Überstands, nicht die Spaltenzahl. */
.trennlinie-zeile > * { min-width: 0; }
.trennlinie-zeile .trennlinie-pos { grid-area: pos; }
/* Breite ausdrücklich: `feld_leeren.js` schiebt für den ✕ eine Hülle zwischen Zeile und Feld,
   und ein <input> ist von sich aus nur rund 20 Zeichen breit. Ohne diese Zeile bliebe im
   Namensfeld auf dem grossen Schirm rechts ein leerer Streifen (gemessen 228 statt 307 px). */
.trennlinie-zeile .trennlinie-name { grid-area: name; width: 100%; }
.trennlinie-zeile .toggle-switch { grid-area: an; margin: 0; }
.trennlinie-zeile [data-zeile-weg] { grid-area: weg; justify-self: end; }
/* Zusatz und „vorne/hinten" gehören zusammen und stehen deshalb in EINEM Kästchen —
   getrennt im Raster rissen sie die Zeile auseinander (der eine links, der andere rechts
   aussen unter dem Kreuz). */
.trennlinie-zeile .trennlinie-zettel {
    grid-area: zettel;
    display: flex;
    align-items: center;
    gap: 6px;
}
.trennlinie-zettel .trennlinie-zusatz { flex: 0 1 96px; min-width: 0; }
.trennlinie-zettel .trennlinie-stelle { flex: 0 0 auto; }
/* Auf dem Telefon ist die Zeile nur noch 270 px breit. Dort wandert die Position hinunter,
   damit der NAME die erste Zeile für sich hat — gemessen 177 statt 93 px. */
@media (max-width: 480px) {
    .trennlinie-zeile {
        grid-template-areas:
            "name name   an     weg"
            "pos  zettel zettel zettel";
    }
}
/* Ganz schmale Geräte (iPhone SE, 320 px): dort reicht auch die zweite Zeile nicht für beide
   Felder — gemessen 5 px Überstand. Erst hier dürfen sie untereinander brechen; ab 390 px
   passen sie nebeneinander, und ein früherer Umbruch machte aus einer Linie drei Zeilen. */
@media (max-width: 360px) {
    .trennlinie-zeile .trennlinie-zettel { flex-wrap: wrap; }
}
.btn-klein {
    padding: 6px 12px;
    font-size: 0.8rem;
    line-height: 1.2;
}
.trennlinien-formular {
    margin-top: 4px;
    padding-top: 14px;
    border-top: 1px solid var(--djk-border);
}

/* --- Buchungs-Journal (Würfelmenü → Buchungen, siehe kasse.js buchungenZeichnen) ----------
   Die Trennlinie ist dieselbe wie im Produktraster (.kueche-section-divider) — bewusst, denn
   sie sagt dasselbe: "hier beginnt ein neuer Abschnitt". Nur der Abstand ist grösser, weil
   hier ganze Tischbesuche getrennt werden und nicht Produktgruppen. */
.buchung-trenner { margin: 18px 0 8px; }
.buchung-trenner:first-child { margin-top: 4px; }
.buchung-bezahlt {
    font-size: 0.74rem;
    color: var(--djk-gray);
    text-align: center;
    margin-bottom: 8px;
}
/* Kein Rahmen mehr um die Buchung: die Zeilen darin sind schon Karten (.cart-line), und ein
   Kasten um Kaesten macht die Liste eng. Zusammengehalten wird sie jetzt allein durch die
   Kopfzeile darueber und den Abstand darunter. */
.buchung-block { margin-bottom: 14px; }
.buchung-liste { margin: 0; padding: 0; list-style: none; }
.buchung-kopf {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.72rem;
    color: var(--djk-gray);
    margin-bottom: 6px;
}
.buchung-nr { font-weight: 700; }
.buchung-zeile { cursor: pointer; }
.buchung-zeile.offen { border-color: var(--djk-yellow); }

/* Der Abschluss eines Buchungsblocks: wie viele Positionen, wie viel Geld. Er gehört zum Block
   und liegt deshalb innerhalb seiner Kante, abgesetzt durch eine Linie statt durch Abstand. */
.buchung-fuss {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--djk-border);
    font-size: 0.82rem;
    color: var(--djk-gray);
}
.buchung-fuss-summe { font-weight: 800; font-size: 1rem; color: var(--djk-yellow); }

/* --- Die Zettel einer Buchung (07.09.2026) -----------------------------------------------
 *
 * Der Wirt: „нажимая на него внизу откроется чек, если есть бар и кухня то два чека и на каждом
 * повторно напечатать". Der Kopf der Buchung ist der Griff, darunter klappt fuer jede Station
 * ihr Zettel auf — der echte, so wie er aus dem Drucker kaeme.
 */
.buchung-kopf.hat-zettel { cursor: pointer; }
.buchung-zettel-marken { display: inline-flex; align-items: center; gap: 5px; margin-left: auto; }
.buchung-zettel-marken svg {
    width: 12px; height: 12px;
    transition: transform 0.15s ease;
}
.buchung-kopf.offen .buchung-zettel-marken svg { transform: rotate(180deg); }
/* Die Farbe sagt, wie weit der Zettel gekommen ist: gedruckt, nur auf dem Brett, gar nicht
   geschickt. Dieselben drei Zustaende wie in der Liste der Station — und dieselben Farben. */
.bz-marke {
    font-size: 0.62rem;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 999px;
    border: 1px solid transparent;
}
/* Die Farben kommen aus dem Satz des Hauses, nicht fest aus der Zeile: sonst zeigt das
   Programm daneben ein anderes Gruen (gemessen 07.09.: #22c55e hier gegen #10b981 dort). */
.bz-marke.ist-gedruckt {
    background: color-mix(in srgb, var(--djk-success) 18%, transparent);
    color: var(--djk-success);
    border-color: color-mix(in srgb, var(--djk-success) 40%, transparent);
}
.bz-marke.ist-gesendet {
    background: color-mix(in srgb, var(--djk-yellow) 18%, transparent);
    color: var(--djk-yellow);
    border-color: color-mix(in srgb, var(--djk-yellow) 40%, transparent);
}

.buchung-zettel {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--djk-border);
}
/* `hidden` verliert gegen `display:flex` — deshalb noch einmal ausdruecklich. */
.buchung-zettel[hidden] { display: none; }
.bz-blatt { flex: 1 1 240px; min-width: 0; }
.bz-blatt-kopf {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    font-size: 0.78rem;
}
.bz-stand { color: var(--djk-gray); font-size: 0.7rem; }
.bz-blatt-kopf .btn { margin-left: auto; }
.bz-papier { overflow-x: auto; }

/* --- Rot ist, was nicht angekommen ist (07.09.2026) ---------------------------------------
 *
 * Der Wirt: *„может весь тикет красный, но когда раскроем, останется только тот тикет красным,
 * который не получили: например бар не напечатал, но кухня напечатала"*. Also zwei Ebenen:
 * die ganze Karte faellt auf, und aufgeklappt nur noch der schuldige Zettel.
 *
 * Gerechnet wird das auf dem Server, mit derselben Regel wie die Vollbild-Warnung
 * (zustellung_offene_ziele) — zwei Rechnungen ergaeben zwei Wahrheiten.
 */
.buchung-block.hat-problem { border-left: 3px solid var(--djk-danger); padding-left: 9px; }
.buchung-kopf.hat-problem .buchung-nr { color: var(--djk-danger); }
.bz-marke.hat-problem {
    background: color-mix(in srgb, var(--djk-danger) 18%, transparent);
    color: var(--djk-danger);
    border-color: color-mix(in srgb, var(--djk-danger) 55%, transparent);
}
.bz-blatt.hat-problem .bz-blatt-kopf strong { color: var(--djk-danger); }
.bz-blatt.hat-problem .bz-papier { outline: 2px solid var(--djk-danger); outline-offset: 2px; border-radius: 4px; }

/* --- Und gruen, wenn ein Mensch „Erledigt" gesagt hat (07.09.2026) -------------------------
 *
 * Der Wirt: *„после Erledigt блок должен цвет на зелёный поменять"*. Der Fall verschwindet
 * nicht — man soll noch sehen, dass es ihn gab; er ist nur nicht mehr offen. Dasselbe Gruen
 * wie „gedruckt", denn es sagt dasselbe: hier ist alles in Ordnung.
 */
.buchung-block.ist-erledigt { border-left: 3px solid var(--djk-success); padding-left: 9px; }
.buchung-kopf.ist-erledigt .buchung-nr { color: var(--djk-success); }
.bz-blatt.ist-erledigt .bz-blatt-kopf strong { color: var(--djk-success); }
.bz-blatt.ist-erledigt .bz-papier { outline: 2px solid var(--djk-success); outline-offset: 2px; border-radius: 4px; }

/* --- Die lebende Suche ueber den Buchungen ------------------------------------------------
 *
 * Sie steht dort, wo bis zum 07.09.2026 die Reiter standen. Dieselbe Form wie die Produktsuche
 * oben in der Kasse — wer die eine bedient hat, bedient auch die andere.
 */
.kasse-verlauf-suche {
    position: relative;
    display: flex;
    align-items: center;
    margin: 12px 0 14px;
}
.kasse-verlauf-suche[hidden] { display: none; }
.kasse-verlauf-suche input {
    width: 100%;
    height: var(--feld-hoehe, 43px);
    padding: 0 38px;
    border-radius: 5px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: var(--djk-white);
    font: inherit;
}
.kasse-verlauf-suche input:focus { outline: none; border-color: var(--djk-yellow); }
.kasse-verlauf-suche-lupe {
    position: absolute;
    left: 10px;
    display: flex;
    pointer-events: none;
    color: var(--djk-gray);
}
.kasse-verlauf-suche-lupe svg { width: 18px; height: 18px; }
.kasse-verlauf-suche-x {
    position: absolute;
    right: 6px;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 5px;
    background: transparent;
    color: var(--djk-gray);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
}
.buchung-sitzung[hidden] { display: none; }
/* `hidden` verliert gegen `.admin-tabs { display: flex }` — die alte Falle (siehe
   „hidden gegen display"). Die Reiterleiste ist seit dem 07.09.2026 eine leere Huelle;
   sie darf keinen Platz mehr nehmen. */
.kasse-verlauf-reiter[hidden] { display: none; }

/* --- „Buchung": derselbe Anblick wie im Programm (07.09.2026) ------------------------------
 *
 * Der Wirt: *„дизайн на браузере тоже сделай точно так же, как на приложении"*.
 *
 * Der Unterschied war EINE geerbte Eigenschaft: die Zeilen benutzen `.cart-list`/`.cart-line`,
 * und das ist der BON an der Kasse — weisses Papier, Schreibmaschinenschrift, schwarze Schrift.
 * Gemessen: Grund rgb(255,255,255), Name SFMono 16,3 px fett in Schwarz. Im Programm steht
 * dieselbe Liste auf `MaterialTheme.colorScheme.surface` — und das IST `--djk-black-card`, mit
 * der normalen Schrift in 14 sp.
 *
 * Also hier dieselben Werte, Zahl fuer Zahl aus Verlauf.kt: Karte 5 px rund, Zeile 10 px
 * Polster, Name und Betrag 14 sp = 0,875 rem, Trennung ein duenner gestrichelter Strich in
 * `--djk-border`. Nur in DIESER Liste — der Bon an der Kasse bleibt Papier.
 *
 * WARUM `.kasse-verlauf-inhalt` DAVOR STEHT: die Bon-Regeln (`.cart-list .cart-item-name`,
 * Zeile ~13380) sind genauso spezifisch wie `.buchung-liste .cart-item-name` und stehen
 * SPAETER im Blatt — sie gewinnen dann. Gemessen: der Name blieb SFMono 16,3 px schwarz,
 * obwohl die Regel dastand. Mit der dritten Klasse gewinnt sie unabhaengig von der Reihenfolge.
 */
.kasse-verlauf-inhalt .buchung-liste {
    /* Kein Rahmen — im Programm steht die Liste als reine Flaeche da (`background(surface)`),
       und ein Strich mehr waere schon wieder ein Unterschied. */
    background: var(--djk-black-card);
    border-radius: 5px;
    overflow: hidden;
}
.kasse-verlauf-inhalt .buchung-liste li.cart-line {
    background: transparent;
    border-radius: 0;
    padding: 10px;
    margin: 0;
    box-shadow: none;
    border-top: 0;
}
.kasse-verlauf-inhalt .buchung-liste li.cart-line + li.cart-line {
    border-top: 1px dashed var(--djk-border);
}
/*
 * UND IM DUNKLEN NOCH EINMAL — sonst bleibt die Liste weiss.
 *
 * `body.thema-dunkel .cart-list { background: #ffffff }` (Zeile ~13409) haelt das PAPIER auch
 * im dunklen Erscheinungsbild weiss, und das ist dort richtig: ein Bon sieht aus wie ein Bon.
 * Diese Liste ist aber kein Bon mehr. Die Regel traegt `body` im Waehler und ist damit
 * spezifischer als jede Klassenkette ohne — gemessen: Grund blieb rgb(255,255,255), obwohl
 * Schrift und Rundung schon stimmten. Also dieselbe Form noch einmal, mit `body` davor.
 */
body.thema-dunkel .kasse-verlauf-inhalt .buchung-liste { background: var(--djk-black-card); }
body.thema-dunkel .kasse-verlauf-inhalt .buchung-liste li.cart-line { background: transparent; }
.kasse-verlauf-inhalt .buchung-liste .cart-item-name {
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 400;
    color: var(--djk-white);
}
.kasse-verlauf-inhalt .buchung-liste .cart-item-name small {
    display: block;
    font-size: 0.72rem;
    font-weight: 400;
    color: var(--djk-gray);
    margin-top: 2px;
}
.kasse-verlauf-inhalt .buchung-liste .cart-item-price,
.kasse-verlauf-inhalt .buchung-liste .cart-preis-spalte {
    font-family: inherit;
    font-size: 0.875rem;
    color: var(--djk-white);
}
/* Gestrichene Zeile: blasser und durchgestrichen — wie im Programm (LineThrough). */
.kasse-verlauf-inhalt .buchung-liste .cart-line.gestrichen .cart-item-name,
.kasse-verlauf-inhalt .buchung-liste .cart-line.gestrichen .cart-item-price {
    color: var(--djk-gray);
    text-decoration: line-through;
}

/* source/style_css/385_dark_theme_journal_continued.css - style.css: dark theme journal continued, part 56 of 78 (built by werkzeuge/parts_build.php) */
/* Die Linie ueber dem Tischbesuch traegt im Programm die normale Schreibweise („Tisch 104"),
   nicht Grossbuchstaben — und keinen Sperrsatz. */
.buchung-trenner span {
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.75rem;
}
.buchung-block { margin-bottom: 10px; }
.buchung-nr { font-size: 0.75rem; }
.buchung-fuss { font-size: 0.75rem; padding-top: 6px; margin-top: 6px; }
.buchung-fuss-summe { font-size: 0.875rem; }
/*
 * Der Zettel passt sich der Spalte an — dieselbe Rechnung wie am Kuechenbrett: die Zeile ist
 * `--papier-zeichen` Zeichen breit, also folgt die Schriftgroesse aus der Spaltenbreite. Fest
 * gesetzte 12 px liessen auf dem Telefon die halbe Zeile rechts ausserhalb liegen.
 */
@supports (container-type: inline-size) {
    .bz-papier { container-type: inline-size; }
    .bz-papier .druck-papier { width: 100%; padding: 10px 8px; }
    .bz-papier .druck-zeile { font-size: calc(100cqw / var(--papier-zeichen, 32) / 0.66); }
    .bz-papier .druck-zeile.schrift-hoch,
    .bz-papier .druck-zeile.schrift-breit,
    .bz-papier .druck-zeile.schrift-gross { font-size: calc(200cqw / var(--papier-zeichen, 32) / 0.66); }
}
/* "Unklar" ist eine Merkfarbe, kein Fehler: Kupfer wie der Stern, nicht Rot wie ein Storno. */
.buchung-zeile.unklar { background: rgba(245, 158, 11, 0.16); }
.buchung-zeile.unklar .cart-item-name { color: var(--djk-copper, #f59e0b); font-weight: 700; }
.buchung-zeile.gestrichen .cart-item-name,
.buchung-zeile.gestrichen .cart-item-price { text-decoration: line-through; opacity: 0.55; }
/*
 * Hier stand der Stil des Kastens, der unter einer Buchungszeile aufklappte („− 2 + Streichen").
 * Den Kasten gibt es seit dem 07.09.2026 nicht mehr — der Wirt hat ihn durchgestrichen, und
 * geaendert wird am Tisch. Der Stil ist mitgegangen, damit niemand ihn spaeter fuer lebendig
 * haelt; die Regel, die er einmal gelehrt hat, steht im Handbuch („hidden gegen display").
 */
.buchung-menge-gross { min-width: 26px; text-align: center; font-weight: 800; }

/* --- Nachlass-Zeilen der Tischkategorie (Verwaltung -> Tische -> Tischkategorien) ---------
   Raster statt Flex, damit die Spalten aller Zeilen untereinander stehen; sonst richtet sich
   die Breite nach dem laengsten Kategorienamen und die Zeilen wackeln gegeneinander. */
.tkrabatt-zeile {
    display: grid;
    grid-template-columns: 1fr 64px 78px auto auto;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}
.tkrabatt-zeile select,
.tkrabatt-zeile input[type="text"] { min-width: 0; }
.tkrabatt-zeile .toggle-switch { margin: 0; }

/* Der Nachlass in der Preisspalte einer Warenkorbzeile — dieselbe Machart wie der
   Extra-Aufschlag darueber, nur in der Warnfarbe der Ermaessigung statt in Rot des Aufschlags. */
.cart-preis-nachlass {
    display: block;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--djk-success);
    text-align: right;
}

/* Auf dem großen Kassenbildschirm gehört der Menü-Knopf (Uhr) NEBEN die Suche, nicht links
   davor: links stehen Tisch und Suche — also das, womit man arbeitet —, rechts die Absprünge
   in andere Ansichten. Verschoben wird über die Flex-Reihenfolge, nicht im HTML: auf dem
   schmalen Bildschirm soll er dort bleiben, wo er ist. */
@media (min-width: 1200px) {
    body.kasse-body .kasse-search-bar #verlaufBtn { order: 1; }
    body.kasse-body .kasse-search-bar #kuecheBellBtn,
    body.kasse-body .kasse-search-bar #barBellBtn,
    body.kasse-body .kasse-search-bar #reservierungenBtn,
    body.kasse-body .kasse-search-bar #qrScanBtn { order: 2; }
}

/* --- Aktiver Punkt der Menue-Flaeche ------------------------------------------------------
   Wie eine gedrueckte Taste: derselbe Akzent, mit dem die Kasse ueberall "das hier gilt gerade"
   sagt. Ohne das sahen alle Knoepfe gleich aus, obwohl einer von ihnen die Flaeche daneben
   gefuellt hatte. */
.kasse-menue-knopf.aktiv {
    border-color: var(--djk-yellow);
    color: var(--djk-yellow);
    background: color-mix(in srgb, var(--djk-yellow) 14%, transparent);
}
.kasse-menue-knopf { transition: background var(--transition), border-color var(--transition), color var(--transition); }

/* source/style_css/390_product_grid_seat_plan_z_report.css - style.css part 57 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Produktraster sanft einblenden -------------------------------------------------------
   Nur die Kacheln, nicht die Trennlinien: die sollen als Geruest stehenbleiben, waehrend der
   Inhalt wechselt. Kurz gehalten (160 ms) - eine Kasse darf sich nicht traege anfuehlen. */
@keyframes raster-auf {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
/* Nicht im Umstellen: diese Regel ist spezifischer als das Zappeln (.kacheln-ordnen >
   .product-tile) und hielt die Produkte still, sobald das Einblenden eingeschaltet war —
   die Kategorien daneben wackelten (Foto des Wirts, 26.09.2026). */
.product-grid.raster-einblenden:not(.kacheln-ordnen) > .product-tile {
    animation: raster-auf 160ms ease-out both;
}
/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt sie auch hier nicht. */
@media (prefers-reduced-motion: reduce) {
    .product-grid.raster-einblenden > .product-tile { animation: none; }
}

/* --- Sitzplan des Tisches (langes Druecken auf eine Tisch-Kachel) -------------------------- */
.sitzplan-fenster .sitzplan-box { max-width: 460px; padding: 18px; }
.sitzplan-kopf { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.sitzplan-kopf h3 { margin: 0; font-size: 1.05rem; }
/* Das Glas vor dem Tischnamen. `margin-right: auto` an der Ueberschrift, damit der Kopf
   (`space-between`) Zeichen und Name zusammen nach links legt und das Kreuz rechts bleibt —
   ohne diese Zeile stuende der Name in der Mitte, weit weg von seinem Zeichen. */
.sitzplan-kopf h3 { margin-right: auto; }
.sitzplan-kopf-zeichen { display: inline-flex; flex: 0 0 auto; }
.sitzplan-kopf-zeichen svg,
.sitzplan-kopf-zeichen .icon { width: 20px; height: 20px; }
.sitzplan-info { font-size: 0.8rem; color: var(--djk-gray); margin-bottom: 10px; }
.sitzplan-liste { display: grid; gap: 8px; max-height: 46vh; overflow-y: auto; margin-bottom: 12px; }
/* Nummer, Name, Knopf — feste Spalten, damit die Felder aller Zeilen untereinander stehen. */
.sitzplan-zeile { display: grid; grid-template-columns: 24px 1fr auto auto; align-items: center; gap: 6px; }
.sitzplan-nr { font-weight: 800; text-align: center; color: var(--djk-gray); }
.sitzplan-zeile input { min-width: 0; }
/* Der Platz, auf den gerade gebucht wird — dieselbe Akzentfarbe wie ueberall fuer "gilt jetzt". */
.sitzplan-zeile.gewaehlt .sitzplan-nr { color: var(--djk-yellow); }
.sitzplan-zeile.gewaehlt .sitzplan-waehlen { border-color: var(--djk-yellow); color: var(--djk-yellow); }
.sitzplan-aktionen { display: flex; justify-content: flex-end; }

/* Erinnerung oben am Warenkorb, dass gerade auf einen bestimmten Platz gebucht wird. */
.platz-hinweis {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    background: color-mix(in srgb, var(--djk-yellow) 18%, transparent);
    color: var(--djk-yellow);
}

/* Fenster sanft auftauchen lassen statt hart einblenden — gilt fuer ALLE modalen Fenster. */
@keyframes fenster-auf { from { opacity: 0; transform: translateY(8px) scale(0.99); } to { opacity: 1; transform: none; } }
.modal-overlay.active > .modal-box { animation: fenster-auf 150ms ease-out both; }
@media (prefers-reduced-motion: reduce) { .modal-overlay.active > .modal-box { animation: none; } }

/* Platz und Gast auf dem Kuechen-/Bar-Zettel: hervorgehoben, weil das die Angabe ist, nach der
   gesucht wird, wenn der Teller fertig ist. */
.kueche-ticket-platz { font-weight: 800; color: var(--djk-yellow); }

/* --- Z-Bericht ------------------------------------------------------------------------------
   Der Bericht selbst ist fertig gesetzter Text mit 42 Zeichen je Zeile (siehe
   includes/tagesabschluss_druck.php). Deshalb hier keine Tabelle und kein Flexbox-Raster,
   sondern nur: eine Schrift, in der jedes Zeichen gleich breit ist, und genug Platz fuer
   42 davon. Jede andere Schrift macht aus den ausgerichteten Spalten wieder eine Treppe.

   Die Groesse in `ch` statt `px`: 1ch ist die Breite einer Ziffer, 42ch also genau eine
   Bonbreite - egal wie gross der Nutzer die Schrift eingestellt hat. */
.z-beleg {
    font-family: "SFMono-Regular", "Consolas", "Liberation Mono", "Menlo", monospace;
    font-size: 0.78rem; line-height: 1.45; margin: 0;
    white-space: pre; tab-size: 4;
    /* Auf schmalen Telefonen passen 42 Zeichen nicht immer - dann darf der Bon seitlich
       wandern, statt umzubrechen. Ein umgebrochener Bon ist unlesbar. */
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    max-width: 100%;
}
/* Der Bon soll IMMER ganz hineinpassen, statt seitlich zu verschwinden - ein Bon, von dem man
   die Betragsspalte wegscrollen muss, ist kein Bon mehr.

   Deshalb richtet sich die Schriftgroesse nach der Breite des Behaelters (`cqw`), nicht nach
   der des Fensters: derselbe Bon steht einmal in der schmalen Kassenspalte und einmal auf einer
   breiten Verwaltungsseite, und ein `@media`-Punkt kann beide nicht gleichzeitig treffen.

   3.9cqw kommt aus der Rechnung: 42 Zeichen * ~0.6em Zeichenbreite = ~25.2em, also
   100cqw / 25.2 = 3.97cqw. `min()` deckelt nach oben, damit der Bon auf grossen Schirmen
   nicht ins Riesenhafte waechst. Wo Container-Queries fehlen, bleibt es bei 0.78rem und dem
   seitlichen Scrollen darueber. */
@supports (container-type: inline-size) {
    .z-bon { container-type: inline-size; }
    .z-bon .z-beleg { font-size: min(0.78rem, 3.9cqw); }
}
/* Die Schriftfarbe des Bons in der Verwaltung.
   Hier stand `var(--djk-black)` — und das war eine Falle mit Anlauf. `--djk-black` ist in
   diesem Projekt die FLAECHE, nicht die Schrift; `--djk-white` ist die Schrift. Solange das
   ganze Personal-Modul dunkel war, fiel das nicht auf: die Flaeche war dunkel, also war die
   Schrift zufaellig auch dunkel und stand richtig auf der hellen Verwaltungsseite. Mit dem
   Wechsel auf die helle Palette kehrten sich beide Werte um — seitdem stand der ganze
   Z-Bericht in #f8fafc auf einer weissen Karte, also unsichtbar. Gedruckt kam er weiter
   schwarz heraus (siehe @media print), deshalb fiel es lange niemandem auf.
   Mit `--djk-white` steht er in beiden Erscheinungsbildern richtig. */
.z-druck .z-beleg { color: var(--djk-white, #16181d); }

/* --- Reste der frueheren Zeilendarstellung -------------------------------------------------
   Noch gebraucht fuer das Eingabefeld des Kassensturzes unter dem Bon. */
.z-kopf {
    display: flex; justify-content: space-between; align-items: baseline;
    font-weight: 800; font-size: 1.05rem; margin-bottom: 10px;
}
.z-kopf span { font-size: 0.76rem; font-weight: 600; color: var(--djk-gray); }
.z-zeile {
    display: flex; justify-content: space-between; gap: 12px;
    padding: 4px 2px; font-size: 0.86rem;
    /* Betraege in Ziffern gleicher Breite - sonst tanzt die Nachkommastelle von Zeile zu Zeile. */
    font-variant-numeric: tabular-nums;
}
.z-zeile span:last-child { white-space: nowrap; }
.z-gruppensumme { border-top: 1px solid var(--djk-border); margin-top: 2px; }
.z-gesamt { font-size: 1.05rem; border-top: 2px solid var(--djk-yellow); margin-top: 4px; padding-top: 8px; }
.z-klein { color: var(--djk-gray); font-size: 0.78rem; }
.z-bar-feld { width: 110px; text-align: right; padding: 4px 8px; }
/* Der Satz unter dem Kassensturz-Feld: er sagt, warum die Zahl gebraucht wird, und
   verschwindet, sobald sie dasteht (z_bericht.js). */
.z-sturz-hinweis { margin: 6px 0 10px; font-size: 0.78rem; color: var(--djk-yellow); }

.z-differenz { text-align: right; font-size: 0.82rem; font-weight: 700; min-height: 18px; padding: 2px; }
.z-differenz.passt { color: var(--djk-success); }
.z-differenz.weicht-ab { color: var(--djk-danger); }
.z-warnung {
    margin-top: 14px; padding: 12px; border-radius: 6px; font-size: 0.84rem; line-height: 1.5;
    background: rgba(248, 113, 113, 0.12); border: 1px solid var(--djk-danger);
}
.z-abschluss-knopf { width: 100%; margin-top: 16px; padding: 14px; font-size: 0.95rem; }

/* --- Z-Bericht als eigene Seite (personal/z_bericht.php) -----------------------------------
   Gebaut wie der Kassenbericht daneben: eine Liste mit Abschnitten statt eines Bons. Der
   42-Zeichen-Text lebt weiter, aber nur noch in der Verwaltung und spaeter auf dem Drucker. */
.z-zeitraum {
    font-size: 0.82rem; line-height: 1.5; color: var(--djk-gray);
    padding: 0 4px 12px; text-align: center;
}
.z-liste li { align-items: baseline; }
/* Abschnittsueberschrift — dieselbe Form wie die Trennlinien im Produktraster, damit die
   Seite sich nicht wie ein Fremdkoerper anfuehlt. */
.z-abschnitt {
    display: block !important;
    margin: 18px 0 2px; padding: 0 2px 4px;
    font-size: 0.72rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--djk-yellow); border-bottom: 1px solid var(--djk-border);
}
.z-abschnitt:first-child { margin-top: 0; }
/* Laufende Nummer der Sparte: feste Breite, sonst rutschen die Namen gegeneinander. */
.z-nr {
    display: inline-block; min-width: 1.6em; margin-right: 4px;
    color: var(--djk-gray); font-variant-numeric: tabular-nums;
}
/* Der Anteil steht hinter dem Betrag und muss kleiner sein — sonst liest man ihn als zweite
   Geldsumme. Genau dieser Verwechslung wegen bekommt er auch ein eigenes Prozentzeichen. */
.z-anteil { color: var(--djk-gray); font-size: 0.76rem; font-weight: 600; }
.z-unter, .z-unterzeile { color: var(--djk-gray); font-size: 0.8rem; }
.z-unterzeile { padding-left: 14px; }
.z-hinweis {
    display: block !important;
    margin-top: 8px; padding: 10px; border-radius: 6px; line-height: 1.5;
    font-size: 0.78rem; color: var(--djk-gray);
    background: var(--djk-black-soft); border: 1px solid var(--djk-border);
}
.z-abschluss-block { margin-top: 22px; padding: 14px; border-radius: 8px; background: var(--djk-black-card); border: 1px solid var(--djk-border); }

/* --- Z-Bericht im Produktbereich -----------------------------------------------------------
   Er tauscht sich mit dem Warenraster: eine Klasse am <body> entscheidet, was in
   #kasseProductsSection zu sehen ist. Kein zweites Fenster, kein Seitenwechsel — der
   Bedienende bleibt in der Kasse, und der Bericht bekommt trotzdem die volle Breite. */
.z-bereich { display: none; }
body.kasse-zeigt-z #kasseProdukteHuelle { display: none; }
body.kasse-zeigt-z .z-bereich {
    /* KEIN height:100% mehr: der Bereich soll so hoch werden, wie sein Inhalt ist, und rollen
       soll die Flaeche darum herum (#kasseProductsSection). Mit fester Hoehe entstand darin ein
       zweiter Rollbereich, und beim Wischen bewegte sich der falsche. */
    display: block;
    padding: 12px 14px calc(16px + env(safe-area-inset-bottom, 0px));
}
.z-bereich-kopf {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding-bottom: 10px; border-bottom: 2px solid var(--djk-yellow);
}
.z-bereich-titel { font-weight: 800; font-size: 1rem; flex: 1 1 auto; }
.z-bereich-titel span { display: block; font-size: 0.74rem; font-weight: 600; color: var(--djk-gray); }
.z-bereich-werkzeuge { display: flex; align-items: center; gap: 8px; }
.z-filter-feld {
    width: 170px; max-width: 38vw; padding: 8px 10px; border-radius: 5px;
    background: var(--djk-black-soft); border: 1px solid var(--djk-border); color: var(--djk-white);
}
.z-filter-feld:focus { outline: none; border-color: var(--djk-yellow); }
@media print { .z-filter-feld { display: none !important; } }
/* Die Leiste: drei Zahlen nebeneinander, mehr nicht. Ein Tipp darauf klappt den ganzen Bon
   darunter auf, ein zweiter schliesst ihn wieder. Werte wie vom Wirt am Bildschirm eingestellt. */
.z-leiste {
    display: flex !important;
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    margin: 0;
    cursor: pointer;
    overflow: hidden;
}
.z-leiste-feld {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; padding: 0 5px; text-align: center;
}
.z-leiste-feld b {
    font-size: 0.7rem; font-variant-numeric: tabular-nums;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.z-leiste-feld small {
    font-size: 0.66rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--djk-gray);
}
.z-leiste-pfeil { display: flex; align-items: center; padding: 0 12px; color: var(--djk-yellow); }
.z-druck.z-offen .z-leiste-pfeil { transform: rotate(180deg); }

/* Der Bon. Zugeklappt unsichtbar, aufgeklappt in voller Laenge — und beim Drucken immer da.
   Die Schriftfarbe steht ausdruecklich da, weil dieser Bon in der KASSE liegt und nicht in der
   Verwaltung: `--djk-white` ist die Schriftfarbe des jeweiligen Erscheinungsbildes und damit
   auf beiden Gruenden lesbar (siehe auch `.z-druck .z-beleg` weiter oben). */
#zBeleg { display: none; margin-top: 12px; color: var(--djk-white); }
.z-druck.z-offen #zBeleg { display: block; }
@media print {
    #zBeleg { display: block !important; color: #000 !important; }
    .z-leiste { display: none !important; }
}

/* Gerollt wird die ganze Flaeche, nicht ein Kasten darin: zwei ineinanderliegende Rollbereiche
   sind mit dem Finger nicht auseinanderzuhalten — man schiebt den inneren, waehrend man den
   aeusseren meint. */
body.kasse-zeigt-z #kasseProductsSection { overflow-y: auto; -webkit-overflow-scrolling: touch; }

/* Die Summe oben zeigt gerade NICHT den ganzen Tisch, sondern nur die angetippten Positionen
   (Teilzahlung, siehe updatePayBtnState in kasse.js). Ohne ein Zeichen dafuer liest man die
   kleinere Zahl als "der Tisch ist billiger geworden" - und das waere die gefaehrlichste
   Fehldeutung, die diese Zahl haben kann. */
.cart-total-auswahl {
    color: var(--djk-yellow);
    position: relative;
}
.cart-total-auswahl::after {
    content: "Auswahl";
    display: block;
    font-size: 0.6rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--djk-gray); line-height: 1; margin-top: 2px;
}

/* --- Z-Bericht drucken ---------------------------------------------------------------------
   Beim Drucken bleibt genau der Bon uebrig: kein Menue, keine Liste der uebrigen Abschluesse,
   kein Drucken-Knopf, der sich selbst mitdruckt. Erreicht ueber `visibility` statt `display`,
   weil ein ausgeblendeter Vorfahre auch das Kind mitnimmt - der Bon steckt tief in der Seite. */
@media print {
    body:has(.z-druck) * { visibility: hidden; }
    body:has(.z-druck) .z-druck, body:has(.z-druck) .z-druck * { visibility: visible; }
    body:has(.z-druck) .z-druck {
        position: absolute; inset: 0 auto auto 0; width: auto;
        margin: 0; padding: 0; border: 0; box-shadow: none; background: #fff;
    }
    .z-druck-kopf { display: none !important; }
    /*
     * Auf Papier KEINE Container-Abfrage.
     *
     * Am Bildschirm richtet sich die Schriftgroesse des Bons nach der Breite seines Behaelters
     * (`min(0.78rem, 3.9cqw)`, siehe `.z-bon` weiter oben). Beim Drucken wird `.z-druck` aber
     * absolut gesetzt und schrumpft auf seinen Inhalt — und dessen Groesse haengt wiederum an
     * der Behaelterbreite. Diese Katze beisst sich in den Schwanz, das Ergebnis war 0: der Bon
     * kam mit Schriftgroesse 0 px und Breite 0 px heraus, das Blatt blieb leer (11.08.2026).
     *
     * Deshalb hier beides: die Container-Abfrage abschalten UND die Groesse mit derselben
     * Genauigkeit setzen wie die Regel am Bildschirm (`.z-bon .z-beleg` wiegt schwerer als
     * `.z-beleg` — ein @media-Block aendert daran nichts).
     */
    .z-bon { container-type: normal; }
    /* Schwarz auf Weiss - ein Bonrucker kennt nichts anderes, und Toner spart es auch. */
    .z-beleg,
    .z-bon .z-beleg {
        color: #000 !important;
        font-size: 10pt !important;
        overflow: visible !important;   /* nichts abschneiden, was seitlich hinausragt */
    }
}

/* Ein Haken in "Ansicht & Rechte" (Verwaltung → Tische): Kästchen und Name als ein Feld, damit
   die Gruppen als Reihe von Marken lesbar sind und nicht als Liste nackter Kästchen. */
.tisch-ansicht-haken {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 8px 14px;
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    background: var(--djk-black-card);
    font-size: 0.9rem;
    cursor: pointer;
}
.tisch-ansicht-haken input { width: auto; }
.tisch-ansicht-haken:has(input:checked) { border-color: var(--djk-blue); background: var(--djk-black-soft); }

/* Ein Widerspruch im Aktions-Formular (siehe admin/rabatte.php): auffaellig, aber nicht rot —
   es ist kein Fehler, sondern eine Einstellung, die anders wirkt, als sie gelesen wird. */
.rabatt-warnung {
    display: block;
    margin-top: 6px;
    padding: 8px 10px;
    border-left: 3px solid var(--djk-yellow);
    border-radius: 4px;
    background: rgba(245, 158, 11, .10);
    color: var(--djk-white);
    font-size: 0.8rem;
    line-height: 1.4;
}
.rabatt-warnung[hidden] { display: none; }

/* „Hier laeuft eine Aktion" — Rahmen und Schimmer in der Farbe aus der Verwaltung
   (Kasse → Zeichen & Farben). Nur ein Hinweis: WAS laeuft, steht im Preis daneben, wo der alte
   Preis durchgestrichen neben dem neuen steht. Ohne gesetzte Farbe greift keine Regel. */
.product-tile.hat-aktion,
.kategorie-tile.hat-aktion {
    border-color: var(--kasse-aktion, transparent);
    box-shadow: inset 0 0 0 2px var(--kasse-aktion, transparent);
}

/* Bewegung auf der Kachel, solange dort eine Aktion laeuft (Verwaltung → Kasse → Zeichen &
   Farben, "Aktion: Bewegung"). Sie soll das Auge holen, nicht den Abend lang zappeln:
   langsam (2,4 s bzw. 1,8 s), nur Helligkeit und Schimmer, KEINE Groessenaenderung — eine
   Kachel, die atmet, verschiebt beim Tippen ihre Nachbarn und man trifft daneben.
   Ohne gesetzte Aktionsfarbe passiert wie bisher gar nichts. */
/* WELCHE Kanten sich bewegen, waehlt der Wirt einzeln (Verwaltung → "Aktion: welche Kanten").
   Der Trick: jede Kante ist eine eigene Farb-Variable. Ist die Kante abgewaehlt, steht dort
   "transparent" — der Schatten wird trotzdem gezeichnet, man sieht ihn nur nicht. So bleibt die
   Schattenliste in beiden Bildern GLEICH LANG (sonst rechnet der Browser zwischen ungleichen
   Listen und die Bewegung springt), und jede Mischung der vier Kanten ergibt sich von selbst,
   ohne fuer 15 Kombinationen je eine Regel zu schreiben. */
body {
    --kasse-kante-oben: transparent;
    --kasse-kante-unten: transparent;
    --kasse-kante-links: transparent;
    --kasse-kante-rechts: transparent;
}
body.kasse-kante-oben   { --kasse-kante-oben:   var(--kasse-aktion, transparent); }
body.kasse-kante-unten  { --kasse-kante-unten:  var(--kasse-aktion, transparent); }
body.kasse-kante-links  { --kasse-kante-links:  var(--kasse-aktion, transparent); }
body.kasse-kante-rechts { --kasse-kante-rechts: var(--kasse-aktion, transparent); }

/* source/style_css/395_product_grid_seat_plan_z_report_continued.css - style.css: product grid seat plan z report continued, part 58 of 78 (built by werkzeuge/parts_build.php) */
/* Ruhiges Leuchten: der Schimmer tritt an den gewaehlten Kanten nach aussen. */
@keyframes kasse-aktion-leuchten {
    0%, 100% {
        box-shadow: inset 0 0 0 2px var(--kasse-aktion, transparent),
                    0 0 0 0 var(--kasse-kante-oben),
                    0 0 0 0 var(--kasse-kante-unten),
                    0 0 0 0 var(--kasse-kante-links),
                    0 0 0 0 var(--kasse-kante-rechts);
    }
    50% {
        box-shadow: inset 0 0 0 2px var(--kasse-aktion, transparent),
                    0 -7px 10px -2px var(--kasse-kante-oben),
                    0  7px 10px -2px var(--kasse-kante-unten),
                    -7px 0 10px -2px var(--kasse-kante-links),
                    7px  0 10px -2px var(--kasse-kante-rechts);
    }
}
/* Pulsierender Rahmen: nur die gewaehlten Kanten werden dicker. Alle vier gewaehlt ergibt
   wieder den Ring von frueher, der von 2 auf 6 px waechst. */
@keyframes kasse-aktion-pulsieren {
    0%, 100% {
        box-shadow: inset 0 0 0 2px var(--kasse-aktion, transparent),
                    inset 0  2px 0 0 var(--kasse-kante-oben),
                    inset 0 -2px 0 0 var(--kasse-kante-unten),
                    inset  2px 0 0 0 var(--kasse-kante-links),
                    inset -2px 0 0 0 var(--kasse-kante-rechts);
    }
    50% {
        box-shadow: inset 0 0 0 2px var(--kasse-aktion, transparent),
                    inset 0  6px 0 0 var(--kasse-kante-oben),
                    inset 0 -6px 0 0 var(--kasse-kante-unten),
                    inset  6px 0 0 0 var(--kasse-kante-links),
                    inset -6px 0 0 0 var(--kasse-kante-rechts);
    }
}
body.kasse-aktion-leuchten .product-tile.hat-aktion,
body.kasse-aktion-leuchten .kategorie-tile.hat-aktion {
    animation: kasse-aktion-leuchten 2.4s ease-in-out infinite;
}
body.kasse-aktion-pulsieren .product-tile.hat-aktion,
body.kasse-aktion-pulsieren .kategorie-tile.hat-aktion {
    animation: kasse-aktion-pulsieren 1.8s ease-in-out infinite;
}
/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt sie auch hier nicht —
   dieselbe Regel wie beim Einblenden des Rasters. */
@media (prefers-reduced-motion: reduce) {
    body.kasse-aktion-leuchten .product-tile.hat-aktion,
    body.kasse-aktion-leuchten .kategorie-tile.hat-aktion,
    body.kasse-aktion-pulsieren .product-tile.hat-aktion,
    body.kasse-aktion-pulsieren .kategorie-tile.hat-aktion {
        animation: none;
    }
}

/* Die Positionen einer offenen Online-/Terminal-Bestellung in der Kasse (personal/
   online_bestellungen.php). Wer an der Theke kassiert, soll sehen, WAS bestellt wurde und
   warum der Betrag niedriger ist als die Summe der Kartenpreise. */
.bestell-zeilen { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; }
.bestell-zeile {
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr) auto;
    gap: 8px;
    align-items: baseline;
    padding: 4px 0;
    border-top: 1px solid var(--djk-black-soft);
    font-size: 0.9rem;
}
.bestell-zeile-menge { color: var(--djk-gray); font-weight: 700; }
.bestell-zeile-name .hint { display: block; font-size: 0.78rem; }
.bestell-zeile-aktion {
    display: block;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--djk-success);
}
.bestell-zeile-preis { white-space: nowrap; }
.bestell-zeile-preis s { margin-right: 6px; color: var(--djk-gray); font-weight: 400; }

/* Die zwei Bloecke „Grosser Bildschirm" und „Telefon" in den Schrift-Einstellungen. */
.schrift-geraet { margin-bottom: 18px; }
.schrift-geraet + .schrift-geraet {
    padding-top: 14px;
    border-top: 1px solid var(--djk-black-soft);
}
.schrift-geraet-titel {
    margin-bottom: 8px;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--djk-blue);
}

/* source/style_css/400_print_preview_stations_tickets.css - style.css part 59 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Vorschau der Druckzettel (Verwaltung → System) ----------
   Ein Bondrucker kennt nur eine Schriftbreite: alle Zeichen sind gleich breit, und die
   Zeilenlänge ist gezählt, nicht gemessen. Deshalb steht die Vorschau in einer festen
   Schrift und in einer Fläche, die genau so viele Zeichen breit ist wie das Papier
   (--papier-zeichen, vom Skript gesetzt) — sonst sähe der Umbruch am Bildschirm anders aus
   als auf der Rolle, und die Vorschau wäre wertlos. */
.druck-vorschau-block { margin-top: 22px; }
.druck-vorschau-titel { font-size: 0.9rem; font-weight: 700; margin-bottom: 10px; }
.druck-vorschau-reihe { display: flex; gap: 18px; flex-wrap: wrap; }
.druck-vorschau-name { font-size: 0.8rem; font-weight: 600; opacity: 0.75; margin-bottom: 6px; }

.druck-papier {
    --papier-zeichen: 32;
    font-family: "Courier New", Consolas, monospace;
    font-size: 12px;
    line-height: 1.25;
    /* 0.6em ist die Zeichenbreite von Courier — mal der Zeichenzahl ergibt die Papierbreite. */
    width: calc(var(--papier-zeichen) * 0.62em + 24px);
    max-width: 100%;
    padding: 12px;
    margin: 0;
    background: #fff;
    color: #111;
    border: 1px solid var(--djk-border);
    border-radius: 4px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
    overflow-x: auto;
    white-space: pre;
}
/* Der Zettel ist immer weiss — auch im dunklen Erscheinungsbild. Papier wird nicht dunkel,
   und eine Vorschau, die anders aussieht als das Ergebnis, ist keine. */
body.thema-dunkel .druck-papier { background: #fff; color: #111; }

/* Das Logo auf dem Bon. `pixelated`, weil hier keine Schönheit gefragt ist, sondern die
   Wahrheit: jeder Punkt, den der Druckkopf schwärzt, ist einer — weichgezeichnet sähe die
   Vorschau besser aus als das Papier. */
.druck-bild {
    display: block;
    margin: 0 auto 2px;
    image-rendering: pixelated;
}

.druck-zeile { white-space: pre; }
.druck-zeile.ist-fett { font-weight: 700; }
.druck-zeile.ist-mitte { text-align: center; }
/* Die drei Grössen des Druckers (GS ! n): doppelt hoch, doppelt breit, beides.
   NICHT über `transform: scale()` — eine Transformation verändert nur das Aussehen, nicht den
   Platz: die Zeile blieb einzeilig hoch, der vergrösserte Text schob sich aus dem Papier
   heraus, und übrig blieb eine leere Fläche mit einer Bildlaufleiste. So sah die Vorschau
   kaputt aus, obwohl der Druck stimmte.
   Richtig ist `font-size`, denn die zählt beim Umbruch mit — und die jeweils NICHT gemeinte
   Achse wird per scale wieder halbiert. Doppelt breite Schrift braucht damit auch in der
   Vorschau doppelt so viel Platz, genau wie auf dem Papier (statt 32 passen dann 16 Zeichen). */
.druck-zeile.schrift-hoch,
.druck-zeile.schrift-breit,
.druck-zeile.schrift-gross { font-size: 2em; line-height: 1.15; }
.druck-zeile.schrift-hoch { transform: scaleX(0.5); transform-origin: left center; }
.druck-zeile.schrift-breit { transform: scaleY(0.5); transform-origin: left center; }
.druck-zeile.ist-mitte.schrift-hoch { transform-origin: center; }
.druck-zeile.ist-mitte.schrift-breit { transform-origin: center; }

.druck-schnitt {
    /* Grau, aber lesbar: #999 auf Papierweiß sind 2,8:1 — unter dem, was als lesbar gilt. */
    color: #6b7280;
    font-size: 11px;
    letter-spacing: -1px;
    margin: 6px 0;
    overflow: hidden;
    white-space: nowrap;
}

/* Knopf "Zettel drucken" unter den Positionen einer aufgeklappten Verlauf-Karte.
   Die Karte selbst ist ein <button> — der Knopf darin braucht deshalb etwas Abstand und
   einen eigenen Rand, damit er nicht wie ein Teil der Karte wirkt. */
.kasse-verlauf-druck {
    display: flex;
    justify-content: flex-end;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--djk-border);
}
.kasse-verlauf-druck-btn { min-width: 150px; }

/* Schriftart B des Druckers (ESC M 1): schmaler, damit mehr in eine Zeile passt. */
.druck-zeile.schrift-art-b { transform: scaleX(0.82); transform-origin: left center; }
.druck-zeile.ist-mitte.schrift-art-b { transform-origin: center; }
.druck-zeile.schrift-art-b.schrift-hoch { transform: scaleX(0.41); }
.druck-zeile.schrift-art-b.schrift-breit { transform: scaleX(0.82) scaleY(0.5); }

/* ---------- Stationen (Verwaltung → Küche & Bar) ----------
   Listen zum Ankreuzen: Leute, Kategorien, einzelne Gerichte. Bei 153 Gerichten muss die
   Liste scrollen statt die Seite zu sprengen — und die Suche darüber macht sie erst
   benutzbar. */
.station-wahl {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    max-height: 240px;
    overflow-y: auto;
    padding: 10px 12px;
    border: 1px solid var(--djk-border);
    border-radius: 5px;
    background: var(--djk-black-soft);
}
.station-wahl-eintrag {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 0.85rem;
    min-width: 170px;
    cursor: pointer;
}
.station-wahl-eintrag small { opacity: 0.6; margin-left: 4px; }
.station-suche { width: 100%; margin-bottom: 8px; }

/* Ein Gericht, das schon einer anderen Station gehört: sichtbar, aber nicht wählbar — und mit
   dem Namen der Station daneben. Ein ausgegrauter Haken ohne Begründung wäre ein Rätsel. */
.station-wahl-eintrag.ist-fremd { opacity: 0.55; cursor: not-allowed; }
.station-wahl-eintrag .station-belegt {
    color: var(--djk-danger);
    margin-left: 6px;
    white-space: nowrap;
}

/* --- Ein Ticket ist EIN Zettel (13.08.2026) ------------------------------------------------
   Der Wirt hat es hingezeichnet: links, wie es war — jede Kategorie ein eigener Kasten mit
   dunklem Balken darueber, fuenf Zettel fuer einen Tisch. Rechts, wie es sein soll: eine
   weisse Bahn, oben "Vorspeise", weiter unten "Hauptspeise", dazwischen nur duenne Linien.

   Der Grund ist derselbe wie beim Bon auf Papier: wer kocht, liest von oben nach unten und
   will wissen, WANN etwas raus muss. Aus welcher Kategorie der Speisekarte das Gericht stammt,
   hilft ihm dabei nicht — das ist eine Frage der Verwaltung, nicht der Kueche.

   Die Farben stehen ausgeschrieben und nicht als Variable: der Zettel bleibt in beiden
   Erscheinungsbildern weiss (siehe die Begruendung weiter oben bei .kueche-item). */
.kueche-ticket-detail .kueche-zettel {
    background: #ffffff;
    border-radius: 6px;
    overflow: hidden;
}
.kueche-ticket-detail .kueche-zettel-gang {
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    font-weight: 800;
    font-size: 1.15rem;
    color: #000000;
    padding: 14px 12px 6px;
    letter-spacing: 0.01em;
}
/* Der erste Gang braucht oben keinen Abstand — der Zettel faengt ja gerade erst an. */
.kueche-ticket-detail .kueche-zettel-gang:first-child { padding-top: 10px; }
/* Die Gruppen behalten ihre Aufgabe (senden, "unterwegs", "fertig"), verlieren aber ihren
   Kasten: auf dem Zettel gibt es keine Karten mehr, nur Zeilen. */
.kueche-ticket-detail .kueche-zettel .kueche-gruppe {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    margin: 0;
}
.kueche-ticket-detail .kueche-zettel .kueche-gruppe-head {
    margin: 0;
    padding: 6px 12px;
}
.kueche-ticket-detail .kueche-zettel .kueche-gruppe-name { color: #111827; }
/* Zustand als Streifen am linken Rand statt als Flaechenfarbe — sonst faellt der weisse
   Zettel wieder in bunte Kaesten auseinander, genau das, was weg sollte. */
.kueche-ticket-detail .kueche-zettel .kueche-gruppe-erledigt { box-shadow: inset 5px 0 0 var(--djk-success); }
.kueche-ticket-detail .kueche-zettel .kueche-gruppe-unterwegs { box-shadow: inset 5px 0 0 var(--djk-danger); }
/* Zwei Linien uebereinander (Unterkante der letzten Position + Oberkante der ersten der
   naechsten Gruppe) sehen aus wie ein Fehler. Auf dem Zettel trennt genau EINE Linie. */
.kueche-ticket-detail .kueche-zettel .kueche-item:last-child { border-bottom: 0; }
.kueche-ticket-detail .kueche-zettel .kueche-ticket-actions { padding: 8px 12px 12px; }

/* --- Das Blatt auf dem Brett (13.08.2026) --------------------------------------------------
   Was der Drucker ausgibt, steht genauso auf dem Bildschirm: dieselben Zeilen (.druck-zeile),
   dasselbe Papier (.druck-papier) wie in der Vorschau der Verwaltung. Hier kommt nur dazu, was
   Papier nicht hat — der Kopf mit dem Ziel und dem Knopf, der das Blatt dorthin schickt. */
.kueche-blatt { margin-bottom: 4px; }
.kueche-blatt-kopf {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
/* Auf dem Brett ist das Papier so breit wie die Spalte — die feste Zeichenbreite der Vorschau
   wäre hier eine schmale Säule mitten im Bild. Die Zeilen selbst bleiben unangetastet. */
.kueche-ticket-detail .druck-papier {
    width: 100%;
    max-width: 100%;
    border: 0;
    box-shadow: none;
    border-radius: var(--brett-g-zettel-rundung, 6px);
    padding: var(--brett-g-zettel-polster, 10px) calc(var(--brett-g-zettel-polster, 10px) + 2px);
    line-height: var(--brett-g-zettel-zeilenhoehe, 1.25);
    /* Der Zettel ist so breit wie die Spalte — die Schrift richtet sich danach (unten). */
    container-type: inline-size;
    /*
     * 15 PX SIND DIE WURZEL ALLER `em` AUF DIESEM ZETTEL (04.09.2026).
     *
     * Der Wirt drehte an „Schrift auf dem Zettel" und die Zeile mit dem GERICHT blieb, wie sie
     * war. Grund: sie misst sich nicht an der gerechneten Groesse, sondern an dieser hier —
     * `.ist-position` hat `font-size: 1.3em !important`, und die Kopfzeilen tragen ein
     * `style="font-size: 2em"` vom Server. Beide `em` zeigen hierher.
     *
     * Also muss der Regler HIER ansetzen. Dann wachsen alle drei Sorten Zeile gemeinsam: die
     * gewoehnliche ueber ihre eigene Rechnung weiter unten, Gericht und Kopf ueber dieses `em`.
     */
    font-size: calc(15px * var(--brett-g-zettel-faktor, 1));
}
/*
 * Die Zeile ist auf dem Papier genau `--papier-zeichen` Zeichen breit (Server, druck_umbruch).
 * Damit dieselbe Zeile auch auf einer schmalen Spalte GANZ zu sehen ist, wird die Schriftgröße
 * aus der Spaltenbreite gerechnet: 100cqw geteilt durch die Zeichenzahl, geteilt durch die
 * Zeichenbreite der Schreibmaschinenschrift (0,6 em).
 *
 * Vorher stand die Größe fest bei 15 px — auf dem Telefon endete jede zweite Zeile bei
 * „1x Peperoni gegri" und der Rest lag außerhalb des Zettels.
 */
@supports (container-type: inline-size) {
    .kueche-ticket-detail .druck-zeile {
        /* KEINE Obergrenze: der Wirt zieht die Spalte breit, und die Schrift geht mit.
           Auf Papier ist die Zeile so viele Zeichen breit wie eingestellt — der Bildschirm
           bildet genau das ab, nur eben in der Größe, die gerade Platz hat. */
        font-size: calc(100cqw / var(--papier-zeichen, 32) / 0.62 * var(--brett-g-zettel-faktor, 1));
    }
    /* Doppelt breite Schrift verbraucht zwei Plätze — die Rechnung oben gilt weiter, die Zeile
       ist einfach doppelt so groß (wie auf dem Papier). */
    .kueche-ticket-detail .druck-zeile.schrift-hoch,
    .kueche-ticket-detail .druck-zeile.schrift-breit,
    .kueche-ticket-detail .druck-zeile.schrift-gross {
        font-size: calc(200cqw / var(--papier-zeichen, 32) / 0.62 * var(--brett-g-zettel-faktor, 1));
    }
}
/*
 * Umbrochen wird HIER, nicht auf dem Server: wird die Spalte breiter gezogen, rutschen die
 * Wörter wieder in eine Zeile. Der Rest einer langen Zeile rückt unter den Namen ein
 * (hängender Einzug), damit die Mengenangabe am linken Rand allein steht — wie auf dem Bon.
 */
.kueche-ticket-detail .druck-zeile {
    white-space: pre-wrap;
    overflow-wrap: break-word;
    padding-left: 3ch;
    text-indent: -3ch;
}
/* Mittige Zeilen (Kopf, Tisch, Uhrzeit) haben keinen hängenden Einzug — er verschöbe sie. */
.kueche-ticket-detail .druck-zeile.ist-mitte { padding-left: 0; text-indent: 0; }
/* Der Schnitt trennt zwei ZETTEL für zwei Leute — er muss deutlicher sein als eine Trennlinie
   zwischen zwei Positionen, sonst liest sich das Blatt darunter wie eine Fortsetzung. */
.kueche-blatt-schnitt {
    color: var(--djk-gray);
    font-size: 12px;
    letter-spacing: 0;
    margin: 10px 0 14px;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
}
/* Nach dem letzten Blatt kommt nichts mehr — ein Schnitt ins Leere sähe aus wie ein
   vergessener Teil. */
.kueche-blatt:last-of-type + .kueche-blatt-schnitt { display: none; }

/* --- Die Kasse zeigt denselben Zettel wie die Küche (13.08.2026) ---------------------------
   Der Wirt: „точно такой же тикет должен быть на кассе, лист заказов, корзина." Und er hat
   recht: es ist DIESELBE Bestellung. Wenn sie auf drei Bildschirmen drei Gestalten hat, muss
   man beim Vergleichen jedes Mal neu suchen, welche Zeile welcher entspricht.

   Deshalb bekommt der Warenkorb das Aussehen des Zettels: weiße Bahn, Schreibmaschinenschrift,
   gestrichelte Linien zwischen den Positionen. Was er BEHÄLT, sind die Preise und die
   Handgriffe (Menge, wischen zum Löschen) — die gehören an die Kasse und auf keinen
   Küchenzettel. */
.cart-list {
    background: #ffffff;
    border-radius: 6px;
    padding: 4px 0;
}
.cart-list li.cart-line {
    background: #ffffff;
    margin-bottom: 0;
    border-top: 2px dashed #9ca3af;
    border-radius: 0;
    padding: 8px 12px;
}
.cart-list li.cart-line:first-child { border-top: 0; }
.cart-list li.cart-line:last-child { margin-bottom: 0; }
/* Die Akzentränder der wartenden/ungebuchten Zeilen bleiben — sie sagen etwas, das der Zettel
   nicht sagen kann („noch nicht gesendet", „liegt ohne Netz hier"). */
.cart-list .cart-item-name,
.cart-list .cart-item-sub,
.cart-list .cart-preis-spalte {
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}
.cart-list .cart-item-name {
    color: #000000;
    font-weight: 700;
    font-size: 1.02rem;
    font-variant-numeric: tabular-nums;
}
.cart-list .cart-item-sub { color: #1f2937; }
.cart-list .cart-preis-spalte,
.cart-list .cart-item-sub-price { color: #111827; }
/*
 * Der Betrag im Kassenbericht.
 *
 * Diese Liste verwendet `.cart-item-price` und nicht `.cart-preis-spalte` — beim Umbau des
 * Warenkorbs auf das Papier-Aussehen (weisser Grund) bekam nur die zweite eine dunkle Farbe.
 * Die erste erbte weiter die helle Schrift des dunklen Themas und stand damit weiss auf weiss:
 * der Wirt hat den Betrag eingekringelt, weil er ihn nicht lesen konnte. Gemessen war er
 * rgb(233,236,242) auf rgb(255,255,255).
 */
.cart-list .cart-item-price { color: #111827; }
.cart-list .cart-item-vorspeise span { color: #b45309; font-weight: 700; }
body.thema-dunkel .cart-list,
body.thema-dunkel .cart-list li.cart-line { background: #ffffff; }
/*
 * Die noch nicht gebuchte Zeile behält, was sie immer hatte: links blau (wischen zum
 * Bearbeiten), rechts rot (wischen zum Löschen) — und die Ränder sagen dasselbe wie die Knöpfe
 * dahinter. Beim Umbau auf das Papier-Aussehen war der Inhalt weiß geworden, die farbigen
 * Ränder aber unter der neuen Regel verschwunden; der Wirt hat es sofort gesehen.
 *
 * Der Inhalt braucht einen DECKENDEN Hintergrund, sonst schienen die Knöpfe durch ihn hindurch,
 * statt beim Wischen aufzutauchen.
 */
.cart-list li.cart-line.cart-line-pending {
    padding: 0;
    border-left: 3px solid #1d4ed8;
    border-right: 3px solid #c81e1e;
}
.cart-list .cart-line-pending .cart-line-inhalt {
    background: #ffffff;
    padding: 10px 14px 10px 10px;
}
.cart-list .cart-line-pending .cart-item-name,
.cart-list .cart-line-pending .cart-preis-spalte { color: #000000; }
/* Ohne Netz gebucht: dieselbe Sprache, nur gestrichelt — sie liegt noch auf dem Gerät. */
.cart-list li.cart-line.cart-line-wartend { background: #ffffff; }

/* --- „Drucken" am Zettel und an der Karte (13.08.2026) -------------------------------------
   Der Knopf steht dort, wo auf Papier der Schnitt käme: unter dem Blatt. Auf der
   Übersichtskarte sitzt er unten rechts — nah genug, um ihn zu treffen, weit genug weg vom
   Rest der Karte, die den Auftrag öffnet. */
.kueche-blatt-fuss { display: flex; justify-content: flex-end; margin-top: 6px; }
/*
 * Zwei Knöpfe nebeneinander, gleich breit (23.08.2026).
 *
 * Der Wirt hat sie im Betrieb selbst zurechtgeschoben und das Ergebnis fotografiert: volle
 * Farbe statt durchsichtiger Umrandung, und beide gleich groß. Grund ist nicht der Geschmack,
 * sondern die Küche: ein durchsichtiger Knopf auf dunklem Grund ist bei Dampf und schrägem
 * Blick kaum zu sehen, und wer mit dem Handrücken tippt, braucht eine Fläche.
 */
.kueche-mini-fuss { display: flex; gap: var(--brett-k-knopf-luecke, 8px); margin-top: 8px; }
.kueche-mini-fuss > .kueche-drucken-btn,
.kueche-mini-fuss > .kueche-ticket-btn { flex: 1 1 0; min-width: 0; }
.kueche-drucken-btn {
    width: 100%;
    padding: var(--brett-k-knopf-hoehe, 15px) 20px;
    border-radius: var(--brett-k-knopf-rundung, 5px);
    border: 1.5px solid #e4e4e4;
    background: var(--brett-k-drucken-farbe, #2f7cc9);
    color: #f1f1f1;
    font-size: var(--brett-k-knopf-gross, 0.78rem);
    font-weight: 700;
    cursor: pointer;
}
.kueche-drucken-btn:hover { background: #2569ab; border-color: #ffffff; color: #ffffff; }
.kueche-drucken-btn:disabled { opacity: 0.6; cursor: default; }
/* „Fertig" an der Übersichtskarte: dasselbe Maß wie „Drucken" daneben, und ebenfalls voll —
   der helle Schleier (rgba) ließ ihn wie abgeschaltet aussehen. Der große grüne Knopf im
   geöffneten Auftrag bleibt, wie er ist: dort ist er der Handgriff des Fensters. */
.kueche-mini-fuss > .kueche-mini-fertig {
    padding: var(--brett-k-knopf-hoehe, 15px) 20px;
    border-radius: var(--brett-k-knopf-rundung, 5px);
    border: 1.5px solid #15803d;
    background: var(--brett-k-fertig-farbe, #16a34a);
    color: #ffffff;
    font-size: var(--brett-k-knopf-gross, 0.78rem);
    font-weight: 700;
}
.kueche-mini-fuss > .kueche-mini-fertig:hover { background: #15803d; border-color: #ffffff; }
.kueche-mini-fuss > .kueche-mini-fertig:disabled {
    background: var(--djk-black-soft);
    border-color: var(--djk-border);
    color: var(--djk-gray);
}

/* source/style_css/405_print_preview_stations_tickets_continued.css - style.css: print preview stations tickets continued, part 60 of 78 (built by werkzeuge/parts_build.php) */
/* Kategorie des Tisches auf der Übersichtskarte — gedämpft, sie ergänzt die Nummer, sie
   ersetzt sie nicht. Und der Knopf im Auswahlfenster bleibt sichtbar, egal wie weit die Liste
   der Extras gerollt ist: er ist das Ziel des ganzen Fensters. */
.kueche-ticket-mini-kat { font-size: 0.72rem; color: var(--djk-gray); font-weight: 600; }
/*
 * Der Knopf klebte unten fest (position: sticky) und lag damit UEBER dem, was darunter
 * kam — auf dem Bildschirmfoto des Wirts verdeckte er „Kueche Divers" zur Haelfte. Jetzt
 * steht er da, wo er hingehoert: am Ende des Fensters. Der Schatten bleibt, er trennt ihn
 * vom Kommentarfeld darueber.
 */
#pickerAddBtn {
    /* position: sticky; */
    z-index: 3;
    margin-top: 15px;
    margin-bottom: 10px;
    box-shadow: 0 -10px 14px -10px rgba(0, 0, 0, 0.55);
}

/* --- Buchungen im Verlauf (13.08.2026) -----------------------------------------------------
   Grün: die Station hat es bekommen. Rot: nur gebucht — sie sieht davon nichts. Die Farbe sitzt
   am linken Rand, nicht auf der ganzen Fläche: sie soll auffallen, aber die Zeilen lesbar
   lassen. */
.buchungen-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; margin-bottom: 22px; }
.buchung-karte {
    background: var(--djk-black-card);
    border: 1px solid var(--djk-border);
    border-left: 5px solid var(--djk-border);
    border-radius: 6px;
    padding: 10px 12px;
}
.buchung-karte.ist-gesendet { border-left-color: var(--djk-success, #4caf50); }
.buchung-karte.ist-offen { border-left-color: var(--djk-danger, #e05a5a); }
.buchung-kopf { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.buchung-ort { color: var(--djk-gray); font-size: 0.8rem; }
.buchung-zeit { margin-left: auto; color: var(--djk-gray); font-size: 0.8rem; }
.buchung-zeile { color: var(--djk-gray); font-size: 0.82rem; margin: 4px 0 8px; }
.buchung-knoepfe { display: flex; gap: 6px; flex-wrap: wrap; }

/* source/style_css/410_cart_buttons_settings_paid_online.css - style.css part 61 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Die Knöpfe im Warenkorb: einer wie der andere (13.08.2026) ----------------------------
   Der Wirt hat es angestrichen: „−" war grau, „+" schwarz, und bei einem langen Namen schob
   sich der Preis mitten ins Wort („2× Alkoholfrei Spalter Bier" / „7,80 €").

   Beides dieselbe Ursache: die Zeile war auf Enge gebaut. Jetzt hat der Preis seinen festen
   Platz rechts (er schrumpft nicht und wird nicht überschrieben), der Name bricht stattdessen
   um — auf einem Zettel steht er ja auch in zwei Zeilen. Und die beiden Mengen-Knöpfe sehen
   gleich aus: gleiche Größe, gleicher Rahmen, gleiche Farbe. Ein Knopf, der anders aussieht,
   verspricht etwas anderes. */
.cart-list .cart-item-name {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    /* Der Name darf umbrechen, der Preis nicht angeknabbert werden. */
    flex: 1 1 auto;
    padding-right: 10px;
    line-height: 1.25;
}
.cart-list .cart-preis-spalte {
    flex: 0 0 auto;
    white-space: nowrap;
    text-align: right;
}
.cart-list .posten-qty-btn,
.cart-list .posten-qty-btn:disabled {
    width: 38px;
    height: 38px;
    border: 1.5px solid #cbd5e1;
    border-radius: 6px;
    background: #ffffff;
    color: #111827;
    font-size: 1.15rem;
    font-weight: 800;
}
.cart-list .posten-qty-btn:disabled { opacity: 0.4; }
.cart-list .posten-qty-btn:not(:disabled):hover { border-color: var(--djk-yellow); }
.cart-list .posten-qty-value { color: #111827; }
.cart-list .posten-qty-label { color: #4b5563; }

/* --- Knöpfe in den Rückfrage-Fenstern: so hoch wie überall (13.08.2026) --------------------
   Mit dem Symbol darin wuchsen sie auf das Doppelte: ein SVG ohne Maßangabe nimmt sich die
   Höhe, die es kriegen kann, und zieht den Knopf mit. Der Wirt hat die Größe angestrichen und
   danebengelegt, wie es sein soll — wie „In den Warenkorb".

   Also: das Symbol bekommt ein Maß, der Knopf seine normale Polsterung, und beides steht in
   einer Zeile nebeneinander. */
.modal-box .btn-block {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    /*
     * 40 px — so hat der Wirt es vorgegeben (vorher 50).
     *
     * Diese Knöpfe werden im Vorbeigehen getroffen, mit einer Hand am Tablett: „Ja, senden" und
     * „Nein, nur buchen" entscheiden, ob die Küche die Bestellung sieht. Danebentippen kostet
     * hier mehr als ein paar Pixel Platz.
     */
    padding: 40px 18px;
    line-height: 1.2;
}
/*
 * ALLE Knöpfe im Fenster sind gleich rund — auch der unterste.
 *
 * Hier stand einmal das Gegenteil: der letzte Knopf lief unten mit 44 px aus, „rund wie der
 * Bildschirm des Telefons". Der Gedanke stimmt nur, wenn der Knopf den Rand auch wirklich
 * berührt — das tut er nicht. Gemessen auf dem Telefon (390×844): der Knopf endet bei 826, das
 * Fenster hat darunter noch 24 px Polster. Ein Knopf, der oben eckig und unten stark gerundet
 * ausläuft und dabei in der Luft steht, sieht neben dem Knopf darüber falsch aus — genau das
 * hat der Wirt angestrichen: „кнопку снизу бордер радиус сделай как и наверху."
 *
 * Es gilt also die Rundung von `.btn`, wie bei jedem anderen Schalter im Haus.
 */
.modal-box .btn-block svg,
.modal-box .btn-block .icon {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
}

/* Fettgrad 2 („fett + Doppeldruck") — auf Papier fährt der Kopf zweimal über die Zeile, auf
   dem Bildschirm ist das ein Hauch mehr Strichstärke. */
.druck-zeile.ist-fett-stark { -webkit-text-stroke: 0.4px currentColor; }

/* --- Einstellungen: zwei Spalten, wo Platz ist (13.08.2026) --------------------------------
   Eine Einstellungsseite ist eine Liste kurzer Entscheidungen. Untereinander gestapelt ergibt
   das auf einem breiten Bildschirm eine endlose Bahn, durch die man rollt, obwohl daneben alles
   frei ist. Ab 1100 px stehen die Felder deshalb nebeneinander — Schalter und Hinweise bleiben
   über die volle Breite, denn sie werden gelesen, nicht ausgefüllt. */
@media (min-width: 1100px) {
    body.admin-body .form-card .field-paar,
    body.admin-body .admin-karte .field-paar {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0 22px;
        align-items: start;
    }
    /* Die Vorschau der Zettel steht neben den Einstellungen, nicht darunter: wer eine Größe
       ändert, will die Wirkung sehen, ohne zu rollen. */
    .druck-vorschau-reihe { align-items: flex-start; }
}
/* Auf allen Breiten: die Karte darf den Platz nutzen, den ihre Seite hergibt. */
body.admin-body .form-card { max-width: 1180px; }

/* --- „Schon im Netz bezahlt" ---------------------------------------------------------------
 *
 * Ein Merker in Gruen an allen drei Orten, an denen jemand kassieren koennte: auf der
 * Tisch-Kachel, in der Kopfzeile des Warenkorbs und auf der Karte des Kuechenbretts. Dieselbe
 * Farbe wie „fertig/bereit" — Gruen heisst in diesem Haus ueberall „erledigt".
 */
.tisch-tile-bezahlt {
    position: absolute;
    top: 5px;
    left: 5px;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--djk-success);
    color: #fff;
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.2px;
}
.bezahlt-hinweis {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 800;
    background: color-mix(in srgb, var(--djk-success) 20%, transparent);
    color: var(--djk-success);
}
.kueche-bezahlt {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--djk-success);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 800;
    white-space: nowrap;
    vertical-align: middle;
}
.kueche-bezahlt-klein { margin-left: 0; font-size: 0.68rem; padding: 1px 7px; }
.kueche-ticket-mini-bezahlt { padding: 2px 0 4px; }


/* Eigene Fertig-Zeit am Online-Auftrag: Feld und Knopf in einer Zeile, umbruchfaehig auf dem
   Telefon. Das Feld ist bewusst so gross wie die Knoepfe daneben — es ist gleichberechtigt. */
.kueche-zeit-eigen {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 8px;
}
.kueche-zeit-eigen-text {
    font-size: 0.78rem;
    opacity: 0.75;
}
.kueche-zeit-feld {
    /* Breit genug, dass die Uhrzeit vollstaendig darin steht — auf dem iPhone war das Feld
       sonst ein Kaestchen, in dem man die eigene Eingabe nicht lesen konnte. */
    min-width: 116px;
    padding: 11px 12px;
    border-radius: 999px;
    border: 1.5px solid var(--djk-blue);
    background: var(--djk-black-card, #1a1a1f);
    color: inherit;
    font-size: 0.95rem;
    font-weight: 700;
}

/*
 * Drei Farben, drei Bedeutungen — der Wirt wollte die beiden unteren Wege unterscheidbar haben:
 *
 *   schnelle Zeiten (17:15 …)   neutral, das ist der Normalfall
 *   Wunschzeit des Gastes       gruen — sie kommt von IHM, man sagt nur zu
 *   eigene Zeit                 violett — hier entscheidet die Kueche selbst
 */
.kueche-zeit-wunsch {
    border-color: var(--djk-success);
    background: color-mix(in srgb, var(--djk-success) 14%, transparent);
    color: var(--djk-success);
}
.kueche-zeit-eigen-btn {
    border-color: var(--djk-blue);
    background: color-mix(in srgb, var(--djk-blue) 14%, transparent);
    color: var(--djk-blue);
}
.kueche-zeit-wunsch:hover { border-color: var(--djk-success); }
.kueche-zeit-eigen-btn:hover { border-color: var(--djk-blue); }


/* --- „Zum Mitnehmen" -------------------------------------------------------------------------
 *
 * Der Merker sagt dem Koch, WIE angerichtet wird: Schachtel statt Teller. Deshalb faellt er auf
 * — auf dem Brett wie im Warenkorb der Kasse. Orange, weil Gruen im Haus „erledigt" heisst und
 * Rot „Achtung": das hier ist keins von beidem, sondern eine Ansage.
 */
.kueche-mitnehmen {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 9px;
    border-radius: 999px;
    background: #ea580c;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 800;
    white-space: nowrap;
    vertical-align: middle;
}
.kueche-item-mitnehmen { border-left: 3px solid #ea580c; padding-left: 7px; }
.cart-item-mitnehmen {
    color: #ea580c;
    font-weight: 700;
}


/* --- Handbuch (admin/handbuch.php) ----------------------------------------------------------
 *
 * Lesbarkeit vor Dichte: eine Spalte, ruhige Abstaende, Klickwege als Chips. Wer hier liest,
 * sucht eine Antwort und will sie in einem Blick finden — nicht in einer Wand aus Text.
 */
.hb-suche-zeile { margin: 4px 0 18px; }
.hb-suche {
    width: 100%;
    max-width: 560px;
    padding: 12px 16px;
    border-radius: 999px;
    border: 1.5px solid var(--djk-border);
    background: var(--feld-grund, var(--djk-black-card));
    color: inherit;
    font-size: 0.95rem;
}
.hb-inhalt {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 26px;
}
.hb-inhalt-link {
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-card);
    font-size: 0.86rem;
    font-weight: 600;
    text-decoration: none;
    color: inherit;
}
.hb-inhalt-link:hover { border-color: var(--djk-yellow); }
.hb-kapitel {
    max-width: 860px;
    margin: 0 0 34px;
    padding: 22px 24px;
    border-radius: 16px;
    border: 1px solid var(--djk-border);
    background: color-mix(in srgb, var(--djk-black-card) 88%, transparent);
    scroll-margin-top: 80px;
}
.hb-kapitel h3 {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 12px;
    font-size: 1.15rem;
}
.hb-kapitel h3 .icon { width: 22px; height: 22px; color: var(--djk-yellow); }
.hb-lead { font-size: 1rem; opacity: 0.9; margin: 0 0 14px; }
.hb-schritte { margin: 0 0 14px; padding-left: 22px; }
.hb-schritte > li { margin-bottom: 12px; line-height: 1.55; }
.hb-liste { margin: 0 0 14px; padding-left: 22px; }
.hb-liste > li { margin-bottom: 9px; line-height: 1.55; }
.hb-weg {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 8px;
    background: color-mix(in srgb, var(--djk-yellow) 14%, transparent);
    color: var(--djk-yellow);
    font-weight: 700;
    font-size: 0.86rem;
    white-space: nowrap;
}
.hb-weg-link { text-decoration: none; }
.hb-weg-link:hover .hb-weg { background: color-mix(in srgb, var(--djk-yellow) 26%, transparent); }
.hb-merke {
    margin: 14px 0 0;
    padding: 12px 16px;
    border-left: 3px solid var(--djk-yellow);
    border-radius: 0 10px 10px 0;
    background: color-mix(in srgb, var(--djk-yellow) 8%, transparent);
    line-height: 1.55;
}
.hb-tabelle { width: 100%; border-collapse: collapse; margin: 6px 0 14px; }
.hb-tabelle th, .hb-tabelle td {
    padding: 9px 10px;
    border-bottom: 1px solid var(--djk-border);
    text-align: left;
    vertical-align: top;
    font-size: 0.92rem;
    line-height: 1.5;
}
.hb-tabelle th { font-weight: 800; font-size: 0.8rem; text-transform: uppercase; letter-spacing: .04em; opacity: .75; }
.hb-bild { margin: 16px 0; }
.hb-bild img { width: 100%; border-radius: 12px; border: 1px solid var(--djk-border); display: block; }
.hb-bild figcaption { margin-top: 7px; font-size: 0.82rem; opacity: .7; }
/* Solange ein Bild fehlt, steht hier ein ruhiger Platzhalter statt eines kaputten Bildes. */
.hb-bild-platz {
    padding: 22px;
    border-radius: 12px;
    border: 1px dashed var(--djk-border);
    text-align: center;
    font-size: 0.85rem;
    opacity: .6;
}


/* Wegweiser auf der Seite System: wohin die frueheren Bloecke gezogen sind. */
.system-umzug { list-style: none; margin: 0; padding: 0; }
.system-umzug li { margin-bottom: 8px; }
.system-umzug a {
    display: block;
    padding: 11px 14px;
    border-radius: 10px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    text-decoration: none;
    color: inherit;
    line-height: 1.5;
}
.system-umzug a:hover { border-color: var(--djk-yellow); }


/* ==========================================================================================
   Blockgrund auf dem Handy und Kartenzeilen in Tabellen

   Am grossen Bildschirm liegt jeder Block auf durchscheinendem Weiss; auf dem Handy fehlte
   das, und die Bloecke gingen im warmen Grund unter — man sah keine Kante mehr, wo ein
   Formular anfaengt und das naechste aufhoert. Genau das hat der Wirt angezeichnet.

   `#ffffffba` ist dasselbe Weiss mit 73 % Deckung: der Ton der Seite bleibt sichtbar, die
   Flaeche wird trotzdem eine Flaeche.

   NICHT im dunklen Erscheinungsbild: dort waere eine weisse Flaeche ein Loch.
   ========================================================================================== */
@media (max-width: 900px) {
    body.admin-body:not(.thema-dunkel) .admin-content .form-card,
    body.admin-body:not(.thema-dunkel) .admin-content .admin-karte,
    body.admin-body:not(.thema-dunkel) .admin-content .admin-collapsible,
    body.admin-body:not(.thema-dunkel) .admin-content .admin-mini-card,
    body.admin-body:not(.thema-dunkel) .admin-content .admin-produkt-card,
    body.admin-body:not(.thema-dunkel) .admin-content .wg-card {
        background: #ffffffba;
    }
}

/* Auf dem Telefon ist jede Tabellenzeile eine Karte (siehe tabellen_mobil.js) — also bekommt
   sie denselben Grund wie ein Block. Sonst schwimmen die Zeilen ohne Kante im Seitenton. */
@media (max-width: 700px) {
    body.admin-body:not(.thema-dunkel) .table-wrap tr,
    body.admin-body:not(.thema-dunkel) .admin-table-wrap tr {
        background: #ffffffba;
    }
}


/* source/style_css/415_cart_buttons_settings_paid_online_continued.css - style.css: cart buttons settings paid online continued, part 62 of 78 (built by werkzeuge/parts_build.php) */
/* ==========================================================================================
   Eingeklapptes Menue: die Unterpunkte wandern nach oben

   Ist die Leiste zusammengeschoben, sieht man nur noch Symbole — und die Unterpunkte einer
   Seite (Alle Produkte, Kategorien, Extras, Groessen, Warengruppen) verschwinden ganz. Der
   Wirt hat genau das angezeichnet: "если закрываем левое меню, их не видно."

   Sie sind aber schon da: dieselbe Leiste, die das Handy oben zeigt (.admin-mobile-subnav,
   gebaut in admin/includes/header.php fuer JEDEN Bereich mit Unterpunkten). Sie wird hier
   nur wieder eingeblendet — kein zweiter Nachbau, der beim naechsten neuen Reiter zurueckbleibt.

   `admin-menue-zu` setzt das Skript am <html>, sobald jemand die Leiste zuschiebt.
   ========================================================================================== */
html.admin-menue-zu .admin-mobile-subnav {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 0 4px;
    margin-bottom: 6px;
}
html.admin-menue-zu .admin-mobile-subnav a {
    flex: 0 1 auto;
    padding: 8px 16px;
    border-radius: 8px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-card);
    color: inherit;
    font-size: 0.84rem;
    font-weight: 700;
    white-space: nowrap;
    text-decoration: none;
}
html.admin-menue-zu .admin-mobile-subnav a:hover { border-color: var(--djk-yellow); }
html.admin-menue-zu .admin-mobile-subnav a.active {
    background: var(--djk-yellow);
    border-color: var(--djk-yellow);
    color: #fff;
}


/* source/style_css/420_divers_clear_field_printers.css - style.css part 63 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* --- Freie Posten (Divers) im Speisen-Fenster ------------------------------------------------
 *
 * Je Posten eine Zeile — Bezeichnung mit Suche, Betrag, Kreuz — und darunter ein Pluszeichen für
 * den nächsten (17.08.2026, „ещё один диверс или много"). Sie erscheinen erst, wenn eine Station
 * gewählt ist. Die Vorschlagsliste haengt UNTER dem Feld und ueberdeckt den Betrag — deshalb
 * liegt sie absolut und das Fenster darf sie nicht abschneiden.
 */
.divers-felder {
    display: block;
    margin-top: 10px;
}
.divers-felder[hidden] { display: none; }
.divers-zeile {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    margin-bottom: 8px;
}
.divers-such-hülle { position: relative; flex: 1 1 auto; min-width: 0; }
.divers-zeile input[type="number"] { width: 120px; flex: 0 0 auto; min-width: 0; }
/* Der Betrag fehlt, obwohl eine Bezeichnung dasteht: rot, und der Knopf „In den Warenkorb"
   geht nicht weiter. Ein still weggefallener Posten war vorher erst auf dem Bon zu sehen. */
.divers-zeile input.ist-fehler {
    border-color: var(--djk-danger);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--djk-danger) 22%, transparent);
}
/* Kreuz und Pluszeichen sind gleich gross und stehen in derselben Spur — sonst sieht die
   Zeile aus, als gehörte das eine nicht zum anderen. */
.divers-zeile-weg,
.divers-mehr {
    flex: 0 0 auto;
    width: 44px;
    height: 46px;
    border: 1px solid var(--feld-rand);
    border-radius: var(--feld-radius);
    background-color: var(--feld-grund);
    color: var(--djk-white);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
}
.divers-zeile-weg:hover { border-color: var(--djk-danger); color: var(--djk-danger); }
.divers-mehr { border-style: dashed; color: var(--djk-yellow); }
.divers-mehr:hover { border-style: solid; }
/*
 * DER BLOCK „EXTRA" IM AUSWAHLFENSTER (26.09.2026) — dieselbe Zeile wie ein freier Posten:
 * Auswahl, Aufpreis (fest), Kreuz und Plus in derselben Spur. Der Aufpreis ist nur Auskunft.
 */
.picker-extra-zeile { align-items: center; margin-top: 8px; margin-bottom: 0; }
.picker-extra-zeile .picker-extra-wahl { flex: 1 1 auto; min-width: 0; }
.picker-extra-zeile .picker-extra-preis { width: 110px; flex: 0 0 auto; min-width: 0; text-align: right; pointer-events: none; }
.picker-extra-platz { flex: 0 0 44px; }
@media (max-width: 400px) { .picker-extra-zeile .picker-extra-preis { width: 92px; } }
.divers-vorschlaege {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    max-height: 210px;
    overflow-y: auto;
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    background: var(--djk-black-card);
    box-shadow: 0 10px 26px rgba(0, 0, 0, .35);
}
.divers-vorschlaege[hidden] { display: none; }
.divers-vorschlag {
    text-align: left;
    padding: 10px 14px;
    border: 0;
    background: none;
    color: inherit;
    font-size: 0.92rem;
    cursor: pointer;
}
.divers-vorschlag:hover { background: color-mix(in srgb, var(--djk-yellow) 14%, transparent); }
/* Der gespeicherte Preis steht rechts im Vorschlag — man wählt ein Wort und weiss dabei, was
   es kostet. Wörter aus der Zeit vor dem Preis haben keinen; dann fehlt die Angabe. */
.divers-vorschlag-preis { float: right; color: var(--djk-gray); font-weight: 600; }
/* Im Warenkorb steht der freie Posten wie ein Extra unter dem Gericht. */
.cart-item-divers { font-weight: 600; }

/* ---------- Feld leeren: der ✕ rechts im Eingabefeld (assets/js/feld_leeren.js) ----------
   Die Bauweise ist dieselbe wie bei .input-icon + .password-toggle, nur eben für JEDES Feld,
   in das man mit der Tastatur schreibt. Das Skript hängt die Hülle nur dort ein, wo es noch
   keine gestellte gibt. */
.feld-x-huelle { position: relative; display: block; }

.feld-leeren {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--djk-gray);
    /* Das Kreuz ist ein Zeichen, kein Text — ohne eigene Zeilenhöhe säße es nicht mittig. */
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.75;
    transition: opacity var(--transition), color var(--transition), background var(--transition);
}
.feld-leeren:hover,
.feld-leeren:focus-visible {
    opacity: 1;
    color: var(--djk-yellow);
    background: color-mix(in srgb, var(--djk-yellow) 12%, transparent);
}
.feld-leeren[hidden] { display: none; }

/* Im mehrzeiligen Feld gehört er nach oben — in der Mitte stünde er mitten im Text. */
.feld-leeren-oben { top: 8px; transform: none; }

/* Platz für den Knopf, damit die Schrift nicht darunter läuft.
   Mit Nachdruck, weil viele Felder ihr Innenmaß über die Kurzform `padding:` setzen und diese
   dann gewinnt — hier geht es nur um DIESE eine Seite. */
input.feld-hat-x,
textarea.feld-hat-x { padding-right: 40px !important; }

/* ---------- Küche / Bar im Verlauf der Kasse: die Buchungen dieser Station ----------
   Ein Block ist ein Druck auf „Buchen". Rot heisst: der Zettel ist nie losgegangen. */
.stb-block {
    border: 1px solid var(--djk-border);
    border-radius: 12px;
    background: var(--djk-black-card);
    padding: 12px 14px;
    margin-bottom: 12px;
}
.stb-kopf { font-size: 0.86rem; line-height: 1.5; }
.stb-datum { font-weight: 800; margin-bottom: 2px; }
.stb-kopf-zeile { display: flex; justify-content: space-between; gap: 12px; color: var(--djk-gray); }
.stb-kopf-zeile span:last-child { color: var(--djk-white); font-weight: 700; }

.stb-liste {
    margin: 10px 0;
    padding: 10px 0;
    border-top: 1px dashed var(--djk-border);
    border-bottom: 1px dashed var(--djk-border);
}
.stb-zeile { font-weight: 700; padding: 2px 0; }

.stb-knoepfe { display: flex; gap: 8px; }
.stb-knoepfe .btn { flex: 1 1 0; min-width: 0; padding: 12px 6px; font-size: 0.82rem; }

.stb-fuss {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 0.8rem;
    color: var(--djk-gray);
    /* Passt der Druckknopf nicht mehr neben die Meldung, rutscht er in die nächste Zeile —
       lieber eine Zeile mehr als „An Küche / gesendet" in zwei Stücken. */
    flex-wrap: wrap;
    row-gap: 8px;
}
.stb-fuss > span:first-child { white-space: nowrap; }
.stb-zurueck {
    background: none;
    border: 0;
    padding: 4px 2px;
    color: var(--djk-gray);
    font-size: 0.8rem;
    text-decoration: underline;
    cursor: pointer;
}
/* Rechts in der Fusszeile: „rückgängig" (nur beim geklärten Block) und der Druckknopf. */
.stb-fuss-knoepfe { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; margin-left: auto; }
/*
 * „Drucken" steht an JEDEM beantworteten Block — auch an einem, der längst gedruckt wurde.
 * Deshalb ein ruhiger Knopf mit Rahmen und nicht die volle Knopfreihe: er soll erreichbar sein,
 * ohne den Block zu einer Handlungsaufforderung zu machen.
 */
.stb-druck {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: 1px solid var(--djk-border);
    border-radius: 9px;
    padding: 7px 11px;
    color: var(--djk-white);
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
}
.stb-druck .icon { width: 18px; height: 18px; flex: 0 0 18px; }
.stb-druck:disabled { opacity: 0.5; }
.stb-block.ist-offen .stb-druck { border-color: #ffffff; color: #ffffff; }

/*
 * Der rote Block: GANZ rot mit weisser Schrift, wie der Wirt es gezeichnet hat („если не
 * отправлен весь блок будет красным а шрифты белыми"). Er soll aus der Liste herausbrüllen —
 * eine rote Kante allein übersieht man im Betrieb.
 */
.stb-block.ist-offen {
    background: #c0392b;
    border-color: #c0392b;
    color: #ffffff;
}
.stb-block.ist-offen .stb-kopf-zeile,
.stb-block.ist-offen .stb-kopf-zeile span:last-child,
.stb-block.ist-offen .stb-fuss { color: #ffffff; }
.stb-block.ist-offen .stb-liste {
    border-top-color: rgba(255, 255, 255, 0.45);
    border-bottom-color: rgba(255, 255, 255, 0.45);
}
/* Die Knöpfe auf rotem Grund: heller Rahmen statt der üblichen Farben, sonst verschwinden sie. */
.stb-block.ist-offen .btn-outline {
    border-color: #ffffff;
    color: #ffffff;
    background: transparent;
}
.stb-block.ist-offen .btn-primary {
    background: #ffffff;
    border-color: #ffffff;
    color: #c0392b;
}

/* ---------- Verwaltung → Drucker: gefundene und benannte Geräte ----------
   Eine Zeile ist ein Gerät: links, woran man es erkennt (Name oder Adresse), rechts die zwei
   Handgriffe. Auf dem Telefon rutscht alles untereinander — die Knöpfe bleiben so breit genug,
   um sie im Vorbeigehen zu treffen. */
.drucker-fund {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 12px 0;
    border-bottom: 1px solid var(--djk-border);
}
.drucker-fund:last-child { border-bottom: 0; }

/*
 * DER SUCHBALKEN (16.09.2026).
 *
 * Der Wirt: „когда ищет принтер, сделай какую-то полосу или что-то с цветами, чтобы было видно,
 * что она ищет." Der Agent holt den Auftrag alle vier Sekunden ab — bis dahin stand die Seite
 * still, und still sieht aus wie kaputt.
 *
 * Bewusst OHNE Zahl: wie weit der Agent im Netz ist, weiss der Server nicht. Ein Balken, der
 * hin und her laeuft, sagt „es geschieht etwas" — ein Prozentwert waere geraten.
 *
 * `prefers-reduced-motion`: wer Bewegung abbestellt hat, bekommt einen ruhenden Streifen in der
 * Hausfarbe statt gar nichts.
 *
 * FARBEN AUS DEM `--djk-`-SATZ, NICHT AUS `--brand-` (Pruefer 16.09.2026). Der `--brand-`-Satz
 * wird im dunklen Erscheinungsbild NICHT getauscht — der Balken waere dort hell auf dunkler
 * Karte stehengeblieben. `--djk-yellow` ist der Akzent des Hauses (hell #3b82f6, dunkel #60a5fa),
 * `--djk-black-soft` der ruhige Grund (hell #eef2f7, dunkel #1e2128).
 */
.dr-suchbalken {
    position: relative; overflow: hidden;
    height: 6px; margin: 0 0 14px; border-radius: 999px;
    background: var(--djk-black-soft, #eef2f7);
}
.dr-suchbalken[hidden] { display: none !important; }
.dr-suchbalken span {
    position: absolute; top: 0; bottom: 0; left: 0; width: 40%;
    border-radius: 999px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--djk-yellow, #3b82f6) 25%, transparent),
        var(--djk-yellow, #3b82f6),
        color-mix(in srgb, var(--djk-yellow, #3b82f6) 25%, transparent));
    animation: dr-suchlauf 1.2s ease-in-out infinite;
}
@keyframes dr-suchlauf {
    0%   { left: -40%; }
    100% { left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
    .dr-suchbalken span { animation: none; left: 0; width: 100%; opacity: .5; }
}
.drucker-fund-adresse { flex: 1 1 180px; min-width: 0; }
.drucker-fund-adresse small { display: block; opacity: 0.7; font-size: 0.8rem; }
.drucker-fund-name { flex: 1 1 160px; min-width: 0; }

/* ---------- Verlauf in der Kasse: Reiter als Zeichen (17.08.2026) ----------
   Vier Reiter mit Wörtern brachen auf dem Telefon in zwei Zeilen um — „Fertige Bestellungen"
   allein füllte eine. Als Zeichen passen sie nebeneinander und lesen sich im Vorbeigehen wie
   die Knopfreihe oben in der Kasse. Was jedes bedeutet, steht als `title` daran. */
.kasse-verlauf-reiter { flex-wrap: nowrap; }
.kasse-verlauf-reiter .admin-tab-btn {
    min-width: 0;
    padding: 9px 4px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.kasse-verlauf-reiter .admin-tab-btn .icon {
    width: 22px;
    height: 22px;
    /* Das Zeichen trägt hier die ganze Aussage — es darf nicht schrumpfen. */
    flex: 0 0 22px;
}

/* source/style_css/430_tile_settings.css - style.css part 64 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ---------- Kacheln: was die Verwaltung an ihnen einstellt (17.08.2026) ----------
   Der Abstand steht in der Regel für schmale Geräte weiter oben; hier der grosse Bildschirm.
   Die Kachel selbst hat ihre Farbe INLINE (aus Kategorie oder Produkt) — deshalb hebt der
   flache Anstrich sie mit `!important` auf; ein Inline-Wert lässt sich anders nicht überstimmen.
   `--kachel-voll` ist dieselbe Farbe ohne Verlauf, sie kommt aus demselben Erzeuger. */
#kasseProductsSection .product-grid { gap: var(--kasse-kachel-abstand, 6px); }
body.kasse-kachel-flach .product-tile[style*="--kachel-voll"] {
    background: var(--kachel-voll) !important;
}
/* Die farbige Kante links (Warengruppe) — abschaltbar, ohne die Kachel sonst anzufassen. */
body.kasse-kachel-ohne-kante #productGrid .product-tile {
    border-left-width: var(--kasse-kachel-rahmen, 1px) !important;
    border-left-color: transparent !important;
}

/* Wer macht was? - die Zuteil-Zeilen ueber dem eigenen Blatt des Chefs (19.08.2026).
   Sie stehen bewusst UEBER dem Papier: erst entscheiden, wer was macht, dann liest man den
   Zettel. Auf dem Papier selbst haben sie nichts zu suchen - das ist der Auftrag, nicht die
   Verwaltung. */
.kueche-zuteil-block {
    margin: 0 0 10px; padding: 8px 10px; border-radius: 8px;
    background: rgba(255, 255, 255, .04); border: 1px solid var(--djk-border);
}
.kueche-zuteil-titel { font-size: .78rem; color: var(--djk-gray); margin-bottom: 6px; }
.kueche-zuteil-zeile {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 3px 0; font-size: .9rem;
}
.kueche-zuteil-knoepfe { display: flex; gap: 6px; flex-wrap: wrap; }

/* Zuteilen und Drucken stehen in einer Zeile unter dem Blatt (19.08.2026). */
.kueche-blatt-fuss { display: flex; gap: 8px; align-items: center; justify-content: flex-end; }

/*
 * Ein Gang auf dem Brett (19.08.2026): gesendet ist FARBIG, fertig ist blass.
 * Der Wirt: „надо точно видно было на экране что заказ отправлен и сделан."
 */
/*
 * „VORSPEISE" steht in der MITTE des Zettels — immer (23.08.2026).
 *
 * Vorher war es eine Reihe aus drei Kästen, und der rechte war breiter als der linke
 * (150 gegen 92 Punkte, für den Knopf „✓ Anna unterwegs"). Damit saß die Überschrift
 * sichtbar links von der Mitte; der Wirt hat sie auf dem Bildschirmfoto eingekringelt.
 *
 * Ein Raster aus `minmax(0, 1fr) auto minmax(0, 1fr)` hält die beiden Seiten exakt gleich
 * breit, ganz gleich, was darin steht — die Mitte ist damit wirklich die Mitte.
 */
.kueche-gang-kopf {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 8px;
}
.kueche-gang-kopf .druck-zeile { text-align: center; }
.kueche-gang-gesendet { background: rgba(59, 130, 246, 0.14); border-left: 3px solid #3b82f6; padding-left: 6px; }
.kueche-gang-fertig { opacity: 0.45; }
.kueche-gang-btn, .kueche-gang-weg, .kueche-gang-schild {
    font-size: 0.72rem; padding: 2px 8px; border-radius: 999px; white-space: nowrap;
}
/* Volle Farbe, wie der Wirt sie im Betrieb eingestellt hat (24.08.2026): der blasse Rahmen war
   auf dem weissen Zettel kaum als Knopf zu erkennen. */
.kueche-gang-btn { border: 1px solid #2f7cc9; background: #2f7cc9; color: #ffffff; font-weight: 700; cursor: pointer; }
.kueche-gang-btn:hover { background: #2569ab; border-color: #2569ab; }
.kueche-gang-weg { border: 1px solid #94a3b8; background: #e5e7eb; color: #374151; font-weight: 700; cursor: pointer; }
.kueche-gang-schild { border: 1px solid transparent; color: #93c5fd; }
.kueche-gang-schild.kueche-gang-fertig { color: #86efac; opacity: 1; }
.kueche-gang-btn:disabled, .kueche-gang-weg:disabled { opacity: 0.5; cursor: default; }

/*
 * Ein Brett ohne Auswahl ist ein Brett mit EINER Spalte (19.08.2026).
 * Der Zettel des Arbeiters nimmt die ganze Breite; die Uebersicht daneben haette nichts
 * zu zeigen - er waehlt nichts aus, er arbeitet ab.
 */
.kueche-board.brett-eine-spalte .kueche-board-detail,
.kueche-board.brett-eine-spalte .kueche-board-resizer { display: none; }
.kueche-board.brett-eine-spalte .kueche-board-list { flex: 1 1 100%; grid-template-columns: 1fr; }
.kueche-board.brett-eine-spalte .kueche-ticket { max-width: none; }

/* Die Schilder am Gang etwas groesser - der Koch liest sie im Vorbeigehen. */
.kueche-gang-btn, .kueche-gang-weg, .kueche-gang-schild { font-size: 0.92rem; padding: 3px 12px; }
.kueche-gang-schild { font-weight: 700; }

/*
 * Zwei feste Plaetze neben jeder Gang-Ueberschrift (20.08.2026): links zuruecknehmen,
 * rechts fertig melden. Gleiche Breite, damit die Ueberschrift wirklich in der Mitte
 * steht und nichts springt, wenn ein Knopf seinen Text wechselt.
 */
/* Im Raster darf der Platz schrumpfen: eine Mindestbreite würde die Spalte aufblähen und
   die Mitte wieder verschieben (siehe oben). */
.kueche-gang-platz { min-width: 0; display: flex; }
.kueche-gang-links { justify-content: flex-start; }
.kueche-gang-rechts { justify-content: flex-end; }
.kueche-gang-platz .kueche-gang-btn, .kueche-gang-platz .kueche-gang-weg { width: 100%; text-align: center; }
.kueche-gang-platz button[disabled] { opacity: 0.35; cursor: default; }

/*
 * Schmale, ruhige Bildlaufleisten auf dem Brett (20.08.2026).
 *
 * Die Standardleiste des Systems ist auf einem dunklen Brett ein heller Balken, der mehr
 * auffaellt als der Zettel daneben. Firefox kennt `scrollbar-width`, die uebrigen den
 * `::-webkit-scrollbar` - beides steht hier, damit es ueberall gleich aussieht.
 */
.kueche-board-detail, .kueche-board-list, .kueche-ticket, .kueche-blatt-papier {
    scrollbar-width: thin;
    scrollbar-color: rgba(148, 163, 184, 0.45) transparent;
}
.kueche-board-detail::-webkit-scrollbar, .kueche-board-list::-webkit-scrollbar,
.kueche-ticket::-webkit-scrollbar, .kueche-blatt-papier::-webkit-scrollbar { width: 6px; height: 6px; }
.kueche-board-detail::-webkit-scrollbar-track, .kueche-board-list::-webkit-scrollbar-track,
.kueche-ticket::-webkit-scrollbar-track, .kueche-blatt-papier::-webkit-scrollbar-track { background: transparent; }
.kueche-board-detail::-webkit-scrollbar-thumb, .kueche-board-list::-webkit-scrollbar-thumb,
.kueche-ticket::-webkit-scrollbar-thumb, .kueche-blatt-papier::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.45); border-radius: 999px;
}
.kueche-board-detail::-webkit-scrollbar-thumb:hover, .kueche-board-list::-webkit-scrollbar-thumb:hover,
.kueche-ticket::-webkit-scrollbar-thumb:hover { background: rgba(148, 163, 184, 0.7); }

/* Rechts stehen Schild UND Knopf nebeneinander (20.08.2026). */
.kueche-gang-platz { gap: 6px; align-items: center; }
/* Auch hier keine eigene Mindestbreite mehr — sonst säße die Überschrift wieder daneben. */
.kueche-gang-platz .kueche-gang-schild { width: auto; }
.kueche-gang-platz .kueche-gang-btn, .kueche-gang-platz .kueche-gang-weg { width: auto; }


/* Sprachwahl im Personal-Kopf (20.08.2026): sechs kurze Kuerzel, das aktive hervorgehoben. */
.sprache-wahl-personal { display: flex; gap: 3px; align-items: center; margin-left: auto; margin-right: 10px; }
.sprache-wahl-knopf {
    font-size: 0.68rem; font-weight: 700; letter-spacing: 0.03em;
    padding: 2px 6px; border-radius: 4px; text-decoration: none;
    color: rgba(255, 255, 255, 0.55); border: 1px solid transparent;
}
.sprache-wahl-knopf:hover { color: #fff; border-color: rgba(255, 255, 255, 0.3); }
.sprache-wahl-knopf.ist-aktiv { color: #fff; border-color: var(--djk-yellow); }
@media (max-width: 640px) { .sprache-wahl-personal { display: none; } }

/* „Fertig" auf der Uebersichtskarte (20.08.2026): klein, gruen, neben „Drucken". */
.kueche-mini-fuss { display: flex; gap: 6px; justify-content: flex-end; align-items: center; }
.kueche-mini-fertig { font-size: 0.75rem; padding: 4px 12px; }
.kueche-mini-fertig:disabled { opacity: 0.45; cursor: default; }

/*
 * Menge der Beigabe mit den Daumen (20.08.2026): zwei grosse Knoepfe, dazwischen die Zahl.
 * Auf dem Telefon ist jedes Zahlenfeld eine Tastatur, die das halbe Fenster verdeckt.
 */
.bg-stepper { display: inline-flex; align-items: center; gap: 2px; }
.bg-stepper button {
    width: 44px; height: 44px; font-size: 1.4rem; line-height: 1;
    border: 1px solid var(--djk-border); background: var(--djk-black-card);
    color: var(--djk-white); border-radius: 8px; cursor: pointer;
}
.bg-stepper button:active { background: rgba(59, 130, 246, 0.25); }
.bg-menge { min-width: 46px; text-align: center; font-size: 1.2rem; font-weight: 800; font-variant-numeric: tabular-nums; }

/*
 * Die kleine Zeile beim Aufteilen (20.08.2026): sie zeigt den REST des Tisches.
 * „Auswahl" stand hier frueher - dieselbe Zahl wie oben war eine Auskunft zu wenig.
 */
.cart-total-rest { color: var(--djk-gray); position: relative; }
.cart-total-rest::after {
    content: "Rest";
    display: block;
    font-size: 0.6rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--djk-gray); line-height: 1; margin-top: 2px;
}

/*
 * Blaettern durch die Tischgruppen (20.08.2026): die Flaeche wird von kasse.js
 * verschoben. Hier steht nur, was das Ziehen ruhig haelt - keine Textmarkierung,
 * kein Kontextmenue, und die Bewegung faellt nicht ueber den Rand.
 */
/* `overflow-anchor: none`: beim Seitenwechsel darf der Browser die Rollposition NICHT
   festhalten - sonst schiebt er die Ueberschrift aus dem Bild. */
#tischOverlay { overflow-x: hidden; overflow-anchor: none; }
#tischOverlayGrid, #tischPlanView { will-change: transform; touch-action: pan-y; }
#tischOverlayGrid.zieht, #tischPlanView.zieht { user-select: none; }

/* Das zweite Blatt beim Blaettern (20.08.2026): es liegt neben dem ersten und wandert mit. */
/* KEIN `position` hier: das Fenster ist `fixed` (Vollbild) und damit selbst schon der
   Bezugspunkt fuer das zweite Blatt. `relative` machte aus dem Vollbild einen Kasten. */
.tisch-seite-nachbar { z-index: 1; }

/*
 * Der Name der Gruppe waehrend des Blaetterns (20.08.2026).
 *
 * Er steht ueber der Flaeche, wo die Augen ohnehin sind - die Knoepfe liegen unten am
 * Rand und werden beim Ziehen nicht gelesen. Halbdurchsichtig, damit er den Plan nicht
 * verdeckt, und ohne Maus-Ereignisse, damit er nichts abfaengt.
 */
.tisch-blaetter-name {
    position: absolute; top: 46%; left: 0; right: 0; z-index: 3;
    text-align: center; pointer-events: none;
    font-size: clamp(1.6rem, 7vw, 2.6rem); font-weight: 800; letter-spacing: 0.01em;
    color: #fff; text-shadow: 0 2px 18px rgba(0, 0, 0, 0.85);
    opacity: 0; transform: scale(0.94);
    transition: opacity 140ms ease-out, transform 140ms ease-out;
}
.tisch-blaetter-name.sichtbar { opacity: 0.92; transform: none; }
@media (prefers-reduced-motion: reduce) { .tisch-blaetter-name { transition: none; } }

/*
 * Der 3D-Weg beim Blaettern (20.08.2026, zum Vergleichen zuschaltbar).
 *
 * Die Tiefe steht am FENSTER: `perspective` wirkt nur auf die Kinder, und beide
 * Seiten muessen dieselbe Fluchtlinie haben - sonst drehen sie sich um verschiedene
 * Achsen und es sieht aus wie zwei Bilder statt einem Wuerfel.
 */
/* KEIN `perspective` am Fenster: es wuerde die fixe Knopfleiste an sich binden.
   Die Tiefe steckt in der Verwandlung der Seite selbst (siehe kasse.js, setzen()). */
body.blaettern-3d #tischOverlayGrid,
body.blaettern-3d #tischPlanView,
body.blaettern-3d .tisch-seite-nachbar { backface-visibility: hidden; transform-style: preserve-3d; }



/* ------------------------------------------------------------------------------------------
   UMSTELLEN WIE AM TELEFON (20.08.2026) — Kategorien, Produkte, Warengruppen

   Das Zappeln laeuft auf `rotate`, das Verschieben auf `translate`. Beides in `transform` geht
   nicht: eine Regel loescht die andere, und eine laufende Animation schlaegt ausserdem jeden
   Inline-Stil, den ein Skript setzt. Als eigene Eigenschaften laufen Drehung und Weg
   nebeneinander her, ohne voneinander zu wissen.
   ------------------------------------------------------------------------------------------ */
.kacheln-ordnen > .kategorie-tile,
.kacheln-ordnen > .product-tile,
.kacheln-ordnen > .warengruppe-chip {
    animation: kachel-wackeln 0.3s linear infinite;
    /* Ohne das rollt beim Ziehen die Liste mit. */
    touch-action: none;
    cursor: grab;
}
/* Zwei, drei Takte — im Gleichschritt zappelt keine Hand, das wirkt sofort wie eine Maschine. */
.kacheln-ordnen > *:nth-child(2n) { animation-duration: 0.36s; animation-delay: -0.13s; }
.kacheln-ordnen > *:nth-child(3n) { animation-duration: 0.33s; animation-delay: -0.22s; }
/* Dazu Richtung und Phase ueber weitere Teiler (26.09.2026): benachbarte Kacheln kippen
   nicht mehr im selben Moment in dieselbe Richtung. Nur CSS — kein Skript je Kachel, auch
   bei 170 Produkten. `rotate` ist eine eigene Eigenschaft und legt sich VOR `transform`:
   die Formen „dick" (perspective + rotateX) und „neigen" bleiben dabei erhalten. */
.kacheln-ordnen > *:nth-child(4n+1) { animation-direction: reverse; }
.kacheln-ordnen > *:nth-child(5n)   { animation-delay: -0.07s; }
.kacheln-ordnen > *:nth-child(7n+3) { animation-duration: 0.39s; animation-direction: alternate-reverse; }
@keyframes kachel-wackeln {
    /* Seit 22.08.2026 deutlich mehr: 0,8 Grad sah im Betrieb wie Stillstand aus. */
    0%, 100% { rotate: -2deg; }
    50%      { rotate: 2deg; }
}
/* Die gezogene Kachel: ruhig, etwas groesser, oben — und durchlaessig, damit
   document.elementFromPoint den Nachbarn unter dem Finger findet (siehe kasse.js). */
.kacheln-ordnen > .zieht {
    animation: none;
    rotate: 0deg;
    scale: 1.06;
    position: relative;
    z-index: 5;
    cursor: grabbing;
    pointer-events: none;
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.55);
}
@media (prefers-reduced-motion: reduce) {
    .kacheln-ordnen > * { animation: none; }
}

/* Die Leiste: sie sagt, was gerade gilt, und wie man wieder herauskommt. Sie kommt von oben
   herein und geht dorthin zurueck — eine Anzeige, die aufblitzt, liest niemand als Zustand. */
.kacheln-ordnen-leiste {
    position: fixed;
    top: calc(12px + env(safe-area-inset-top, 0px));
    left: 50%;
    z-index: 300;
    display: flex;
    align-items: center;
    gap: 13px;
    max-width: min(92vw, 430px);
    padding: 7px 7px 7px 17px;
    border-radius: 999px;
    color: #fff;
    background: linear-gradient(150deg, rgba(42, 45, 54, 0.96), rgba(18, 19, 24, 0.96));
    border: 1px solid rgba(255, 255, 255, 0.14);
    box-shadow: 0 18px 42px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.09);
    -webkit-backdrop-filter: blur(14px) saturate(1.25);
    backdrop-filter: blur(14px) saturate(1.25);
    opacity: 0;
    translate: -50% -14px;
    scale: 0.96;
    transition: opacity 220ms ease, translate 280ms cubic-bezier(.2, .9, .25, 1), scale 280ms cubic-bezier(.2, .9, .25, 1);
}
.kacheln-ordnen-leiste.da { opacity: 1; translate: -50% 0; scale: 1; }
/* Der Punkt atmet — er sagt „das hier laeuft gerade", ohne ein Wort dafuer zu brauchen. */
.kol-punkt {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--djk-yellow);
    animation: kol-puls 1.9s ease-out infinite;
}
@keyframes kol-puls {
    0%   { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.55); }
    70%  { box-shadow: 0 0 0 9px rgba(59, 130, 246, 0); }
    100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
.kol-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
    font-size: 0.84rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}
.kol-text small {
    font-size: 0.67rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    opacity: 0.55;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kol-fertig {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    margin-left: auto;
    padding: 9px 17px;
    border: 0;
    border-radius: 999px;
    background: var(--djk-yellow);
    color: #fff;
    font-weight: 700;
    font-size: 0.82rem;
    cursor: pointer;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
    transition: scale 120ms ease, filter 120ms ease;
}
.kol-fertig:hover { filter: brightness(1.08); }
.kol-fertig:active { scale: 0.95; }
.kol-fertig svg { width: 15px; height: 15px; }
@media (max-width: 420px) {
    .kacheln-ordnen-leiste { gap: 10px; padding-left: 14px; }
    .kol-text small { display: none; }
}

/* ------------------------------------------------------------------------------------------
   OHNE FOTO LIEGT DER NAME DORT, WO SONST DAS BILD WAR (20.08.2026)

   Das Kennzeichen sitzt in seiner Ecke ueber der Kachel. Mit Foto liegt es auf dem Bild — so
   ist es gemeint. Ohne Foto liegt es auf der SCHRIFT: „Alkoholfrei Spalter Bier" verschwand
   halb unter dem gruenen ALK-Fleck.

   Also bekommt der Name eine Gasse auf der Seite, an der ein Zeichen sitzt. Woran die Seite zu
   erkennen ist: die Ecke steht seit dem 20.08.2026 zusaetzlich als KLASSE am Zeichen
   (`kz-links` / `kz-rechts`, gesetzt von kennzeichen_markup() und kennzeichenHtml()).
   Vorher fragte die Regel nach `[style*="left:"]` — und verlor ihren Halt, sobald jemand
   den Stil des Elements anfasste.
   ------------------------------------------------------------------------------------------ */
body.kasse-no-fotos-produkte .product-tile:has(> .produkt-kennzeichen.kz-links) .product-tile-name,
/* Mit Kennung, weil der schmale Aufbau das Innenmass mit einer Kennung setzt (siehe
   `#kasseProductsSection .product-tile-name` weiter oben) - ohne sie verliert die Gasse. */
body.kasse-no-fotos-produkte #kasseProductsSection .product-tile:has(> .produkt-kennzeichen.kz-links) .product-tile-name {
    padding-left: var(--kz-gasse, 32px);
}
body.kasse-no-fotos-produkte .product-tile:has(> .produkt-kennzeichen.kz-rechts) .product-tile-name,
body.kasse-no-fotos-produkte #kasseProductsSection .product-tile:has(> .produkt-kennzeichen.kz-rechts) .product-tile-name {
    padding-right: var(--kz-gasse, 32px);
}


/* source/style_css/440_notifications_bell.css - style.css part 65 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ------------------------------------------------------------------------------------------
   DER WEGWEISER (20.08.2026) — die Zahl am Menuepunkt und die Liste in der Glocke

   Die Zahl steht dort, wo die Arbeit liegt. Rot ist sie, weil sie dasselbe meint wie der rote
   Kreis am App-Symbol; alles andere waere eine zweite Sprache fuer dieselbe Sache.
   ------------------------------------------------------------------------------------------ */
.menue-abzeichen {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    /* Direkt hinter dem Wort. Ganz rechts steht der Pfeil, der hat sein eigenes `auto`. */
    margin-left: 8px;
    padding: 0 6px;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 800;
    line-height: 1;
    flex-shrink: 0;
}
/*
 * Zwei Regeln mit Nachdruck, beide gegen dieselbe Falle: `[hidden]` des Browsers verliert
 * gegen jede Anzeige-Regel des Autors. Im aufgeklappten Menue des Handys steht
 * `.admin-sidebar-link span { display: inline !important }` — damit erschien die Zahl der
 * Reservierungen als leerer roter Punkt, obwohl null offen war.
 */
.admin-sidebar-nav.is-mobile-open .admin-sidebar-link > .menue-abzeichen:not([hidden]) { display: inline-flex !important; }
.admin-sidebar-nav.is-mobile-open .admin-sidebar-link > .menue-abzeichen[hidden] { display: none !important; }
/* In der Zeile liegt schon ein gap - ohne diese Zeile stuende die Zahl 20 px vom Wort weg. */
.admin-sidebar-link > .menue-abzeichen { margin-left: 0; }
.menue-abzeichen[hidden] { display: none !important; }
/* Im Untermenue und in der Reiterreihe steht sie direkt hinter dem Wort, nicht am Rand. */
.admin-sidebar-sublink .menue-abzeichen,
.admin-tab .menue-abzeichen { margin-left: 8px; min-width: 18px; height: 18px; font-size: 0.68rem; }

.admin-wegweiser { position: relative; display: flex; }
.admin-wegweiser > .admin-topbar-icon { background: none; border: 0; padding: 0; cursor: pointer; }
.notif-zahl {
    position: absolute;
    top: -6px;
    right: -8px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 0.68rem;
    font-weight: 800;
    line-height: 18px;
    text-align: center;
}
.notif-zahl[hidden] { display: none; }

/* Das Blatt haengt an der Glocke und nicht am Rand des Fensters: es gehoert sichtbar zu ihr. */
.aww-blatt {
    position: absolute;
    top: calc(100% + 12px);
    right: -6px;
    z-index: 120;
    width: min(84vw, 320px);
    padding: 8px;
    border-radius: 14px;
    /* ACHTUNG: `--djk-white` ist die SCHRIFTfarbe (#0f172a), die Flaeche ist
       `--djk-black-card`. Die Namen der Palette sind verdreht, siehe oben. */
    background: var(--djk-black-card, #fff);
    color: var(--djk-white, #0f172a);
    border: 1px solid var(--djk-border, #e2e8f0);
    box-shadow: 0 18px 44px rgba(15, 23, 42, 0.22);
}
.aww-blatt[hidden] { display: none; }
.aww-blatt::before {
    content: '';
    position: absolute;
    top: -7px;
    right: 16px;
    width: 12px;
    height: 12px;
    rotate: 45deg;
    background: var(--djk-black-card, #fff);
    border-left: 1px solid var(--djk-border, #e2e8f0);
    border-top: 1px solid var(--djk-border, #e2e8f0);
}
.aww-kopf {
    padding: 6px 10px 10px;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    opacity: 0.55;
}
.aww-leer { padding: 6px 10px 12px; font-size: 0.88rem; opacity: 0.7; }
.aww-leer[hidden], .aww-zeile[hidden] { display: none; }
.aww-zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border-radius: 10px;
    text-decoration: none;
    color: inherit;
}
.aww-zeile:hover { background: rgba(59, 130, 246, 0.09); text-decoration: none; }
.aww-symbol { display: flex; opacity: 0.6; }
.aww-symbol .icon { width: 18px; height: 18px; }
.aww-text { flex: 1; font-weight: 700; font-size: 0.9rem; }
.aww-zahl {
    min-width: 22px;
    height: 22px;
    padding: 0 7px;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 0.75rem;
    font-weight: 800;
    line-height: 22px;
    text-align: center;
}
.aww-pfeil { display: flex; opacity: 0.35; }
.aww-pfeil .icon { width: 16px; height: 16px; }

/* ------------------------------------------------------------------------------------------
   ZUGANG GEBEN — das zweite Blatt in der Kopfleiste (22.09.2026)

   Der Wirt: „чтобы всегда был под рукой и быстро можно было доступ давать рабочим." Die Liste
   der Menschen mit ihrem Code, ganz unten das Haus. Baut auf `.aww-blatt` auf und aendert nur,
   was anders ist: breiter, scrollbar, und eine Zeile traegt Wort UND Bild nebeneinander.

   ACHTUNG BEI DEN FARBEN: `--djk-white` ist die SCHRIFTfarbe, die Flaeche ist
   `--djk-black-card` — die Namen der Palette sind verdreht (siehe oben bei `.aww-blatt`).
   Der erste Anlauf stand hier mit `--sa-rand`/`--sa-grau`/`--sa-flaeche`, den Variablen des
   Super-Admin: in der Kasse gibt es sie NICHT, also fiel jede davon auf ihren hellen Ersatzwert
   zurueck — im dunklen Erscheinungsbild haette das Blatt helle Trennlinien mitten in dunkler
   Flaeche gehabt. Der Pruefer hat es gefunden, bevor es jemand gesehen hat.
   ------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------
   DER KNOPF MUSS INS AUGE FALLEN (22.09.2026)

   Der Wirt: „я нашёл, ок — просто сделай в зоне видимости." Er WAR da, als blosses Sinnbild
   zwischen der Glocke und dem Namen des Hauses — und genau so sah er aus wie Zierat. Etwas,
   das man dem Kellner in zehn Sekunden hinhalten will, darf nicht gesucht werden muessen.

   Deshalb bekommt er eine RAHMUNG und auf breiten Schirmen sein Wort dazu. Er bleibt in der
   Kopfleiste (dort gehoert er hin, er gilt auf jeder Seite), aber er ist jetzt ein Knopf und
   kein Zeichen.
   ------------------------------------------------------------------------------------------ */
/* ==========================================================================
   DER BALKEN "NEUE FASSUNG" (22.09.2026) — block_huelle_fassung.php

   Er liegt UEBER allem und nimmt die ganze Breite. Der Wirt hat tagelang einen
   Knopf gesucht, den es nicht gab; einer, den man suchen muss, waere derselbe
   Fehler noch einmal. Zu sehen ist er nur, wenn wirklich etwas bereitliegt —
   sonst traegt das Feld `hidden`.
   ========================================================================== */
/* Der Name, unter dem das Programm auf dem Geraet steht — leiser als die Beschriftung,
   aber lesbar: er ist die Antwort auf "welches von beiden". */
.pl-welches { font-weight: 400; opacity: 0.85; }

.hf-balken {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 400;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* PLUS, nicht MAX: oben ist die sichere Zone nie 0 (siehe .kasse-search-bar). */
    padding: calc(10px + env(safe-area-inset-top, 0px)) 14px 10px;
    background: var(--djk-yellow, #3b82f6);
    color: #fff;
    font-size: 0.95rem;
    font-weight: 700;
    box-shadow: 0 6px 18px -6px rgb(15 23 42 / 45%);
}
.hf-balken[hidden] { display: none; }
.hf-wort { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hf-knopf {
    flex: 0 0 auto;
    padding: 9px 16px;
    border: 0;
    border-radius: 9px;
    background: #fff;
    color: var(--djk-yellow, #3b82f6);
    font-size: 0.95rem;
    font-weight: 800;
    cursor: pointer;
}
.hf-knopf:disabled { opacity: 0.7; cursor: default; }

.zcode-knopf {
    gap: 7px;
    width: auto !important;
    min-height: 40px;
    padding: 0 12px !important;
    border: 1px solid var(--djk-border, rgba(255, 255, 255, .28)) !important;
    border-radius: 999px !important;
    font-size: 0.82rem;
    font-weight: 700;
    white-space: nowrap;
}
/* Das Wort steht nur, wo Platz ist. Am Telefon zaehlt jeder Punkt in der Leiste — dort bleibt
   es beim gerahmten Zeichen, und das hebt sich schon deutlich genug ab. */
.zcode-knopf-wort { display: none; }
@media (min-width: 900px) { .zcode-knopf-wort { display: inline; } }

.zcode-blatt { width: min(92vw, 330px); max-height: 70vh; overflow-y: auto; }

/* ------------------------------------------------------------------------------------------
   AM TELEFON HAENGT DAS BLATT AM BILDSCHIRM, NICHT AM KNOPF (22.09.2026)

   Der Wirt: „опять не в зоне видимости." Und er hatte recht: `.aww-blatt` haengt mit
   `right: 0` an seinem Knopf. Der steht in der Mitte der Leiste, das Blatt ist 330 Punkte
   breit — auf einem Telefon von 390 Punkten lief seine linke Haelfte damit ueber den Rand
   hinaus. Bei der Glocke faellt das nicht auf: ihr Blatt ist schmaler und sie steht weiter
   rechts.

   Deshalb wird es hier `fixed` und spannt sich zwischen die beiden Raender des Bildschirms.
   `top` muss dabei ausgerechnet werden: unter `fixed` bezoege sich das geerbte
   `top: calc(100% + 12px)` auf die HOEHE DES FENSTERS und schoebe das Blatt nach unten aus
   dem Bild. 58 Punkte ist die Leiste am Telefon (app_leiste.css), dazu die sichere Zone
   oben — das iPhone laesst die Seite unter seine Uhr laufen.
   ------------------------------------------------------------------------------------------ */
/*
 * MIT VOLLEM GEWICHT GESCHRIEBEN (nachgemessen 22.09.2026). Der erste Anlauf stand als
 * blosses `.zcode-blatt` hier und verlor: `admin_anstrich.css` setzt
 * `body.admin-body .app-kopf .aww-blatt { top: calc(100% + 8px) }` — Gewicht 0-3-0 gegen
 * 0-1-0, und eine Medienabfrage waegt nichts. `position: fixed` kam durch, `top` nicht,
 * und dann bezog sich `100%` auf die HOEHE DES FENSTERS: das Blatt stand bei 852 Punkten
 * auf einem Bildschirm von 844 — vollstaendig unterhalb des Bildes. Genau die Falle, die
 * im Absatz darueber beschrieben ist; beschrieben hatte ich sie, verhindert nicht.
 */
@media (max-width: 719px) {
    body.admin-body .app-kopf .zcode-halter .zcode-blatt,
    .zcode-blatt {
        position: fixed;
        top: calc(env(safe-area-inset-top, 0px) + 58px + 8px);
        left: 8px;
        right: 8px;
        width: auto;
        max-height: calc(100dvh - env(safe-area-inset-top, 0px) - 58px - 90px);
    }
    /* Das Zipfelchen zeigte auf den Knopf — es passt nicht mehr, wenn das Blatt am Rand haengt. */
    .zcode-blatt::before { display: none; }
}
.zcode-zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-top: 1px solid var(--djk-border, #e2e8f0);
}
.zcode-zeile:first-child { border-top: 0; }
.zcode-wort { flex: 1 1 auto; min-width: 0; }
.zcode-wort strong { display: block; font-size: 0.86rem; line-height: 1.3; }
.zcode-wort small { display: block; font-size: 0.73rem; opacity: 0.6; word-break: break-all; }
/* Der gesperrte Mensch bleibt stehen — sonst sucht man ihn und glaubt, er sei geloescht. */
.zcode-zeile.zcode-zu .zcode-wort strong { text-decoration: line-through; opacity: 0.55; }
.zcode-bild {
    flex: 0 0 auto;
    width: 54px;
    height: 54px;
    padding: 3px;
    /* Ein QR-Code braucht WEISS unter sich, in jedem Erscheinungsbild — eine Kamera liest ihn
       sonst nicht. Das ist keine Farbe der Oberflaeche, sondern eine Eigenschaft des Codes. */
    background: #fff;
    border: 1px solid var(--djk-border, #cbd5e1);
    border-radius: 8px;
    cursor: zoom-in;
}
.zcode-bild svg { display: block; width: 100%; height: 100%; }
.zcode-ohne { flex: 0 0 auto; font-size: 0.73rem; opacity: 0.6; text-align: right; }
/* Das Haus steht UNTEN und ist abgesetzt: es gehoert keinem Menschen. */
.zcode-haus { border-top: 2px solid var(--djk-border, #e2e8f0); }
.zcode-mehr {
    display: block;
    padding: 9px 10px;
    border-top: 1px solid var(--djk-border, #e2e8f0);
    font-size: 0.8rem;
    text-decoration: none;
    color: inherit;
    opacity: 0.75;
}
.zcode-mehr:hover { opacity: 1; text-decoration: none; }
/* Gross: ein Bild, das ein Telefon aus einem halben Meter liest. */
.zcode-gross {
    position: fixed;
    inset: 0;
    z-index: 4000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 24px;
    background: rgba(15, 23, 42, 0.93);
}
.zcode-gross svg {
    width: min(78vw, 340px);
    height: auto;
    background: #fff;
    padding: 14px;
    border-radius: 14px;
}
/* Fest hell: diese Flaeche ist in JEDEM Erscheinungsbild dunkel. */
.zcode-gross-wort { color: #fff; font-size: 1rem; font-weight: 700; text-align: center; }
.zcode-gross-link { color: #cbd5e1; font-size: 0.75rem; word-break: break-all; text-align: center; max-width: 92vw; }

/* Der Hinweis ueber der Liste der Online-Bestellungen: hier sehen, dort abschliessen. */
.ov-offen-hinweis {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 0 0 16px;
    padding: 12px 16px;
    border-radius: 12px;
    background: rgba(239, 68, 68, 0.07);
    border: 1px solid rgba(239, 68, 68, 0.25);
    font-weight: 600;
}
.ov-offen-hinweis .menue-abzeichen { margin-left: 0; }
.ov-offen-hinweis a { margin-left: auto; }


/* source/style_css/445_notifications_bell_continued.css - style.css: notifications bell continued, part 66 of 78 (built by werkzeuge/parts_build.php) */
/* ------------------------------------------------------------------------------------------
   VERANSTALTUNGEN (20.08.2026) — die Karte und die Tische eines Abends

   Viele Zeilen auf einmal: vierzig Getraenke ankreuzen, zwanzig Tische verteilen. Deshalb
   schmale Zeilen, klare Trennung zwischen "gehoert dazu" und "gehoert nicht dazu" — und der
   Preis dieses Abends direkt neben dem normalen, damit man beim Tippen vergleicht.
   ------------------------------------------------------------------------------------------ */
.veranst-raster {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
    margin-bottom: 6px;
}
.veranst-gruppe { margin-bottom: 18px; }
.veranst-gruppe-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 0 8px;
    border-bottom: 1px solid var(--djk-border);
    margin-bottom: 8px;
}
.veranst-produkte,
.veranst-gruppen-wahl {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 6px;
}
.veranst-zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--djk-border);
    border-radius: 8px;
    cursor: pointer;
    background: var(--djk-black-card, #fff);
}
.veranst-zeile.ist-an { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.06); }
/* KEINE Breite setzen: die Kaestchen tragen im ganzen Haus `appearance: none` und holen
   ihre 20 px aus der Hausregel. `width: auto` machte einen Strich daraus. */
.veranst-zeile input[type="checkbox"] { margin: 0; }
.veranst-name { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Der normale Preis steht blass daneben: er ist die Auskunft, nicht die Eingabe. */
.veranst-normalpreis { font-size: 0.8rem; opacity: 0.5; white-space: nowrap; }
.veranst-preis {
    width: 96px;
    flex-shrink: 0;
    padding: 5px 8px !important;
    text-align: right;
    font-weight: 700;
}
.veranst-tische {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 8px;
    margin-top: 14px;
}
.veranst-tisch {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: 1px solid var(--djk-border);
    border-radius: 8px;
}
.veranst-tisch-nr { font-weight: 800; min-width: 42px; }
.veranst-tisch-name { flex: 1; min-width: 0; font-size: 0.85rem; opacity: 0.6; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.veranst-tisch select { width: auto; min-width: 120px; padding: 5px 8px !important; }
.admin-table tr.ist-offen { background: rgba(59, 130, 246, 0.07); }


/* source/style_css/450_event_at_register.css - style.css part 67 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ------------------------------------------------------------------------------------------
   VERANSTALTUNG AN DER KASSE (20.08.2026)

   Der Knopf im kleinen Menue traegt den Namen der laufenden Veranstaltung — man soll nie raten
   muessen, in welcher Kasse man gerade tippt. Und der fremde Tisch steht blass: das ist eine
   Auskunft, keine Sperre (bedienen darf jeder jeden).
   ------------------------------------------------------------------------------------------ */
.kasse-menue-knopf.ist-veranstaltung {
    border-color: var(--djk-yellow);
    color: var(--djk-yellow);
    font-weight: 800;
}
.veranst-box { max-width: 460px; }
.veranst-code-feld {
    width: 100%;
    padding: 14px 16px !important;
    font-size: 1.6rem !important;
    font-weight: 800;
    letter-spacing: 0.32em;
    text-align: center;
}
.veranst-wahl {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    margin-bottom: 8px;
    padding: 12px 14px;
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    background: var(--djk-black-card, #fff);
    color: inherit;
    text-align: left;
    cursor: pointer;
}
.veranst-wahl:hover { border-color: var(--djk-yellow); }
.veranst-wahl.ist-an { border-color: var(--djk-yellow); background: rgba(59, 130, 246, 0.09); }
.veranst-wahl-name { font-weight: 700; font-size: 0.98rem; }
.veranst-wahl-info { font-size: 0.8rem; opacity: 0.6; }
.veranst-zurueck { margin-top: 6px; }

/*
 * Der Tisch eines Kollegen: gedaempft, aber anfassbar - und mit lesbarem Namen.
 *
 * NICHT mit `opacity`: die haette den Namen gleich mit halbiert, und genau der soll gelesen
 * werden („имена других работников на столах все работники видят"). Ein Schleier als
 * inset-Schatten legt sich ueber die FLAECHE; die Schrift steht darueber.
 */
.tisch-tile.tisch-fremd {
    box-shadow: inset 0 0 0 999px rgba(15, 23, 42, 0.55);
    border-color: rgba(255, 255, 255, 0.12);
}
.tisch-tile.tisch-fremd:hover,
.tisch-tile.tisch-fremd:active { box-shadow: inset 0 0 0 999px rgba(15, 23, 42, 0.25); }
.tisch-tile.tisch-fremd .product-tile-photo { opacity: 0.4; }
/* Der Name des Kollegen bleibt hell - er ist die Auskunft, um die es hier geht. */
.tisch-tile.tisch-fremd .tisch-tile-kellner { opacity: 0.95; }

/*
 * MEIN Tisch: ein Rahmen in der Hausfarbe und ein Hauch Licht. Wer zwei von zwanzig Tischen
 * hat, sucht seine zwei - nicht die achtzehn anderen.
 */
.tisch-tile.tisch-mein {
    box-shadow: inset 0 0 0 2px var(--djk-yellow), 0 0 0 1px rgba(59, 130, 246, 0.35);
    filter: brightness(1.08) saturate(1.1);
}
.tisch-tile.tisch-mein .tisch-tile-kellner { color: var(--djk-yellow); opacity: 1; }
.tisch-tile-kellner {
    display: block;
    margin-top: 2px;
    font-size: 0.72rem;
    font-weight: 700;
    opacity: 0.75;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ------------------------------------------------------------------------------------------
   ANLEGEN, WAS ES NUR AN DIESEM ABEND GIBT

   Drei Zeilen, EINE Spaltenordnung: Beschriftung, zwei Felder, Auswahl, Knopf. Vorher hatte
   jede Zeile ihr eigenes Raster, weil die Beschriftungen verschieden breit sind ("Товар" gegen
   "Категория столов") — untereinander sah das aus wie drei Formulare aus drei Programmen.
   ------------------------------------------------------------------------------------------ */
.veranst-anlegen { display: grid; gap: 10px; margin: 12px 0 4px; }
.veranst-anlegen-form {
    display: grid;
    grid-template-columns: 150px minmax(120px, 1fr) minmax(120px, 1fr) minmax(150px, 210px) 46px;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--djk-border);
    border-radius: 10px;
}
.veranst-anlegen-form strong { font-size: 0.9rem; }
.veranst-anlegen-form input[type="text"],
.veranst-anlegen-form input[type="tel"],
.veranst-anlegen-form select { width: 100%; padding: 8px 10px !important; }
/* Mit Zeichen davor (die Seite setzt es von selbst): Platz fuer das Zeichen, sonst liegt es auf dem Text (25.09.2026). */
.veranst-anlegen-form .ui-feld > input.ui-feld-mit, .veranst-anlegen-form .ui-feld > select.ui-feld-mit { padding-left: 40px !important; }
/* Wo nur ein Feld steht, nimmt es den Platz der beiden anderen mit. */
.veranst-anlegen-form .vaf-weit { grid-column: 2 / 5; }
.veranst-anlegen-form .btn { grid-column: 5; padding: 9px 0; width: 100%; }
@media (max-width: 760px) {
    /*
     * Auf dem Telefon untereinander: fuenf Spalten auf 360 px sind fuenf Streifen.
     * Der Knopf bleibt aber ein Knopf und wird kein Balken quer ueber die Karte - er
     * steht rechts unter den Feldern, dort, wo der Daumen ohnehin ist.
     */
    .veranst-anlegen-form { grid-template-columns: 1fr; gap: 8px; }
    .veranst-anlegen-form strong,
    .veranst-anlegen-form input[type="text"],
    .veranst-anlegen-form input[type="tel"],
    .veranst-anlegen-form select,
    .veranst-anlegen-form .vaf-weit { grid-column: 1; }
    .veranst-anlegen-form .btn { grid-column: 1; justify-self: end; width: auto; padding: 9px 26px; }
    /* (Das Seitwaertsschieben ist weg: die Tabelle wird auf dem Telefon zu Karten,
       siehe das Gesetz fuer .admin-table-wrap weiter unten.) */
    .veranst-tisch select { min-width: 0; }
}
.veranst-eigenes-kopf {
    margin-top: 14px;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    opacity: 0.5;
}
.veranst-eigenes-liste { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.veranst-marke {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    border-radius: 999px;
    background: rgba(59, 130, 246, 0.1);
    border: 1px solid rgba(59, 130, 246, 0.3);
    font-size: 0.82rem;
    font-weight: 600;
}
.veranst-marke-tisch { background: rgba(100, 116, 139, 0.12); border-color: rgba(100, 116, 139, 0.3); }
.veranst-marke .icon { width: 14px; height: 14px; }

/* Das Kreuz sitzt IN der Marke: ein eigener Knopf daneben waere ein zweites Element fuer
   dasselbe Stueck. Das Formular darin ist nur ein Traeger und darf nichts umbrechen. */
.veranst-marke-weg { display: inline; margin: 0; }
.veranst-marke-weg button {
    margin-left: 6px;
    padding: 0 2px;
    border: 0;
    background: none;
    color: inherit;
    opacity: 0.45;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
}
.veranst-marke-weg button:hover { opacity: 1; color: var(--djk-danger); }

/* Kopf der Liste: Ueberschrift links, „Neue Veranstaltung" rechts. */
.veranst-listenkopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.veranst-listenkopf h3 { margin: 0; }
/* Die Spalten der Liste standen aneinandergeklebt ("ТОВАРЫ КАТЕГОРИИ СТОЛОВ" las sich als ein
   Wort). Luft dazwischen, Zahlen mittig, und der Papierkorb rot. */
.admin-karte .admin-table th,
.admin-karte .admin-table td { padding-right: 18px; }
.admin-karte .admin-table th:last-child,
.admin-karte .admin-table td:last-child { padding-right: 0; }
.veranst-weg-knopf { color: var(--djk-danger); border-color: rgba(239, 68, 68, 0.4); }
.veranst-weg-knopf:hover { background: rgba(239, 68, 68, 0.1); border-color: var(--djk-danger); }

/* Die Aushilfe traegt ihre Nummer gleich mit — man ruft sie an, nicht ihre Rolle. */
.veranst-marke-person { background: rgba(139, 92, 246, 0.1); border-color: rgba(139, 92, 246, 0.35); }
.veranst-telefon { opacity: 0.6; font-weight: 500; font-variant-numeric: tabular-nums; }

/* Sinnbild in der Ueberschrift und in der Anlege-Zeile: dieselbe Hoehe wie die Schrift. */
.admin-karte h3 .icon { width: 18px; height: 18px; margin-right: 6px; vertical-align: -3px; }
.veranst-anlegen-form strong .icon { width: 15px; height: 15px; margin-right: 5px; vertical-align: -2px; }
.admin-table td strong .icon { width: 14px; height: 14px; margin-right: 5px; vertical-align: -2px; }

/* ------------------------------------------------------------------------------------------
   DER NAME DER VERANSTALTUNG IN DER SUCHLEISTE (20.08.2026)

   Die Kasse sieht in einer Veranstaltung fast normal aus - nur mit weniger Kacheln. Deshalb
   steht der Name dort, wo die Augen beim Aufschlagen zuerst sind. Ein Tipp darauf fuehrt zum
   Wechseln.

   Er steht IN der Leiste und nicht davor: die Leiste ist auf dem Handy ein Flex-Kind der Spalte
   und `position: static` - alles, was im Fluss davor steht, landet ganz unten auf der Seite
   (genau so gemessen). Volle Breite schiebt die Knopfreihe auf die naechste Zeile, wie es der
   Hinweis "Kein Internet" schon macht. Umbrochen wird nur, WENN das Band da ist.
   ------------------------------------------------------------------------------------------ */
.kasse-search-bar:has(.kasse-veranstaltung-band) { flex-wrap: wrap; }
.kasse-veranstaltung-band {
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 2px;
    padding: 7px 14px;
    border: 0;
    border-radius: 10px;
    background: linear-gradient(100deg, rgba(236, 72, 153, 0.28), rgba(139, 92, 246, 0.22));
    box-shadow: inset 0 0 0 1px rgba(236, 72, 153, 0.45);
    color: #fff;
    font-size: 0.86rem;
    font-weight: 800;
    cursor: pointer;
    text-align: left;
}
.kasse-veranstaltung-band .icon { width: 16px; height: 16px; flex-shrink: 0; }
.kvb-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Der Zettel einer Veranstaltung auf dem Brett: dieselbe Farbe wie das Band (25.09.2026). */
.kueche-ticket-mini-veranst { margin: 2px 0 4px; padding: 2px 8px; border-radius: 6px; display: inline-block; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .78rem; font-weight: 800; color: #fff;
    background: linear-gradient(100deg, rgba(236, 72, 153, 0.85), rgba(139, 92, 246, 0.8)); }
.veranst-frage { margin: 0 0 10px; font-weight: 700; color: var(--djk-gray, #94a3b8); }
/* Als wer arbeite ich heute - blass daneben, weil es die zweite Auskunft ist. */
.kvb-als {
    margin-left: auto;
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.18);
    font-size: 0.76rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Die Reiter der Veranstaltung sind Verweise (jeder laedt nur seinen Teil) und muessen sich
   trotzdem wie die Reiter im uebrigen Haus verhalten. */
.veranst-reiter { margin-bottom: 14px; }
.veranst-reiter .admin-tab-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    text-decoration: none;
}
.veranst-reiter .admin-tab-btn:hover { text-decoration: none; }
.veranst-reiter .admin-tab-btn .icon { width: 16px; height: 16px; }
/* Der aktive Reiter traegt die Hausfarbe - dort ist die Schrift hell. */
.veranst-reiter .admin-tab-btn.active,
.veranst-reiter .admin-tab-btn.active .icon { color: #fff; }
@media (max-width: 560px) {
    /* Enger, aber mit Wort: vier kurze Woerter passen auf ein Telefon. */
    .veranst-reiter { gap: 4px; padding: 4px; }
    .veranst-reiter .admin-tab-btn { min-width: 0; padding: 10px 4px; gap: 5px; font-size: 0.76rem; }
    .veranst-reiter .admin-tab-btn .icon { width: 15px; height: 15px; }
}
@media (max-width: 400px) {
    /* Hier wird es wirklich eng - dann sprechen die Sinnbilder allein. */
    .veranst-reiter .admin-tab-btn span { display: none; }
    .veranst-reiter .admin-tab-btn { padding: 12px 6px; }
    .veranst-reiter .admin-tab-btn .icon { width: 18px; height: 18px; }
}

/* Der Abend in Zahlen: die Summe gross, alles andere daneben - man liest zuerst die eine Zahl,
   nach der gefragt wurde, und danach ihre Aufteilung. */
.veranst-zahlen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 10px;
    margin: 12px 0 4px;
}
.veranst-zahl {
    padding: 12px 14px;
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    background: var(--djk-black-card, #fff);
}
.veranst-zahl-gross {
    background: rgba(59, 130, 246, 0.09);
    border-color: rgba(59, 130, 246, 0.35);
    grid-column: span 2;
}
.vz-wert { font-size: 1.35rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.veranst-zahl-gross .vz-wert { font-size: 1.8rem; }
.vz-wort { margin-top: 2px; font-size: 0.78rem; font-weight: 600; opacity: 0.6; }
.admin-table td, .admin-table th { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------------------------------
   ABSTAENDE IN DEN KARTEN DER VERANSTALTUNG (20.08.2026)

   Die Knopfzeile einer Karte stand auf dem Telefon auseinandergezogen: die Zelle ohne
   Beschriftung wird zu einer Flex-Zeile mit `space-between`, und darin gingen Stift und
   Papierkorb an die beiden Raender. Sie gehoeren zusammen an eine Seite - dazwischen ist kein
   Wert, sondern Luft.
   ------------------------------------------------------------------------------------------ */
@media (max-width: 700px) {
    .admin-karte .admin-table-wrap td:not([data-label]),
    .admin-karte .admin-table-wrap td[data-label=""] {
        justify-content: flex-end;
        gap: 10px;
        padding-top: 10px;
        padding-bottom: 10px;
    }
    /* Beide Knoepfe gleich gross und mit Platz fuer den Daumen. */
    .admin-karte .admin-table-wrap td .btn-sm { padding: 9px 16px; }
    /* Die Karte selbst etwas luftiger - sie traegt vier Zeilen und zwei Knoepfe. */
    .admin-karte .admin-table-wrap tr { padding: 6px 0 8px; margin-bottom: 10px; }
    .admin-karte .admin-table-wrap td:first-child { padding-top: 12px; padding-bottom: 10px; }
}

/* source/style_css/460_daily_revenue_house_settings.css - style.css part 68 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ===================================================================================
 * TAGESUMSATZ AN DER KASSE (20.08.2026)
 *
 * Gebaut fuer ein Telefon in einer Hand: grosse Zahl oben, alles andere darunter, keine
 * Tabelle, die man seitlich schieben muss. Die eigene Zahl bekommt den Rahmen in der
 * Hausfarbe — sie ist die, nach der zuerst gesucht wird.
 * =================================================================================== */

.umsatz-seite {
    padding: 12px 12px 90px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    max-width: 640px;
    margin: 0 auto;
}

.umsatz-block {
    background: var(--djk-black-card, #1e293b);
    border: 1px solid var(--djk-border, #334155);
    border-radius: 14px;
    padding: 14px 16px;
}
/*
 * FARBE ALS AUSSAGE (23.08.2026).
 *
 * Jeder Block sagt ueber seinen Streifen, WOVON er handelt: mein Geld blau, das Bargeld in
 * der Lade gruen, was noch aussteht gelb, meine Tische grau, das Haus violett, die Ware
 * tuerkis. Wer die Seite kennt, findet den Block, ohne die Ueberschrift zu lesen.
 *
 * Als rgba UEBER den Untergrund gelegt, damit hell und dunkel dieselbe Regel teilen.
 */
.umsatz-block { border-left-width: 4px; }
.umsatz-block-sturz  { border-left-color: #16a34a; }
.umsatz-block-sturz  .umsatz-block-titel { color: #16a34a; }
.umsatz-block-tische { border-left-color: #64748b; }
.umsatz-block-haus   { border-left-color: #8b5cf6; }
.umsatz-block-haus   .umsatz-block-titel { color: #a78bfa; }
.umsatz-block-haus   .umsatz-gross { color: #a78bfa; }
.umsatz-block-ware   { border-left-color: #14b8a6; }
.umsatz-block-ware   .umsatz-block-titel { color: #2dd4bf; }

/* Papier und Datei: unter der Datumszeile, nicht mehr oben im Kopf. */
.umsatz-aktionen { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }

/* Der eigene Umsatz hebt sich ab: danach wird zuerst gesucht. */
.umsatz-block-ich { border-color: var(--djk-yellow, #f0b429); }
.umsatz-block-ich .umsatz-gross { color: var(--djk-yellow, #f0b429); }

.umsatz-block-titel {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    opacity: 0.7;
    margin-bottom: 8px;
}
.umsatz-gross {
    font-size: 2.1rem;
    font-weight: 800;
    line-height: 1.1;
    white-space: nowrap;
}
.umsatz-klein { font-size: 0.86rem; opacity: 0.7; margin-top: 2px; }

.umsatz-liste {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
}
.umsatz-liste li {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    padding: 7px 0;
    border-bottom: 1px solid var(--djk-border, #334155);
}
.umsatz-liste li:last-child { border-bottom: 0; }
.umsatz-ich { color: var(--djk-yellow, #f0b429); font-weight: 600; }

.umsatz-liste-ware li { display: grid; grid-template-columns: 2.8rem 1fr auto; }
.umsatz-menge { font-weight: 700; opacity: 0.75; }
.umsatz-name { overflow: hidden; text-overflow: ellipsis; }

.umsatz-leer { text-align: center; padding: 24px 0; }

/* DIE SPRACHE IM MENUE DER PERSONAL-APP (21.08.2026)
   ---------------------------------------------------
   Auf dem Telefon ist die Reihe in der Kopfleiste ausgeblendet (siehe .sprache-wahl-personal).
   Hier ist der zweite Weg: unten im Menue hinter dem Strich, mit ausgeschriebenen Namen —
   im Menue ist Platz, und „Ελληνικά" liest sich besser als „EL". */
.sprache-wahl-menue {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 10px 0 2px;
    margin-top: 6px;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
}
.sprache-menue-knopf {
    font-size: 0.82rem;
    padding: 6px 12px;
    border-radius: 999px;
    text-decoration: none;
    color: rgba(255, 255, 255, 0.7);
    border: 1px solid rgba(255, 255, 255, 0.25);
    line-height: 1.2;
}
.sprache-menue-knopf:hover { color: #fff; border-color: rgba(255, 255, 255, 0.5); }
.sprache-menue-knopf.ist-aktiv {
    color: #fff;
    background: var(--djk-yellow);
    border-color: var(--djk-yellow);
    font-weight: 600;
}

/* Die Sprachwahl im Profil der Kasse (21.08.2026) — auf dem Verkaufsschirm der einzige
   Ort dafuer, weil dort die Kopfleiste ausgeblendet ist. */
.kasse-profil-sprachen { display: flex; flex-wrap: wrap; gap: 6px; }
.kasse-sprache-knopf {
    font-size: 0.85rem;
    padding: 7px 13px;
    border-radius: 999px;
    text-decoration: none;
    color: rgba(255, 255, 255, 0.75);
    border: 1px solid rgba(255, 255, 255, 0.25);
    line-height: 1.2;
}
.kasse-sprache-knopf.ist-aktiv {
    color: #fff;
    background: var(--djk-yellow);
    border-color: var(--djk-yellow);
    font-weight: 600;
}

/* DIE ARBEITSLISTE DES ABENDS (21.08.2026)
   Wer noch keinen Tisch hat, steht ueber dem Belegungsband — mit Uhrzeit, Namen und
   Personenzahl. Angetippt oeffnet sich die Karte, in der der Tisch gewaehlt wird. */
.reserv-ohne-tisch {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px;
    padding: 8px 10px;
    border: 1px solid var(--djk-yellow);
    border-radius: 10px;
    background: rgba(240, 180, 41, 0.08);
}
.reserv-ohne-tisch-titel {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    opacity: 0.75;
    margin-right: 4px;
}
.reserv-ohne-tisch-chip {
    font-size: 0.82rem;
    padding: 5px 10px;
    border-radius: 999px;
    border: 1px solid var(--djk-border);
    background: var(--djk-black-soft);
    color: inherit;
    cursor: pointer;
    line-height: 1.2;
}
.reserv-ohne-tisch-chip:hover { border-color: var(--djk-yellow); }

/* Der Stand der Sicherung: eine Zeile, die man im Vorbeigehen liest. Die Farbe sagt das
   Wichtigste - gruen heisst "heute nacht gelaufen", rot heisst "sieh nach". */
/* --- Einstellungen von Haus zu Haus (05.09.2026) ----------------------------------------
 * Drei Ebenen, und sie muessen sich auf einen Blick unterscheiden: der BEREICH (aufklappbar,
 * ein Haken schaltet alles darin), die ZEILE (eine Einstellung) und beim Einspielen der
 * VERGLEICH (alt -> neu). Farben kommen aus den vorhandenen Variablen.
 */
.uebertrag-bereiche { display: flex; flex-direction: column; gap: 8px; }
.uebertrag-bereich {
    border: 1px solid var(--border-color, rgba(148,163,184,.25)); border-radius: 10px;
    background: var(--card-bg, rgba(255,255,255,.03)); overflow: hidden;
}
.uebertrag-bereich > summary {
    list-style: none; cursor: pointer; padding: 10px 14px;
}
.uebertrag-bereich > summary::-webkit-details-marker { display: none; }
.uebertrag-alle { display: flex; align-items: center; gap: 10px; cursor: pointer; margin: 0; }
.uebertrag-zahl {
    margin-left: auto; font-size: .78rem; opacity: .65;
    font-variant-numeric: tabular-nums;
}
.uebertrag-liste {
    display: flex; flex-direction: column;
    border-top: 1px solid var(--border-color, rgba(148,163,184,.2));
    max-height: 320px; overflow-y: auto;
}
.uebertrag-zeile {
    display: flex; align-items: center; gap: 10px; margin: 0;
    padding: 7px 14px; font-size: .88rem; cursor: pointer;
}
.uebertrag-zeile + .uebertrag-zeile { border-top: 1px solid var(--border-color, rgba(148,163,184,.12)); }
.uebertrag-zeile .ub-name { flex: 1 1 auto; min-width: 0; }
.uebertrag-zeile .ub-key { font-size: .74rem; opacity: .45; }
.uebertrag-zeile .ub-hinweis { font-size: .78rem; opacity: .55; }
.uebertrag-zeile.ist-gesperrt { opacity: .55; cursor: default; }
.uebertrag-linie { border: 0; border-top: 1px solid var(--border-color, rgba(148,163,184,.25)); margin: 22px 0 16px; }

/* Der Vergleich beim Einspielen: was sich aendert, faellt ins Auge; was gleich bleibt, tritt
   zurueck. Ohne diesen Unterschied liest niemand dreihundert Zeilen. */
.uebertrag-kopf {
    display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center;
    margin-bottom: 12px; font-size: .9rem;
}
.uebertrag-marken { display: flex; flex-wrap: wrap; gap: 6px; }
.ub-marke {
    font-size: .76rem; font-weight: 600; padding: 3px 9px; border-radius: 999px;
    border: 1px solid currentColor;
}
.ub-anders   { color: var(--primary-color, #3b82f6); }
.ub-gleich   { color: var(--text-muted, #94a3b8); }
.ub-neu      { color: var(--success-color, #10b981); }
.ub-gesperrt { color: var(--danger-color, #ef4444); }
.uebertrag-vergleich { max-height: 460px; }
.uebertrag-zeile.ist-gleich { opacity: .6; }
.ub-wandel { display: flex; align-items: center; gap: 6px; font-size: .8rem; min-width: 0; }
.ub-alt { opacity: .55; text-decoration: line-through; }
.ub-neu-wert { font-weight: 600; }

.sicherung-stand { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 16px;
    padding: 10px 12px; border-radius: var(--radius); border-left: 4px solid var(--djk-border);
    background: var(--djk-black-soft); margin-bottom: 12px; }
.sicherung-stand strong { font-size: 1.05rem; }
.sicherung-stand span { font-size: 0.85rem; opacity: 0.75; }
.sicherung-gut { border-left-color: var(--djk-success, #2e9e5b); }
.sicherung-alt { border-left-color: var(--djk-copper, #c8894a); }
.sicherung-schlecht, .sicherung-nie { border-left-color: var(--djk-danger); }
.sicherung-liste { list-style: none; margin: 0 0 12px; padding: 0; }
.sicherung-liste li { display: flex; justify-content: space-between; gap: 12px;
    padding: 4px 0; border-bottom: 1px solid var(--djk-border); font-size: 0.85rem; }
.sicherung-liste .sl-groesse { opacity: 0.6; white-space: nowrap; }
.sicherung-uhr summary { cursor: pointer; font-size: 0.9rem; }
.sicherung-uhr code { display: block; margin-top: 6px; padding: 8px 10px; border-radius: var(--radius);
    background: var(--djk-black-soft); font-size: 0.78rem; overflow-x: auto; white-space: nowrap; }

/* Verfahrensdokumentation: ein Papier, kein Bildschirm. Ruhige Zeilen, kein Zierrat -
   gelesen wird es von einem Steuerberater, nicht bedient. */
.vd { line-height: 1.65; }
.vd h3 { margin: 26px 0 8px; font-size: 1.05rem; }
.vd h4 { margin: 0 0 6px; font-size: 0.95rem; }
.vd p { margin: 0 0 12px; }
.vd-vorwort { padding: 12px 14px; border-radius: var(--radius); background: var(--djk-black-soft); }
.vd-zahlen { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 0 0 14px; padding: 0; }
.vd-zahlen li { font-size: 0.85rem; opacity: 0.75; }
.vd-zahlen li span { display: block; font-size: 1.15rem; font-weight: 700; opacity: 1; }
.vd-befund { padding: 12px 14px; border-radius: var(--radius); border-left: 4px solid var(--djk-border);
    background: var(--djk-black-soft); margin: 0 0 16px; }
.vd-befund p:last-child { margin-bottom: 0; }
.vd-gut { border-left-color: var(--djk-success, #2e9e5b); }
.vd-schlecht { border-left-color: var(--djk-danger); }
.vd-vorfall { padding: 12px 14px; border: 1px solid var(--djk-border); border-radius: var(--radius); margin: 0 0 14px; }
.vd-fuss { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--djk-border); font-size: 0.88rem; opacity: 0.75; }

/* Die drei Schritte unter dem Knopf. Nummeriert, weil es eine Reihenfolge ist und keine
   Liste von Moeglichkeiten. */
.programm-schritte { margin: 14px 0 10px; padding-left: 20px; line-height: 1.7; font-size: 0.9rem; }
.programm-schritte li { margin-bottom: 2px; }

/* Meine Tische: die Nummer traegt die Zeile, die Zahl daneben ist nur Beiwerk. */
.umsatz-tischliste li { display: flex; align-items: baseline; gap: 10px; }
.umsatz-tischliste .umsatz-tisch { font-weight: 700; min-width: 3.2rem; }
.umsatz-tischliste .umsatz-tisch-klein { flex: 1; font-size: 0.8rem; opacity: 0.6; }
/* Ein offener Tisch faellt auf - er ist der einzige Eintrag, bei dem noch etwas zu tun ist. */
.umsatz-tischliste .umsatz-tisch-offen .umsatz-tisch { color: var(--djk-copper, #c8894a); }
.umsatz-tischliste .umsatz-tisch-offen .umsatz-tisch-klein { opacity: 0.9; }

/* Kopf der Kassen-Unterseiten (Tagesumsatz). Er richtet sich nach denselben 640 px wie die
   Karten darunter - sonst steht die Ueberschrift neben ihrem eigenen Inhalt. */
.kasse-seite-kopf {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    max-width: 640px;
    margin: 0 auto;
    /* Oben die Statusleiste des Telefons freihalten, links und rechts denselben Rand wie
       die Karten - dort wurde der Zurueck-Knopf abgeschnitten. */
    padding: calc(10px + env(safe-area-inset-top, 0px)) 12px 2px;
}
.kasse-seite-kopf h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 1.4rem;
}
@media (max-width: 560px) {
    .kasse-seite-kopf h2 { flex: 1 0 100%; order: 2; }
    .kasse-seite-kopf .kasse-tische-btn { order: 1; }
}
/* Fest oben (26.09.2026): dasselbe Polster wie oben, nur unten etwas Luft vor den Karten. Die
   Zusammensetzung schlaegt `.kopf-fest`, sonst naehme die sichere Zone zweimal Platz. */
.kasse-seite-kopf.kopf-fest { padding: calc(10px + env(safe-area-inset-top, 0px)) 12px 8px; }
/* Datum links, Drucker und PDF als reine Zeichen rechts — eine Zeile. */
/* `order: 3`: am Telefon bekommt die Ueberschrift `order: 2` (siehe oben) — ohne das stuende
   die Datumszeile UEBER dem Titel (gemessen 26.09.2026). */
.umsatz-kopf-zeile { order: 3; flex: 1 0 100%; display: flex; align-items: center; gap: 10px; min-width: 0; }
.umsatz-kopf-zeile .umsatz-zeitraum { flex: 1 1 auto; min-width: 0; margin: 0; }
.umsatz-kopf-zeile .umsatz-aktionen { flex: 0 0 auto; flex-wrap: nowrap; margin: 0; }
.umsatz-kopf-zeile .umsatz-aktionen .btn { width: 40px; height: 36px; padding: 0; justify-content: center; }
.umsatz-kopf-zeile .umsatz-aktionen .icon { width: 18px; height: 18px; }

/* Storno an der Verlaufskarte: dieselbe zurueckhaltende Form wie "rueckgaengig" daneben,
   aber in der Farbe, die im ganzen Haus Rueckabwicklung bedeutet. */
.stb-storno { background: none; border: none; padding: 4px 8px; font: inherit; font-size: 0.82rem;
    color: var(--djk-danger); cursor: pointer; }
.stb-storno:hover { text-decoration: underline; }

/* Der Storno sitzt in der Kopfzeile der Karte, rechts neben dem Datum - weit weg von den
   Knoepfen, die man im Betrieb staendig drueckt. Ein Rahmen statt eines Fuelltons: er soll
   auffindbar sein, nicht einladend. */
.stb-kopf { position: relative; }
.stb-kopf .stb-storno {
    position: absolute;
    top: 0;
    right: 0;
    padding: 4px 12px;
    border: 1px solid var(--djk-danger);
    border-radius: 999px;
    background: none;
    color: var(--djk-danger);
    font: inherit;
    font-size: 0.8rem;
    line-height: 1.4;
    cursor: pointer;
}
.stb-kopf .stb-storno:hover { background: var(--djk-danger); color: #fff; }
/* Auf der roten Karte waere Rot auf Rot unlesbar - dort weiss. */
.stb-block.ist-offen .stb-kopf .stb-storno { border-color: #fff; color: #fff; }
.stb-block.ist-offen .stb-kopf .stb-storno:hover { background: #fff; color: var(--djk-danger); }

/* Zahlenschloss: grosse Tasten, weil im Dienst mit dem Daumen getippt wird, und drei
   Punkte statt Sternchen - ein Passwortfeld holt auf dem Telefon die Buchstabentastatur. */
.cf-box { max-width: 320px; text-align: center; }
.cf-punkte { display: flex; justify-content: center; gap: 14px; margin: 14px 0 6px; }
.cf-punkte i { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--djk-border); }
.cf-punkte i.voll { background: var(--djk-yellow); border-color: var(--djk-yellow); }
.cf-fehler { min-height: 1.3em; color: var(--djk-danger); font-size: 0.85rem; margin-bottom: 10px; }
.cf-tasten { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.cf-taste { padding: 16px 0; font-size: 1.35rem; font-weight: 700; border-radius: var(--radius);
    border: 1px solid var(--djk-border); background: var(--djk-black-soft); color: inherit; cursor: pointer; }
.cf-taste:active { background: var(--djk-yellow); color: #fff; }
.cf-taste.cf-klein { font-size: 1rem; opacity: 0.75; }

/* Die Menuepunkte in der Kopfzeile - nur, wo die Zeile Platz hat. Auf dem Telefon ist sie
   ohnehin voll; dort bleibt das Menue der einzige Weg (eine Drehung weiter). */
.kasse-kopf-menue { display: none; }
@media (min-width: 1100px) {
    .kasse-kopf-menue { display: flex; gap: 6px; margin-left: 6px; }
}
/* Der Tisch-Knopf ist der meistgedrueckte der ganzen Kasse - er darf der groesste sein. */
#tischeBtn { min-width: 96px; padding: 12px 16px; font-size: 1.05rem; }
#tischeBtn svg, #tischeBtn img { width: 1.4em; height: 1.4em; }
@media (max-width: 640px) {
    #tischeBtn { min-width: 78px; padding: 10px 12px; font-size: 1rem; }
}

/* Der Tisch-Knopf traegt seinen Namen ganz - abgeschnittenes "Tis..." sieht kaputt aus. */
#tischeBtn { min-width: auto; white-space: nowrap; }
#tischeBtn #activeTischLabel { overflow: visible; text-overflow: clip; max-width: none; }
/* Der Verlauf stand zweimal in der Zeile, sobald die Fernbedienungen da sind: der alte
   Menue-Knopf und die neue Uhr. Auf dem grossen Schirm bleibt die neue. */
@media (min-width: 1100px) {
    #verlaufBtn { display: none; }
}

/* ===================== Die persoenliche Sicht: ausgeblendete Kacheln =====================
   Was ein Kellner fuer sich weggelegt hat, ist im Alltag GAR nicht da (die Regel dafuer baut
   includes/kachel_verborgen.php und schreibt sie in den Kopf der Seite). Beim langen Druecken
   steht es wieder an seinem Platz — truebe, damit man sieht, dass es weggelegt wurde. */
body.kacheln-ordnen-an .product-tile,
body.kacheln-ordnen-an .warengruppe-chip {
    opacity: calc(1 - 0.62 * var(--kachel-ist-verborgen, 0));
    filter: blur(calc(var(--kachel-ist-verborgen, 0) * 1.6px));
    transition: opacity .18s ease, filter .18s ease;
}
/* Das Auge selbst darf nicht mit verschwimmen — sonst kann man es nicht mehr treffen. */
body.kacheln-ordnen-an .product-tile > .kachel-auge,
body.kacheln-ordnen-an .warengruppe-chip > .kachel-auge {
    filter: none;
    opacity: 1;
}

/* source/style_css/465_daily_revenue_house_settings_continued.css - style.css: daily revenue house settings continued, part 69 of 78 (built by werkzeuge/parts_build.php) */
/* Das Zeichen in der Ecke. Oben LINKS: der Stern der Start-Kategorie und der Punkt der
   Warengruppe sitzen rechts (.ist-start-kat::after) — zwei Marken auf demselben Fleck waeren
   eine Verwechslung im Halbdunkel. */
.kachel-auge {
    position: absolute;
    top: 3px;
    left: 3px;
    z-index: 6;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(15, 23, 42, .82);
    color: #fff;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .45);
    /* Die Kachel wackelt im Ordnen-Modus; das Auge wackelt mit, aber es soll nicht selbst
       gezogen werden koennen. */
    -webkit-user-select: none;
    user-select: none;
    touch-action: manipulation;
}
.kachel-auge.ist-zurueck {
    background: var(--djk-yellow, #f0b429);
    color: #0f172a;
    font-size: 17px;
}
.kachel-auge:active { scale: 0.88; }
.kachel-auge.laeuft { opacity: .5; pointer-events: none; }

/* Die Warengruppe ist ein flacher Knopf ohne eigene Ecke — sie braucht sie erst dafuer. */
body.kacheln-ordnen-an .warengruppe-chip { position: relative; }
body.kacheln-ordnen-an .warengruppe-chip > .kachel-auge {
    width: 22px;
    height: 22px;
    font-size: 13px;
    top: 2px;
    left: 2px;
}

/* Auf dem Telefon ist die Kachel klein — das Auge bleibt trotzdem so gross, dass ein Daumen
   es trifft, ohne den Namen darunter zu verdecken. */
@media (max-width: 640px) {
    .kachel-auge { width: 24px; height: 24px; font-size: 14px; }
}

/* source/style_css/470_reservation_window_colors.css - style.css part 70 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ===================== Das Reservierungs-Fenster: Farbe statt Grau =====================
   „монотонность очень скучно" (22.08.2026). Jedes Feld traegt seine eigene Farbe in `--rf`;
   Zeichen, Streifen und Fokusrahmen kommen alle daraus. */
.reserv-form-bunt .field { --rf: var(--djk-gray); }
.reserv-form-bunt .rf-datum    { --rf: #6366f1; }
.reserv-form-bunt .rf-zeit     { --rf: #3b82f6; }
.reserv-form-bunt .rf-name     { --rf: #8b5cf6; }
.reserv-form-bunt .rf-personen { --rf: #10b981; }
.reserv-form-bunt .rf-zweck    { --rf: #f59e0b; }
.reserv-form-bunt .rf-tisch    { --rf: #14b8a6; }
.reserv-form-bunt .rf-wdh      { --rf: #ec4899; }

.reserv-feld-farbe {
    position: relative;
    padding-left: 12px;
    border-radius: 10px;
}
/* Der Streifen links: er macht aus einer Liste von Kaesten eine Liste von Feldern. */
.reserv-feld-farbe::before {
    content: '';
    position: absolute;
    left: 0;
    top: 2px;
    bottom: 2px;
    width: 3px;
    border-radius: 3px;
    background-color: var(--rf);
    opacity: 0.55;
}
.reserv-feld-farbe:focus-within::before { opacity: 1; }

.reserv-feld-farbe > label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    color: var(--rf);
    letter-spacing: 0.01em;
}
.reserv-feld-farbe > label svg,
.reserv-feld-farbe > label i {
    width: 1.05em;
    height: 1.05em;
    font-size: 1.05em;
    color: var(--rf);
    flex: none;
}

/* Der Fokus faerbt sich mit — man sieht ohne Lesen, in welchem Feld man steht. */
.reserv-feld-farbe input:focus,
.reserv-feld-farbe select:focus {
    border-color: var(--rf);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--rf) 22%, transparent);
    outline: none;
}

/* Personenzahl und „circa" in einer Zeile — vorher stand das im style-Attribut. */
.reserv-personen-reihe { display: flex; align-items: center; gap: 10px; }
.reserv-personen-reihe > input { flex: 1; min-width: 0; }

/* Ein Haken, der aussieht wie ein Haken und nicht wie ein Absatz. */
.reserv-schalter {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
    white-space: nowrap;
    padding: 7px 11px;
    border: 1px solid var(--djk-border);
    /* Dieselbe Rundung wie die Eingabefelder daneben — der Wirt hat die runden Pillen
       eingekringelt. Zwei Formensprachen in einem Fenster sehen aus wie zwei Programme. */
    border-radius: var(--feld-radius);
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}
.reserv-schalter:hover { border-color: var(--djk-yellow); }
.reserv-schalter input[type="checkbox"] {
    accent-color: var(--rf, var(--djk-yellow));
    width: 16px;
    height: 16px;
    margin: 0;
}
.reserv-schalter:has(input:checked) {
    border-color: var(--djk-yellow);
    background-color: color-mix(in srgb, var(--djk-yellow) 12%, transparent);
    font-weight: 600;
}
.reserv-schalter-breit { white-space: normal; }

/* Was der Zweck bedeutet, steht unter dem Zweck — nicht beim Tisch, wo man es erst
   bemerkt, wenn man schon gewaehlt hat. */
.reserv-zweck-hinweis { margin-top: 6px; }
.reserv-zweck-hinweis.reserv-zweck-warnung {
    color: var(--djk-danger);
    font-weight: 600;
}

.reserv-anlegen-knopf {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 4px;
}

/* ===================== Verwaltung: welche Tische gehoeren zum Zweck ===================== */
.zweck-tisch-wahl {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    max-height: 220px;
    overflow-y: auto;
    padding: 10px;
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    background-color: var(--djk-black-soft);
}
.zweck-tisch-kachel {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 7px 11px;
    border: 1px solid var(--djk-border);
    border-radius: 999px;
    background-color: var(--djk-black-card);
    cursor: pointer;
    font-size: 0.9rem;
    user-select: none;
    transition: border-color .15s ease, background-color .15s ease;
}
.zweck-tisch-kachel:hover { border-color: var(--djk-yellow); }
/* Der Haken selbst ist im Weg — die Kachel IST der Haken. */
.zweck-tisch-kachel input { position: absolute; opacity: 0; width: 0; height: 0; }
.zweck-tisch-kachel:has(input:checked) {
    border-color: var(--djk-yellow);
    background-color: color-mix(in srgb, var(--djk-yellow) 14%, transparent);
    font-weight: 600;
}
.ztk-nummer { font-variant-numeric: tabular-nums; }
.ztk-plaetze {
    font-size: 0.75rem;
    color: var(--djk-gray);
    font-weight: 400;
}

.zweck-tische-zeile {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin: 6px 0 0;
    font-size: 0.82rem;
}
.zweck-tisch-marke {
    padding: 2px 8px;
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--djk-yellow) 15%, transparent);
    color: var(--djk-yellow-dark);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.zweck-tische-alle {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--djk-success);
    font-weight: 600;
}
.zweck-tische-alle svg, .zweck-tische-alle i { width: 0.95em; height: 0.95em; font-size: 0.95em; }

/* ===================== Tische, die nicht zu haben sind =====================
   „лучше пусть покажет и пишет, что стол забронирован" (22.08.2026). Ein Tisch, der einfach
   fehlt, sieht aus wie ein Tisch, den es nicht gibt — und jemand sucht ihn.

   Drei Zustaende, drei Farben, alle drei lesbar. Ausgrauen bis zur Unkenntlichkeit waere
   dasselbe wie Weglassen, nur langsamer. */
.rtv-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.rtv-weg {
    cursor: not-allowed;
    opacity: 0.92;
}
.rtv-grund {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: lowercase;
    padding: 1px 6px;
    border-radius: 999px;
    background-color: rgba(0, 0, 0, .10);
}
/* Eine Absicht. */
.rtv-reserviert {
    border-color: #3b82f6 !important;
    color: #2563eb;
    background-color: color-mix(in srgb, #3b82f6 10%, transparent) !important;
}
.rtv-reserviert .rtv-grund { background-color: color-mix(in srgb, #3b82f6 22%, transparent); }
/* Eine Tatsache — da sitzt jemand. */
.rtv-besetzt {
    border-color: var(--djk-danger) !important;
    color: var(--djk-danger);
    background-color: color-mix(in srgb, var(--djk-danger) 10%, transparent) !important;
}
.rtv-besetzt .rtv-grund { background-color: color-mix(in srgb, var(--djk-danger) 22%, transparent); }
/* Eine Regel des Hauses. */
.rtv-gesperrt {
    border-color: var(--djk-gray) !important;
    color: var(--djk-gray);
    background-color: color-mix(in srgb, var(--djk-gray) 12%, transparent) !important;
    text-decoration: line-through;
}
.rtv-gesperrt .rtv-grund { text-decoration: none; background-color: color-mix(in srgb, var(--djk-gray) 24%, transparent); }

.rtv-titel-weg {
    display: block;
    width: 100%;
    margin-top: 10px;
    color: var(--djk-gray);
}

/* ===================== Zweck-Kacheln mit Sperrzeiten ===================== */
.ztk-huelle { position: relative; display: inline-flex; }
.zweck-tisch-kachel { padding-right: 34px; }
.ztk-schloss {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: var(--feld-radius);
    background-color: transparent;
    color: var(--djk-gray);
    cursor: pointer;
    opacity: 0.55;
}
.ztk-schloss:hover { opacity: 1; background-color: rgba(0,0,0,.06); }
.ztk-schloss.an { opacity: 1; color: var(--djk-danger); }
.ztk-schloss svg, .ztk-schloss i { width: 13px; height: 13px; font-size: 13px; }
.zweck-tisch-kachel.hat-sperre { border-color: var(--djk-danger); }
.ztk-sperrmarke {
    position: absolute;
    top: -5px;
    right: -3px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background-color: var(--djk-danger);
    color: #fff;
    font-size: 0.66rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    pointer-events: none;
}

.ztk-sperrkasten {
    margin-top: 12px;
    padding: 14px;
    border: 1px solid var(--djk-border);
    border-radius: 10px;
    background-color: var(--djk-black-soft);
}
.ztk-sperrkopf { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.ztk-tage { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.ztk-tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 10px;
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    background-color: var(--djk-black-card);
    cursor: pointer;
    font-size: 0.85rem;
    user-select: none;
}
.ztk-tag:has(input:checked) {
    border-color: var(--djk-yellow);
    background-color: color-mix(in srgb, var(--djk-yellow) 14%, transparent);
    font-weight: 600;
}
.ztk-zeiten { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
.ztk-zeiten label { display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; }
.ztk-sperrform input[type="text"] { width: 100%; margin-bottom: 10px; }

.sperr-liste { display: flex; flex-direction: column; gap: 7px; margin-bottom: 14px; }
.sperr-zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 8px 12px;
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    background-color: var(--djk-black-card);
}
.sperr-zeile form { margin-left: auto; }
.sperr-art {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 7px;
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--djk-gray) 16%, transparent);
    color: var(--djk-gray);
}
.sperr-text { color: var(--djk-gray); font-size: 0.88rem; }
.sperr-form-reihe { display: flex; flex-wrap: wrap; gap: 14px; }
.sperr-form-reihe .field { min-width: 220px; }

/* ===================== Tisch auf dem Plan waehlen (22.08.2026) =====================
   Eine Liste mit 27 Zeilen sagt nicht, WO ein Tisch steht. Der Plan sagt es in einem Blick.
   Die vier Farben sind dieselben wie bei den Vorschlagsknoepfen — sonst haette derselbe Tisch
   zwei Bedeutungen. */
.tpw-fenster {
    position: fixed;
    inset: 0;
    z-index: 4000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background-color: rgba(15, 23, 42, .62);
}
.tpw-kasten {
    display: flex;
    flex-direction: column;
    width: min(1100px, 100%);
    max-height: 92vh;
    border-radius: 12px;
    background-color: var(--djk-black-card);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
    overflow: hidden;
}
.tpw-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--djk-border);
}
.tpw-zu { border: none; background: none; font-size: 1.7rem; line-height: 1; cursor: pointer; color: var(--djk-gray); }
.tpw-reiter { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 18px 0; }
.tpw-reiter-knopf {
    padding: 7px 13px;
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    background-color: transparent;
    cursor: pointer;
    font-size: 0.9rem;
}
.tpw-reiter-knopf.aktiv {
    border-color: var(--djk-yellow);
    background-color: color-mix(in srgb, var(--djk-yellow) 14%, transparent);
    font-weight: 600;
}
.tpw-buehne { flex: 1; min-height: 0; overflow: auto; padding: 14px 18px; }
.tpw-svg { width: 100%; height: auto; max-height: 66vh; display: block; }
.tpw-text { font-size: 15px; font-weight: 600; }
.tpw-tisch { cursor: pointer; }
.tpw-tisch[data-weg] { cursor: not-allowed; }
/*
 * IN DER TISCHWAHL BLEIBT DER STUHL NEUTRAL — und das ist kein Vergessen (10.09.2026).
 *
 * Ich hatte auch hier die Farbe des Tisches genommen. Gerechnet gegen den WEISSEN Grund
 * des Fensters: `#dcfce7` (frei) 1,10 : 1, `#fee2e2` (besetzt) 1,22 : 1. Die Stuehle
 * waeren praktisch verschwunden — und sie sind genau das, was man hier abzaehlt.
 *
 * Die Flaechen der Tischwahl sind blasse Pastelltoene auf Weiss; ein Ton davon ist auf
 * Weiss nichts. In der KASSE geht es, weil die Flaechen dort kraeftig sind.
 *
 * Der Zustand steht hier ohnehin schon zweimal: in der Flaeche und in ihrer Kontur. Der
 * Stuhl muss ihn nicht ein drittes Mal sagen — er muss zaehlbar sein.
 */
.tpw-flaeche { stroke-width: 2; }
.tpw-name { text-anchor: middle; font-size: 15px; font-weight: 700; fill: #0f172a; }
.tpw-plaetze { text-anchor: middle; font-size: 11px; fill: #475569; }
.tpw-grund { text-anchor: middle; font-size: 10px; font-weight: 700; text-transform: lowercase; }

/* source/style_css/475_reservation_window_colors_continued.css - style.css: reservation window colors continued, part 71 of 78 (built by werkzeuge/parts_build.php) */
.tpw-frei .tpw-flaeche { fill: #dcfce7; stroke: #10b981; }
.tpw-reserviert .tpw-flaeche { fill: #dbeafe; stroke: #3b82f6; }
.tpw-reserviert .tpw-grund { fill: #2563eb; }
.tpw-besetzt .tpw-flaeche { fill: #fee2e2; stroke: #ef4444; }
.tpw-besetzt .tpw-grund { fill: #dc2626; }
.tpw-gesperrt .tpw-flaeche { fill: #e2e8f0; stroke: #94a3b8; }
.tpw-gesperrt .tpw-grund { fill: #64748b; }
.tpw-tisch:not([data-weg]):hover .tpw-flaeche { stroke-width: 4; }

.tpw-rest { display: flex; flex-wrap: wrap; gap: 7px; }
.tpw-rest-voll { padding: 6px 0; }
.tpw-rest-titel { margin: 12px 0 6px; }
.tpw-rest-knopf {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 8px 13px;
    border: 1px solid var(--djk-border);
    border-radius: var(--feld-radius);
    background-color: var(--djk-black-card);
    cursor: pointer;
}
.tpw-rest-knopf small { color: var(--djk-gray); font-size: 0.75rem; }
.tpw-rest-knopf em { font-style: normal; font-size: 0.72rem; font-weight: 700; }
.tpw-rest-knopf:disabled { cursor: not-allowed; }
.tpw-rest-knopf.tpw-frei { border-color: #10b981; }
.tpw-rest-knopf.tpw-reserviert { border-color: #3b82f6; color: #2563eb; }
.tpw-rest-knopf.tpw-besetzt { border-color: #ef4444; color: #dc2626; }
.tpw-rest-knopf.tpw-gesperrt { border-color: #94a3b8; color: #64748b; text-decoration: line-through; }

.tpw-legende {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 14px;
    padding: 10px 18px 14px;
    border-top: 1px solid var(--djk-border);
    font-size: 0.82rem;
    color: var(--djk-gray);
}
.tpw-punkt { width: 12px; height: 12px; border-radius: 3px; border: 2px solid; display: inline-block; }
.tpw-punkt.tpw-frei { background-color: #dcfce7; border-color: #10b981; }
.tpw-punkt.tpw-reserviert { background-color: #dbeafe; border-color: #3b82f6; }
.tpw-punkt.tpw-besetzt { background-color: #fee2e2; border-color: #ef4444; }
.tpw-punkt.tpw-gesperrt { background-color: #e2e8f0; border-color: #94a3b8; }

/* Feld und Plan-Knopf nebeneinander. */
.reserv-tisch-reihe { display: flex; gap: 8px; align-items: stretch; }
.reserv-tisch-reihe > select { flex: 1; min-width: 0; }
.reserv-plan-knopf { flex: none; padding: 0 14px; display: inline-flex; align-items: center; }


/* source/style_css/480_events_colors.css - style.css part 72 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ===================== Veranstaltungen: Farbe statt zehn grauer Karten (22.08.2026)
   Der Wirt: „иконки везде, разные цвета, чтобы не было монотонности."

   Die Farben sind NICHT hier erfunden — sie sind die Hausfarben der Sinnbilder aus
   `ICON_FARBE` (includes/icons.php). Das Haus faerbt seine Zeichen mit `!important`; dagegen
   anzuschreiben hiesse, einen violetten Strich neben ein bernsteinfarbenes Zeichen zu setzen.
   Also folgt der Strich dem Zeichen.

   `--vk` steht an der KARTE und nicht an der Ueberschrift: eigene Eigenschaften vererben sich
   nach unten, nicht nach oben. Stuende sie an der Ueberschrift, faende das Band am Kopf der
   Karte sie nie — genau daran ist der erste Anlauf gescheitert. */
.form-card:has(h3.vk-liste)     { --vk: #ec4899; }   /* music     rosa    — die Abende selbst */
.form-card:has(h3.vk-angaben)   { --vk: #3b82f6; }   /* pencil    blau    — Grunddaten */
.form-card:has(h3.vk-karte)     { --vk: #f59e0b; }   /* produkte  gelb    — Essen und Trinken */
.form-card:has(h3.vk-eigenes)   { --vk: #10b981; }   /* plus      gruen   — etwas Neues */
.form-card:has(h3.vk-leute)     { --vk: #8b5cf6; }   /* user      lila    — Menschen */
.form-card:has(h3.vk-summe)     { --vk: #10b981; }   /* euro      gruen   — Geld */
.form-card:has(h3.vk-jekellner) { --vk: #8b5cf6; }   /* chart     lila    — Auswertung */
.form-card:has(h3.vk-verkauft)  { --vk: #3b82f6; }   /* clipboard blau    — eine Liste */
.form-card:has(h3.vk-tischeneu) { --vk: #10b981; }   /* plus      gruen   — etwas Neues */
.form-card:has(h3.vk-tische)    { --vk: #14b8a6; }   /* table     tuerkis — der Raum; nicht blau, weil der Reiter 'Angaben' blau ist */

h3.vk {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 0;
}
/* Der Strich vor der Ueberschrift macht aus einer Reihe von Kaesten eine Reihe von
   Abschnitten — man sieht sie, ohne die Ueberschrift zu lesen. */
h3.vk::before {
    content: '';
    flex: none;
    width: 4px;
    align-self: stretch;
    min-height: 1.15em;
    border-radius: 2px;
    background-color: var(--vk, var(--djk-gray));
}
h3.vk i.icon, h3.vk svg { flex: none; }

/* Das Band am oberen Rand der Karte. */
.form-card:has(h3.vk) {
    position: relative;
    overflow: hidden;
}
.form-card:has(h3.vk)::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 3px;
    background-color: var(--vk, var(--djk-gray));
    opacity: .9;
}

/* Die Marken bekommen die Farbe ihrer Karte — ohne eigene Regel je Karte. */
.form-card:has(h3.vk) .veranst-marke {
    border-color: color-mix(in srgb, var(--vk) 45%, transparent);
    background-color: color-mix(in srgb, var(--vk) 10%, transparent);
}

/* Geld liest man von weitem. */
.veranst-zahl-gross { color: #059669; }

/*
 * Die Warengruppen in der Karte des Abends.
 *
 * Fuenfzehn gleiche Ueberschriften untereinander sind wieder eine Wand. Sie bekommen der Reihe
 * nach eine von sechs Farben — hier NICHT nach Bedeutung (die hat eine Warengruppe an dieser
 * Stelle nicht), sondern damit das Auge beim Blaettern einen Halt hat.
 */
.veranst-gruppe { --vg: var(--djk-gray); }
.veranst-gruppe:nth-of-type(6n+1) { --vg: #3b82f6; }
.veranst-gruppe:nth-of-type(6n+2) { --vg: #f59e0b; }
.veranst-gruppe:nth-of-type(6n+3) { --vg: #10b981; }
.veranst-gruppe:nth-of-type(6n+4) { --vg: #8b5cf6; }
.veranst-gruppe:nth-of-type(6n+5) { --vg: #ec4899; }
.veranst-gruppe:nth-of-type(6n)   { --vg: #14b8a6; }
.veranst-gruppe-kopf strong {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--vg);
}
.veranst-gruppe-kopf strong::before {
    content: '';
    width: 9px;
    height: 9px;
    border-radius: 3px;
    background-color: var(--vg);
}
/* Eine angehakte Zeile traegt die Farbe ihrer Gruppe: man sieht auf einen Blick, wo an diesem
   Abend etwas gewaehlt ist, ohne die Haken zu zaehlen. */
.veranst-zeile.ist-an {
    border-color: color-mix(in srgb, var(--vg) 55%, transparent) !important;
    background-color: color-mix(in srgb, var(--vg) 9%, transparent) !important;
}

/* ===================== Die Reiter der Veranstaltung (22.08.2026)
   „иконки везде." Fuenf Woerter nebeneinander liest man jedes Mal neu; fuenf Zeichen in fuenf
   Farben erkennt man. Die Farbe muss `!important` sein: ICON_FARBE faerbt jedes Sinnbild des
   Hauses so, und hier soll ausnahmsweise etwas anderes gelten. */
.admin-tab, .admin-sidebar-sublink { display: inline-flex; align-items: center; gap: 8px; }
.admin-tab i.icon, .admin-sidebar-sublink i.icon { font-size: 15px; width: 15px; height: 15px; flex: none; }

.vt-angaben  i.icon { color: #3b82f6 !important; }
.vt-produkte i.icon { color: #f59e0b !important; }
.vt-personal i.icon { color: #8b5cf6 !important; }
.vt-tische   i.icon { color: #14b8a6 !important; }
.vt-finanzen i.icon { color: #10b981 !important; }

/* Der offene Reiter traegt seine Farbe auch als Grund — sonst sieht man das Zeichen, aber nicht,
   wo man ist. */
.admin-tab.vt-angaben.active  { border-color: #3b82f6; box-shadow: inset 0 -3px 0 #3b82f6; }
.admin-tab.vt-produkte.active { border-color: #f59e0b; box-shadow: inset 0 -3px 0 #f59e0b; }
.admin-tab.vt-personal.active { border-color: #8b5cf6; box-shadow: inset 0 -3px 0 #8b5cf6; }
.admin-tab.vt-tische.active   { border-color: #14b8a6; box-shadow: inset 0 -3px 0 #14b8a6; }
.admin-tab.vt-finanzen.active { border-color: #10b981; box-shadow: inset 0 -3px 0 #10b981; }
/* Auf dem offenen Reiter steht weisse Schrift — dort muss das Zeichen mitkommen. */
.admin-tab.active i.icon { color: #ffffff !important; }

/* ===== Das Kalendersymbol ZIEHT DAS FELD AUSEINANDER (22.08.2026) =====
   Gemessen: Datum 52 px, Text 43 px — bei gleichem Innenabstand und gleicher Zeilenhoehe. Die
   Differenz kommt vom eingebauten Kalendersymbol: es steht in derselben Zeile und ist rund
   24 px hoch, also wird die Zeile so hoch. Mit einer festen Groesse steht es still.

   Die Feldhoehe selbst bleibt ungenagelt — sie soll sich weiter aus Schrift und Innenabstand
   ergeben, sonst bricht sie, sobald jemand die Schrift groesser stellt. */
.field input[type="date"]::-webkit-calendar-picker-indicator,
.field input[type="time"]::-webkit-calendar-picker-indicator {
    width: 16px;
    height: 16px;
    margin: 0;
    padding: 0;
    cursor: pointer;
    opacity: .55;
}
.field input[type="date"]:hover::-webkit-calendar-picker-indicator,
.field input[type="time"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }
.field input[type="date"]::-webkit-datetime-edit,
.field input[type="time"]::-webkit-datetime-edit { line-height: 1.15; }

/* ===== Alle Felder gleich hoch, durch Bauart (22.08.2026) =====
   Gemessen: Datumsfeld 48 px neben einem Textfeld mit 43. Weder `line-height` noch
   `display:block` am inneren Teil halfen; erst `height` ZUSAMMEN mit `min-height: 0` — es gibt
   ein Mindestmass, das sonst dagegenhaelt.

   Die Hoehe steht deshalb an EINER Stelle, und alle Felder nehmen sie von dort. Sie sind dann
   gleich hoch, weil sie es gar nicht anders sein koennen. Fuer Text und Auswahl aendert sich
   nichts (die sind schon so hoch) — nur Datum und Uhrzeit kommen in die Reihe.

   Kontrollkaestchen und Schalter sind ausgenommen: die sind keine Felder, sondern Marken. */
/* Die Merke haengt an der ganzen Verwaltung, nicht nur an den `.field`-Kaesten: die Zeile
   „Feste Kosten" baut ihre Felder ohne so einen Kasten, und dort standen 43 und 48
   nebeneinander. Was fuer ein Feld gilt, gilt fuer jedes — deshalb gilt fuer die ganze
   Verwaltung dieselbe Hoehe. */
body.admin-body,
.reserv-feld-farbe { --feld-hoehe: 43px; }

/* Die Ausnahmen stehen in `:where()`, damit sie NICHTS wiegen — sonst waere diese Grundregel
   schwerer als jede oertliche und wuerde sie ueberstimmen (an der Suchzeile der Geldseite
   gemessen: dort blieb ein ausdrueckliches `height: auto` wirkungslos). */
body.admin-body input:where(:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="image"])),
body.admin-body select,
.reserv-feld-farbe input:not([type="checkbox"]):not([type="radio"]),
.reserv-feld-farbe select {
    height: var(--feld-hoehe);
    min-height: 0;
    box-sizing: border-box;
}
/* Ohne den Innenabstand auf null rechnet der Browser ihn zur festen Hoehe dazu und schneidet
   die Ziffern ab. */
body.admin-body input[type="date"],
body.admin-body input[type="time"],
body.admin-body input[type="month"],
body.admin-body input[type="week"],
body.admin-body input[type="datetime-local"],
.reserv-feld-farbe input[type="date"],
.reserv-feld-farbe input[type="time"] {
    padding-top: 0;
    padding-bottom: 0;
}
/* Mehrzeiliges bleibt mehrzeilig. */
body.admin-body textarea, .reserv-feld-farbe textarea { height: auto; min-height: 0; }

/* Das Zeichen der Seite in der Kopfleiste (22.08.2026) — es steht vor dem Namen und
   bekommt seine Farbe wie jedes Sinnbild aus ICON_FARBE. */
.admin-topbar-title { display: inline-flex; align-items: center; gap: 10px; }
.admin-topbar-title i.icon { font-size: 17px; width: 17px; height: 17px; flex: none; }

/* ===== Die Beigaben-Tabelle auf dem Telefon (22.08.2026) =====
   Gemessen: 693 px Tabelle in einem 414 px schmalen Fenster, die Seite lief um 279 px
   seitwaerts. Fuenf Spalten, darunter eine Aufzaehlung von acht Tischkategorien — das passt
   nicht, egal wie man umbricht.

   Also wird aus jeder ZEILE eine Karte und aus fuenf Spalten nebeneinander fuenf Zeilen
   untereinander. Die Beschriftung kommt aus `data-spalte` an der Zelle: sie muss uebersetzt
   sein, und das kann ein Stylesheet nicht. */
@media (max-width: 760px) {
    .beigaben-tabelle,
    .beigaben-tabelle tbody,
    .beigaben-tabelle tr,
    .beigaben-tabelle td { display: block; width: 100%; }
    .beigaben-tabelle thead { display: none; }
    .beigaben-tabelle tr {
        margin-bottom: 12px;
        padding: 4px 0;
        border: 1px solid var(--djk-border);
        border-radius: 12px;
        background-color: var(--djk-black-card);
        overflow: hidden;
    }
    .beigaben-tabelle td {
        border: none;
        padding: 8px 14px;
    }
    /* Die Beschriftung darueber, klein und ruhig — sie ist der Wegweiser, nicht der Inhalt. */
    .beigaben-tabelle td[data-spalte]::before {
        content: attr(data-spalte);
        display: block;
        margin-bottom: 2px;
        font-size: 0.68rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: .05em;
        color: var(--djk-gray);
    }
    /* Der Name ist die Ueberschrift der Karte — er braucht keine Beschriftung ueber sich. */
    .beigaben-tabelle td:first-child { padding-top: 12px; }
    .beigaben-tabelle td:first-child::before { display: none; }
    .beigaben-tabelle td:first-child strong { font-size: 1.02rem; }
    /* Eine leere Zelle nimmt sonst Platz fuer nichts. */
    .beigaben-tabelle td:empty { display: none; }
    /* Der Knopf ganz unten ueber die Breite — dort ist der Daumen. */
    .beigaben-tabelle td:last-child { padding-bottom: 12px; }
    .beigaben-tabelle td:last-child .btn { width: 100%; }
}

/* ===== Der Anteil bricht nicht mehr Zeichen fuer Zeichen (22.08.2026) =====
   Auf dem Telefon steht in der Karte „ANTEIL" links und rechts der Balken samt Zahl. Der
   Balken nahm `width: 100%`, der Zahl blieben ein paar Pixel — sie stand als „4, / 6 / %"
   untereinander (der Wirt hat es dreimal eingekringelt).

   Der Balken darf schrumpfen, die Zahl nicht: sie ist die Auskunft, er ist die
   Verzierung. */
.ov-anteil { flex: 1 1 40px; min-width: 30px; }
.ov-anteil + .hint { flex: 0 0 auto; white-space: nowrap; margin-left: 8px; }
/* Damit die beiden ueberhaupt nebeneinander rechnen koennen. */
td:has(> .ov-anteil) { display: flex; align-items: center; }


/* ===== Drei Griffe, drei Farben (22.08.2026) =====
   Der Wirt: „сделай все кнопки разных цветов".

   Nicht bunt um der Buntheit willen — nach dem, was der Griff bedeutet:
   Buchen gruen (weitergeben), Leeren bernstein (Vorsicht, aber nichts ist verloren),
   Storno rot (offene Liste, hier schaut man genauer hin), Bezahlen bleibt blau —
   es ist der Knopf, den jeder blind findet, und den faerbt man nicht um. */
/* Alle drei gefuellt (22.08.2026) — „сделай все кнопки полый цвет".
   Zwei Umrisse neben einem gefuellten sahen aus wie zwei halbe Knoepfe und ein ganzer. */
body.kasse-body .kasse-bottom-actions #sendToTischBtn {
    background: var(--djk-success);
    border-color: var(--djk-success);
    color: #fff;
}
body.kasse-body .kasse-bottom-actions #korbLeerenBtn {
    background: #f59e0b;
    border-color: #f59e0b;
    color: #fff;
}
/* Das Zeichen nimmt die Farbe der Schrift, nicht seine eigene.

   Im Haus faerbt ICON_FARBE jedes Sinnbild, und `.ikon-rot` tut es mit `!important` — der
   Papierkorb steht dort als rot, was ueberall sonst richtig ist. Auf einer bernsteinfarbenen
   Flaeche ist Rot auf Orange aber kaum zu lesen. Das `!important` hier ueberstimmt nicht die
   Regel des Hauses, es benennt ihre Ausnahme: ein Zeichen, das AUF einer Farbe liegt,
   gehoert der Schrift. */
body.kasse-body .kasse-bottom-actions #korbLeerenBtn .icon { color: #fff !important; }
/* Aufgeklappt: gefuellt und rot. Ein Umriss waere hier zu leise. */
body.kasse-body .kasse-bottom-actions #korbLeerenBtn.ist-storno {
    background: var(--djk-danger);
    border-color: var(--djk-danger);
    color: #fff;
}
/* Zwei Gesichter, eines davon sichtbar. Beide stehen im Markup, damit das Skript kein
   HTML bauen muss — gebautes HTML verliert beim naechsten Umbau als Erstes sein Zeichen. */
#korbLeerenBtn .korb-leeren-wort { display: none; }
#korbLeerenBtn.ist-storno .korb-leeren-zeichen { display: none; }
#korbLeerenBtn.ist-storno .korb-leeren-wort { display: inline; }
#korbLeerenBtn .icon { width: 20px; height: 20px; }

/* ===== Kein Strich unter einem Knopf (22.08.2026) =====
   Vier Zeichen der Kopfleiste sind Links (Kueche, Bar, Kassenbericht, Reservierungen) — sie
   fuehren auf eine andere Seite, die uebrigen oeffnen ein Fenster. Aussehen sollen sie gleich.
   `a:hover { text-decoration: underline }` gilt im Haus fuer jeden Verweis; bei einem Zeichen,
   das wie ein Knopf gebaut ist, gehoert der Strich nicht hin — er gehoert zu Text, den man
   liest, nicht zu einer Flaeche, die man drueckt.

   Gilt fuer die ganze Reihe, nicht nur fuer den einen, ueber den der Wirt gefahren ist —
   sonst faellt es beim naechsten Verweis dort von vorn auf. */
a.kasse-tische-btn:hover,
a.kasse-tische-btn:focus { text-decoration: none; }

/* ===== Ein Punkt sagt „hier drin liegt etwas" (22.08.2026) =====
   Der Wirt hat ihn auf „Rotweine" gemalt. Ohne ihn muss man jede Kategorie einzeln aufmachen,
   um die eigene Auswahl wiederzufinden.

   Rot wie das Minus auf der Kachel: es ist dasselbe „hier ist etwas ausgewaehlt", nur eine
   Ebene hoeher. Der dunkle Ring darum haelt ihn auf jeder Kachelfarbe lesbar — die Kategorien
   traegt der Wirt selbst ein, und eine davon kann auch rot sein. */
.kategorie-tile, .warengruppe-chip { position: relative; }
/* EIN EIGENES ELEMENT, kein `::after`.

   Der erste Anlauf war ein `::after` — und hat den gelben Stern verdraengt, den
   `.kategorie-tile.ist-start-kat::after` dort zeichnet. Ein Pseudo-Element gibt es je
   Element nur EINMAL: wer es fuer eine neue Marke nimmt, nimmt es jemandem weg, und zwar
   still. Fuer etwas, das dazukommt, gehoert ein eigenes Element.

   Oben rechts — die beiden Sterne stehen unten rechts und bleiben unberuehrt. */
.kat-marke {
    position: absolute;
    top: 4px;
    right: 4px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    /* Ohne das Koerbchen steht nur noch eine Zahl darin — also dieselbe Form und dieselbe Groesse
       wie der gelbe Zaehler auf der Produkt-Kachel (.product-tile-badge). Zwei Zaehler auf
       demselben Bildschirm sollen nicht verschieden gross sein; die Farbe allein sagt schon, dass
       der eine der Kategorie gehoert und der andere dem Produkt.
       `padding` bleibt fuer den Fall, dass die Zahl zweistellig wird — dann waechst der Kreis zur
       Tablette, statt die Ziffern an den Rand zu druecken. */
    min-width: 22px;
    height: 22px;
    justify-content: center;
    padding: 0 5px;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 800;
    line-height: 1.35;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
    pointer-events: none;
}
/* Das Zeichen faerbt im Haus ICON_FARBE mit `!important` — auf roter Flaeche muss es der
   Schrift folgen, nicht sich selbst (dieselbe benannte Ausnahme wie am Leeren-Knopf). */
.kat-marke i { font-size: 0.72rem; color: #fff !important; }
.kat-marke-zahl { font-variant-numeric: tabular-nums; }

/* ===== Bezahlt, aber nicht angekommen (22.08.2026) =====
   Rot und laut. Alles andere auf dieser Seite ist Arbeit, die man der Reihe nach
   abarbeitet; das hier ist Geld eines Gastes, das beim Wirt liegt, ohne dass der Gast
   etwas dafuer bekommen hat. Es darf nicht aussehen wie eine Bestellung mehr. */
.panne-karte {
    margin: 0 0 14px;
    padding: 14px 16px;
    border: 2px solid var(--djk-danger);
    border-radius: 10px;
    background: rgba(239, 68, 68, 0.08);
}
.panne-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 6px;
}
.panne-marke {
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--djk-danger);
    color: #fff;
    font-size: 0.74rem;
    font-weight: 800;
    letter-spacing: 0.02em;
}
.panne-betrag { font-size: 1.25rem; font-weight: 800; }
.panne-gast { font-size: 0.9rem; opacity: 0.85; margin-bottom: 8px; }
.panne-korb { margin: 0 0 8px; padding-left: 20px; font-size: 0.92rem; }
.panne-hinweis { font-size: 0.85rem; opacity: 0.8; margin-bottom: 8px; }
.panne-hinweis code { font-family: ui-monospace, monospace; }

/* source/style_css/490_daily_revenue_corrections.css - style.css part 73 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ===== Tagesumsatz: heute, offen, berichtigt (22.08.2026) =====
   Der Wirt: „нужно понятно сделать, строго сегодняшнее показать".

   Die kleine Rechnung unter der grossen Zahl ist der Kern — sie zeigt, dass nichts versteckt
   wurde: heute verkauft + Berichtigung = im Buch. */
.umsatz-rechnung {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--djk-border);
    font-size: 0.9rem;
}
.umsatz-rechnung > div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 3px 0;
}
/* Grau, nicht rot: eine Berichtigung ist kein Fehler mehr, sondern seine Behebung. */
.umsatz-rechnung .ist-berichtigung { color: var(--djk-gray, #94a3b8); }
.umsatz-rechnung .ist-ergebnis {
    margin-top: 4px;
    padding-top: 6px;
    border-top: 1px solid var(--djk-border);
    font-weight: 800;
}
/* Offen = gelb: es fehlt noch etwas. */
.umsatz-block-offen { border-color: var(--djk-yellow); }
.umsatz-block-offen .umsatz-gross { color: var(--djk-yellow); }
/* Berichtigt = grau: erledigt, nur nicht von heute. */
.umsatz-block-berichtigung .umsatz-gross { color: var(--djk-gray, #94a3b8); }
/* Storniert = rot: es war da und ist wieder weg. Dieselbe Farbe wie das Minus davor,
   damit niemand die Zahl fuer eine Einnahme haelt. (23.08.2026) */
.umsatz-block-storno { border-color: var(--djk-red, #dc2626); }
.umsatz-block-storno .umsatz-gross { color: var(--djk-red, #dc2626); }
.umsatz-block-storno .umsatz-block-titel { color: var(--djk-red, #dc2626); }

/* Welcher Zeitraum gemeint ist — der Tag der Kasse endet mit dem Z, nicht um Mitternacht.
   Wer das nicht weiss, sucht sonst nach fehlenden Zahlen. (22.08.2026) */
.umsatz-zeitraum {
    margin: 0 0 12px;
    font-size: 0.82rem;
    opacity: 0.7;
}

/* Was vor der Eroeffnung gebucht wurde und trotzdem in diesen Z kommt (22.08.2026).
   Eine Zeile, kein Block: der Wirt will den Tag sehen. Weglassen darf man sie nicht — sonst
   waere die Lade abends um ihren Bar-Anteil zu voll und nichts auf dem Schirm erklaerte es. */
.umsatz-vortag {
    margin: 4px 0 14px;
    padding: 10px 12px;
    border-left: 3px solid var(--djk-border);
    font-size: 0.82rem;
    opacity: 0.75;
    line-height: 1.5;
}

/* Die Zerlegung des Bargelds beim Abschluss (22.08.2026): eine Berichtigung frueherer
   Tage steht im bar_soll, lag aber nie in der Lade. Klein und grau — sie erklaert nur. */
.z-zeile.z-zeile-klein {
    font-size: 0.82rem;
    opacity: 0.7;
}

/*
 * DAS WUNSCH-FENSTER (23.08.2026)
 *
 * Der Wirt: „очень монотонно" — eine Reihe grauer Kaesten, in der alles gleich aussah.
 *
 * Farbe hier hat Bedeutung, sie ist kein Schmuck: GELB heisst „noch nichts gegeben", GRUEN
 * „steht schon am Tisch" (mit der Zahl daneben), und am Stepper sagen Rot und Gruen, wohin
 * der Daumen geht. Wer das Fenster kennt, muss nicht mehr lesen, sondern nur noch sehen.
 */
/* Die Zeile im Beigaben-Fenster, wenn es zu diesen Gerichten nichts zum Dazufragen gibt.
   Sie steht IM Fenster statt als Meldung am Rand: der Kellner soll sie zusammen mit Tisch
   und Gerichtezahl lesen (31.08.2026, auf Wunsch des Wirts). */
.beigabe-leer {
    padding: 18px 6px;
    text-align: center;
    color: var(--djk-gray);
    font-size: 0.95rem;
    line-height: 1.5;
}
.beigabe-zeile {
    grid-template-columns: auto 1fr auto auto;
    /* Darf schrumpfen: als Kind eines Grids waere sie sonst nie schmaler als ihr
       Inhalt und schoebe eine quere Leiste unter die Liste. */
    min-width: 0;
    gap: 10px;
    padding: 10px 12px;
    margin-bottom: 8px;
    border: 1px solid var(--djk-border);
    border-left: 4px solid var(--djk-yellow);
    border-radius: 10px;
    background: var(--djk-black-card);
}
.beigabe-zeile.schon-da { border-left-color: var(--djk-success); }
.beigabe-zeichen { display: flex; align-items: center; color: var(--djk-yellow); }
.beigabe-zeichen svg { width: 22px; height: 22px; }
.beigabe-zeile.schon-da .beigabe-zeichen { color: var(--djk-success); }
/* Und dasselbe fuer die mittlere Spalte — sonst gibt die Zeile die Breite nur weiter.
   OHNE `overflow-wrap: anywhere`: das brach „Ouzo" zu „Ou/zo". Reicht der Platz nicht,
   wird gestapelt (siehe unten), nicht das Wort zerschnitten. */
.beigabe-name { font-weight: 700; min-width: 0; }

/*
 * Schmales Geraet: Name oben, Bedienung darunter ueber die ganze Breite.
 *
 * Der Stepper ist mit seinen drei Kaesten unverhandelbar breit (3 x 44px sind Fingermass,
 * kein Geschmack). Bleibt „Buchung" daneben, hat der Name keine 70px mehr — und genau da
 * bricht das Wort. Zwei Reihen kosten etwas Hoehe und geben beiden ihren Platz.
 */
@media (max-width: 560px) {
    .beigabe-zeile { grid-template-columns: auto 1fr; row-gap: 12px; }
    .beigabe-zeile .bg-stepper { grid-column: 1; justify-self: start; }
    .beigabe-zeile .beigabe-senden { grid-column: 2; justify-self: stretch; }
}
/* Wie viele schon stehen — beantwortet „habe ich das schon gemacht?" ohne ein Wort. */
.beigabe-schon {
    margin-left: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 800;
    background: rgba(34, 197, 94, .18);
    color: var(--djk-success);
}
.bg-stepper .bg-minus { color: var(--djk-red); }
.bg-stepper .bg-plus { color: var(--djk-success); }
.bg-stepper .bg-minus:active { background: rgba(239, 68, 68, .22); }
.bg-stepper .bg-plus:active { background: rgba(34, 197, 94, .22); }

/*
 * DAS AUSWAHLFENSTER: FARBE MIT BEDEUTUNG (23.08.2026)
 *
 * Der Wirt: „очень монотонно" — jeder Knopf derselbe graue Kasten, und der Blick musste jedes
 * Wort lesen. Die Farben hier sind kein Schmuck, sie sagen jede etwas Eigenes:
 *
 *     gruen    was das Haus dazugibt      (Beigabe — mit dem Geschenk-Zeichen)
 *     blau     was der Gast gewaehlt hat  (Zusammenfassung „Mit Pommes")
 *     gelb     was Geld kostet            (freier Posten, „Kueche Divers")
 *     kupfer   was das Haus verlaesst     (Zum Mitnehmen)
 *
 * Dieselbe Sprache wie im Wunsch-Fenster: dort ist eine Beigabe ebenfalls gruen und traegt
 * dasselbe Zeichen. Zwei Fenster ueber dieselbe Sache duerfen sie nicht verschieden faerben.
 */
/* Die Beigabe war bis zum 28.08.2026 eine Taste neben „Kueche Divers". Jetzt ist sie eine
   Zeile in der Extra-Liste unter „Ohne" — die Regeln dafuer stehen bei .extra-zeile-beigabe. */


/*
 * DIE FARBE GILT AUCH IM RUHEZUSTAND (28.08.2026).
 *
 * Der Wirt: *„эти кнопки сделай все разноцветные."* Bisher trugen die Knoepfe ihre Farbe erst,
 * WENN sie gewaehlt waren — vorher standen sie alle grau nebeneinander, und der Blick musste
 * jedes Wort lesen. Die Bedeutung der Farben aendert sich dabei nicht (siehe oben): sie tritt
 * nur frueher auf. Der Unterschied zwischen „kann ich" und „habe ich" bleibt trotzdem lesbar —
 * gewaehlt kommt zusaetzlich der farbige Grund dazu.
 */
.praefix-btn[data-divers] { border-color: var(--djk-yellow); color: var(--djk-yellow); }
/* „Zum Mitnehmen" — es geht aus dem Haus. Kupfer, damit es sich von jeder Wahl im Haus abhebt. */
.praefix-btn[data-schalter="pickerMitnehmen"] { border-color: var(--djk-copper); color: var(--djk-copper); }
/*
 * „Als Vorspeise" — eine Ansage an die Kueche ueber die REIHENFOLGE, nicht ueber die Speise.
 * Deshalb die Uhr als Zeichen und eine eigene Farbe: neben dem Kupfer von „Zum Mitnehmen" muss
 * man die beiden auf einen Blick auseinanderhalten koennen, sie stehen jetzt nebeneinander.
 */
.praefix-btn[data-schalter="pickerVorspeise"] { border-color: var(--djk-blue); color: var(--djk-blue); }

/*
 * GEWAEHLT = GRUEN MIT HAKEN (28.08.2026).
 *
 * Der Wirt, nachdem die Knoepfe ihre Farbe schon im Ruhezustand bekamen: *„когда они выбраны
 * или нет — не понятно разница. Можно когда она выбрано зелёной сделать и иконку как галочка."*
 *
 * Er hat recht, und der Fehler war meiner: solange die Farbe erst BEIM Waehlen kam, war sie
 * selbst das Zeichen. Jetzt traegt der Knopf sie immer — und der Unterschied lag nur noch in
 * einem blassen Hintergrund, den man auf einem Telefon in der Kueche nicht sieht.
 *
 * Die beiden Fragen sind seitdem getrennt, und so bleiben sie:
 *
 *     die FARBE sagt, WAS es ist   — gelb Geld, kupfer aus dem Haus (siehe oben)
 *     GRUEN + HAKEN sagt, DASS es AN ist
 *
 * Der Haken kommt aus dem Stil und nicht aus dem Markup: die Klasse `active` wird zur Laufzeit
 * umgeschaltet (`classList.toggle`), ein Zeichen im HTML muesste dabei jedes Mal mitgezogen
 * werden. So folgt es von allein.
 */
.praefix-btn[data-divers].active,
.praefix-btn[data-schalter].active {
    border-color: var(--djk-success);
    color: var(--djk-success);
    background: rgba(34, 197, 94, .16);
}
/*
 * Der Haken TRITT AN DIE STELLE des Zeichens, er stellt sich nicht daneben.
 *
 * Ein zweites Zeichen am Ende machte den Knopf breiter und liess das Auge zweimal suchen —
 * einmal links nach dem Zeichen, einmal rechts nach dem Haken. Getauscht bleibt alles an
 * seinem Platz, und die Breite des Knopfes aendert sich nicht: beide Zeichen sind gleich gross.
 */
.knopf-zeichen,
.knopf-zeichen-haken { display: inline-flex; align-items: center; }
.knopf-zeichen-haken { display: none; }
.praefix-btn.active .knopf-zeichen { display: none; }
.praefix-btn.active .knopf-zeichen-haken { display: inline-flex; }

/*
 * Dasselbe fuer das WORT: manche Schalter heissen in beiden Zustaenden anders, weil sie eine
 * Entscheidung benennen und keinen Handgriff — „Als Hauptspeise bestellen" / „Als Vorspeise
 * bestellen". Wer nur einen Text hat, laesst beide Spannen einfach weg; dann aendert sich nichts.
 */
.knopf-wort-an { display: none; }
.praefix-btn.active .knopf-wort { display: none; }
.praefix-btn.active .knopf-wort-an { display: inline; }

/*
 * DIE WORTPLAETTCHEN — jedes seine eigene Farbe (28.08.2026).
 *
 * Sie bleiben WERKZEUG und nicht Zustand: der gestrichelte Rand sagt das weiter, und daran
 * aendert sich nichts. Aber grau nebeneinander waren fuenf gleiche Kaesten, in denen man jedes
 * Wort einzeln lesen musste — „Mit Statt Nur nicht Mehr" unterscheiden sich ohnehin nur um
 * wenige Buchstaben.
 *
 * Gefaerbt wird nach der STELLE, nicht nach dem Wort: die Woerter kommen aus der Verwaltung und
 * heissen in einem anderen Haus anders. Fuenf Farben laufen um; ein sechstes Wort faengt wieder
 * vorn an, und das ist besser als ein sechstes Grau.
 */
.praefix-btn.praefix-word-chip {
    background: var(--djk-black-soft);
    border-style: dashed;
}
.praefix-btn.praefix-word-chip:nth-child(5n+1) { color: var(--djk-blue-light); border-color: var(--djk-blue-light); }
.praefix-btn.praefix-word-chip:nth-child(5n+2) { color: var(--djk-success);    border-color: var(--djk-success); }
.praefix-btn.praefix-word-chip:nth-child(5n+3) { color: var(--djk-copper);     border-color: var(--djk-copper); }
.praefix-btn.praefix-word-chip:nth-child(5n+4) { color: var(--djk-danger);     border-color: var(--djk-danger); }
.praefix-btn.praefix-word-chip:nth-child(5n+5) { color: var(--djk-yellow);     border-color: var(--djk-yellow); }
/* Beim Antippen kurz voll ausgefuellt — eine Rueckmeldung, dass das Wort im Kommentar steht. */
.praefix-btn.praefix-word-chip:active {
    color: var(--djk-white);
    border-style: solid;
}

/* Ist nichts gewaehlt, soll der leere Behaelter auch keinen Platz halten. */
#extraSummaryWrap:empty { display: none; }

/*
 * DIE WAHL ALS SATZ, UND ZEICHEN AUF DEN KNOEPFEN (23.08.2026)
 *
 * „Mit Pommes · Ohne Zwiebeln" steht unter dem Namen des Gerichts wie eine Unterzeile: blau
 * (die Farbe der getroffenen Entscheidung), aber ohne Rahmen. Ein Rahmen haette daraus wieder
 * einen Knopf gemacht, und es gibt hier nichts zu druecken.
 */
/*
 * Name und Auswahl an derselben Grundlinie: „Gyros  Mit Pommes".
 *
 * `baseline` und nicht `center`: die beiden Schriften sind verschieden gross, und nur an der
 * Grundlinie sitzen sie so, wie ein Mensch sie schreiben wuerde. `flex-wrap`, damit eine lange
 * Auswahl auf dem Telefon umbricht statt den Namen zusammenzuquetschen.
 */
.picker-titelzeile {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
    margin-bottom: 12px;
    /*
     * PLATZ FUER DAS KREUZ (28.08.2026).
     *
     * Das Schliessen-Kreuz sitzt `position: absolute` oben rechts — es nimmt in der Zeile also
     * keinen Platz weg, und die Auswahl lief darunter hindurch. Beim Wirt stand
     * „Ohne Tzatzki · Ohne Zwiebeln · Mit Pommes" quer durch das Kreuz.
     *
     * Der Abstand hier haelt die Zeile davon fern; wird die Auswahl laenger, bricht sie in die
     * naechste Zeile um (dort ist das Kreuz nicht mehr im Weg) — und das ist richtig so: die
     * Auskunft abzuschneiden waere schlimmer, als eine Zeile hoeher zu werden.
     */
    padding-right: 56px;
}
.picker-titelzeile h3 { margin: 0; }

.picker-wahl-text {
    margin: 0;
    color: var(--djk-blue-light);
    font-size: .9rem;
    font-weight: 600;
    line-height: 1.4;
}

/* Die Reihe ueber „Kueche Divers": was zum Gericht dazukommt. */

/* Zeichen und Wort auf einem Knopf brauchen dieselbe Mittellinie. */
.praefix-btn[data-schalter],
.praefix-btn[data-divers] { display: inline-flex; align-items: center; gap: 6px; }
.praefix-btn[data-schalter] svg,
.praefix-btn[data-divers] svg { width: 16px; height: 16px; }


/* ==============================================================================================
   ECKIG WAR ES EINEN TAG LANG (27.08.2026)
   ==============================================================================================
   Hier stand eine Regel, die dem ganzen Kassen-Bildschirm `border-radius: 0` gab — auf Ansage.
   Der Wirt hat sie sich angesehen, sie in den Entwicklerwerkzeugen wieder ABGESCHALTET und ein
   Bild vom Ergebnis geschickt: mit Rundungen. Also ist sie hier wieder weg.

   Sie steht nur als Notiz da, damit niemand sie ein zweites Mal erfindet — und damit klar ist,
   dass die Rundungen Absicht sind. Zurueckholen waere eine Zeile:
     body.kasse-body *:not([class*="badge"]):not([class*="spinner"]):not(.product-tile-minus-btn)
                     :not(.toggle-switch):not(.toggle-switch-track) { border-radius: 0 !important; }
   ============================================================================================== */

/* ==============================================================================================
   KUECHE / BAR OBEN AUF DEM BRETT (27.08.2026)
   ==============================================================================================
   Der Wirt hat die beiden Punkte unten in der Leiste eingekringelt und einen Strich nach oben
   gezogen. Am Pass wechselt man zwischen diesen Brettern staendig — und der untere Rand eines
   Tresen-Bildschirms ist genau die Stelle, an die die Hand nicht faehrt.

   Das Aussehen borgt sich beim Bestellstopp-Schalter daneben (Tablettenform, gleiche Hoehe,
   gleiche Randfarbe): zwei Dinge in derselben Zeile sollen nicht wie aus zwei Programmen
   aussehen. `margin-left: auto` steht hier UND dort — dann nimmt der erste den freien Platz und
   beide stehen rechts nebeneinander, in der Reihenfolge des Markups.
   ============================================================================================== */
.board-stationen {
    margin-left: auto;
    display: inline-flex;
    align-items: stretch;
    gap: 4px;
    padding: 4px;
    background: var(--djk-black-soft);
    border: 1px solid var(--djk-border);
    border-radius: 999px;
}
.board-station {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 14px;
    border-radius: 999px;
    color: var(--djk-white);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 700;
    white-space: nowrap;
    transition: background var(--transition), color var(--transition);
}
.board-station svg,
.board-station i { width: 18px; height: 18px; font-size: 18px; }

.board-station:hover { background: rgba(255, 255, 255, 0.07); }

/* Wo man STEHT, ist heller ausgelegt — nicht farbig: die Farbe traegt hier schon das Zeichen
   (ICON_FARBE), und zwei Farben nebeneinander machen aus einem Wegweiser eine Ampel. */
.board-station.ist-hier {
    background: var(--djk-white);
    color: var(--djk-black);
}
.board-station.ist-hier svg,
.board-station.ist-hier i { filter: brightness(0.35); }

/* Auf schmalen Schirmen zaehlt der Platz: dann bleibt das Zeichen, das Wort geht. Wer am Pass
   steht, kennt Topf und Krug ohnehin. */
@media (max-width: 520px) {
    .board-station span { display: none; }
    .board-station { padding: 5px 11px; }
}

/* ==============================================================================================
   DIE STERNE STEHEN WIEDER UNTEN RECHTS (27.08.2026)
   ==============================================================================================
   Sie waren einen Nachmittag lang oben links — auf Ansage. Der Wirt hat es sich angesehen und
   zurueckgenommen, und man sieht auf seinem Bild sofort, warum: die Kategorie-Kacheln sind nicht
   hoch, der Name beginnt oben, und zwei Sterne davor schoben ihn nach rechts weg. Bei „Bier"
   stand am Ende der Name neben seinen eigenen Marken statt darueber.

   Unten rechts ist der Platz, an dem sie niemanden stoeren: der Name endet darueber, und die
   Kachel ist dort ohnehin leer. Die alten Regeln (weiter oben in dieser Datei) gelten damit
   wieder unveraendert — hier steht nur noch die Notiz, damit niemand den Weg ein zweites Mal
   geht.

   Auf den TISCHGRUPPEN-Plaettchen bleibt der Stern links: dort sitzt seit heute die Zahl der
   besetzten Tische in der rechten Ecke, und zwei Marken auf demselben Fleck waeren eine zu viel.
   ============================================================================================== */

/* source/style_css/495_daily_revenue_corrections_continued.css - style.css: daily revenue corrections continued, part 74 of 78 (built by werkzeuge/parts_build.php) */
/* ==============================================================================================
   DIE TISCHGRUPPEN ZEIGEN, WIE VIELE TISCHE BESETZT SIND (27.08.2026)
   ==============================================================================================
   „на столах тоже должно показывать сколько столов занято." Dieselbe Sprache wie bei den
   Produkt-Kategorien: eine Zahl im Kreis. Wer die Tischwahl öffnet, sieht damit ohne einen
   einzigen Klick, wo etwas läuft — und muss nicht durch alle Gruppen blättern, um es
   herauszufinden.

   Der Stern wandert hier ebenfalls nach links, damit die Zahl die rechte Ecke bekommt: zwei
   Marken auf demselben Fleck wären eine zu viel.
   ============================================================================================== */
.tisch-kat-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.tisch-kat-chip.ist-start-kat { padding-right: 16px; padding-left: 26px; }
.tisch-kat-chip.ist-start-kat::after {
    top: 3px;
    left: 6px;
    right: auto;
}

/* Der Zähler steht IM Fluss, nicht darüber: ein Plättchen ist nur so hoch wie seine Schrift, und
   ein aufgesetztes Zeichen sässe dort halb draussen. So wächst das Plättchen einfach mit. */
.tisch-kat-chip-badge {
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--kasse-badge-grund, var(--djk-yellow));
    color: var(--kasse-badge-schrift, var(--djk-black));
    font-size: 0.72rem;
    font-weight: 800;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

/* source/style_css/500_product_search_keyboard.css - style.css part 75 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==============================================================================================
   DIE EIGENE TASTATUR AN DER PRODUKTSUCHE (27.08.2026)
   ==============================================================================================
   Sie tritt auf dem Telefon an die Stelle der Geräte-Tastatur (siehe kasse.js). Deshalb sitzt sie
   UNTEN: von dort kommt eine Tastatur, dort hält die Hand das Gerät, und die Kacheln bleiben oben
   sichtbar — man tippt und sieht dabei, wie sich das Raster verkleinert.

   Sie legt sich über die untere Leiste (Buchen/Bezahlen), genau wie es die Geräte-Tastatur täte.
   Wer sucht, bezahlt gerade nicht.

   Ab 1200px gibt es sie nicht — dort steht der grosse Ziffernblock ohnehin dauerhaft rechts.
   ============================================================================================== */
.suche-pad {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    display: none;
    flex-direction: column;
    gap: 6px;
    padding: 8px 6px calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--djk-black-soft, #1b1f24);
    border-top: 1px solid var(--djk-border, #2b3138);
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.45);
}
.suche-pad.ist-offen { display: flex; }

/* Der Ziffernblock nimmt die VOLLE Breite — auf Ansage.
   Er stand hier eine Fassung lang mittig und schmal (340px), damit er wie ein Wählfeld aussieht.
   Der Wirt hat die leeren Streifen links und rechts gesehen und sie weggeschickt, und er hat
   recht: die Ränder eines Kassenbildschirms sind kein Zierrat, sondern Fläche, die getroffen
   werden will. Drei Tasten über die ganze Breite sind grosse Tasten — und eine grosse Taste ist
   im Betrieb mehr wert als eine hübsche Form. */

.suche-pad-reihe { display: flex; gap: 5px; }

.suche-pad button {
    /* Alle Tasten einer Reihe gleich breit — `min-width: 0` muss dazu, sonst weigert sich eine
       Flex-Zelle, unter ihren Inhalt zu schrumpfen, und die längste Reihe läuft über den Rand. */
    flex: 1 1 0;
    min-width: 0;
    padding: 12px 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--djk-white, #e8edf2);
    background: var(--djk-black-card, #232830);
    border: 1px solid var(--djk-border, #2b3138);
    border-radius: 8px;
    cursor: pointer;
    /* Kein Warten auf den Doppeltipp-Zoom — am Pass zählt jede Zehntelsekunde. */
    touch-action: manipulation;
    -webkit-user-select: none;
    user-select: none;
    /*
     * WEICH STATT HART (auf Ansage: „нужна плавность, очень грубо").
     *
     * Vorher sprang die Farbe ohne Übergang um, was sich wie ein Ruck anfühlte. Jetzt sinkt die
     * Taste beim Drücken ein wenig ein und die Farbe wandert dorthin — 90 ms hinunter, 160 ms
     * zurück. Das Hinunter ist bewusst schneller: es soll der Berührung folgen, nicht ihr
     * hinterherlaufen; das Zurück darf sich Zeit lassen, dort sieht man es als Nachklang.
     */
    transition: background 160ms ease, border-color 160ms ease, transform 160ms ease;
}
.suche-pad button:active {
    background: var(--djk-blue, #3b82f6);
    border-color: var(--djk-blue, #3b82f6);
    transform: scale(0.93);
    transition-duration: 90ms;
}

/* Der Ziffernblock darf grössere Tasten haben — er hat ja nur drei Spalten. */
.suche-pad.ist-zahlen button { padding: 16px 0; font-size: 1.3rem; font-weight: 700; }

/* Die Umschalttaste (ABC / 123) hebt sich ab: sie ist kein Zeichen, sondern ein Weg. */
.suche-pad-um {
    font-size: 0.9rem !important;
    font-weight: 700 !important;
    color: var(--djk-blue-light, #93c5fd) !important;
}

/* ----------------------------------------------------------------------------------------------
   DIE BUCHSTABEN SEHEN AUS WIE AUF DER TASTATUR DES TELEFONS (Bild vom Wirt)
   ----------------------------------------------------------------------------------------------
   Hellgraue Tasten mit weicher Ecke auf dunklem Grund, weisse Schrift, und die dritte Reihe
   endet mit einer breiten Ruecktaste. Warum nachgebaut und nicht eigen erfunden: eine Tastatur
   ist das Bedienelement, das jeder Mensch am besten kennt. Jede Abweichung davon kostet den
   Kellner eine Zehntelsekunde — und die hat er im Betrieb nicht.
   ---------------------------------------------------------------------------------------------- */
.suche-pad button {
    background: rgba(255, 255, 255, 0.16);
    border-color: transparent;
}
.suche-pad button:active {
    background: var(--djk-blue, #3b82f6);
    border-color: var(--djk-blue, #3b82f6);
}

/* Die Ruecktaste am Ende der kurzen Reihe ist breiter — wie auf dem Bild. */
.suche-pad .suche-pad-breit { flex-grow: 1.7; }

/* Die dritte Reihe hat weniger Tasten; auf einer echten Tastatur sitzt sie deshalb eingerückt.
   Ohne das stünden ihre Tasten breiter da als die darüber, und das Auge liest es als Fehler. */
.suche-pad-reihe--b2 { padding: 0 4%; }

/* ----------------------------------------------------------------------------------------------
   DAS MIKROFON
   ----------------------------------------------------------------------------------------------
   Es erscheint nur, wo der Browser wirklich zuhören kann (siehe kasse.js) — eine Taste, die beim
   Antippen schweigt, probiert man sonst jedes Mal wieder.

   Während es hört, pulsiert es rot. Das ist kein Schmuck: wer nicht sieht, dass aufgenommen wird,
   spricht in ein Gerät, das längst wieder still ist.
   ---------------------------------------------------------------------------------------------- */
.suche-pad .suche-pad-mikro {
    flex-grow: 0.8;
    font-size: 1.15rem;
}
.suche-pad .suche-pad-mikro.ist-an {
    background: #ef4444;
    border-color: #ef4444;
    animation: mikroPuls 1.1s ease-in-out infinite;
}
@keyframes mikroPuls {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
}
@media (prefers-reduced-motion: reduce) {
    .suche-pad .suche-pad-mikro.ist-an { animation: none; }
}
/* MIT `.suche-pad` davor — gemessen am 27.08.2026: ohne den Vorfahren wiegt `.suche-pad-fertig`
   (0,1,0) weniger als `.suche-pad button` (0,1,1), und das Häkchen blieb grau statt grün, der
   Zwischenraum blieb schmal. Zwei Zeilen, die aussahen, als täten sie etwas, und nichts taten. */
.suche-pad .suche-pad-space { flex-grow: 4; }
.suche-pad .suche-pad-fertig {
    color: var(--djk-black, #10151a);
    background: var(--djk-green, #34d399);
    border-color: var(--djk-green, #34d399);
    font-weight: 800;
}
.suche-pad-reihe--tasten button { font-size: 0.95rem; padding: 12px 0; }

/* Sehr schmale Geräte: elf Tasten in einer Reihe brauchen jeden Punkt. */
@media (max-width: 380px) {
    .suche-pad button { padding: 10px 0; font-size: 0.95rem; }
    .suche-pad-reihe { gap: 4px; }
}

/* Wer Bewegung nicht mag, bekommt nur die Farbe. */
@media (prefers-reduced-motion: reduce) {
    .suche-pad button { transition: background 120ms ease; }
    .suche-pad button:active { transform: none; }
}

@media (min-width: 1200px) {
    .suche-pad { display: none !important; }
}


/* ----------------------------------------------------------------------------------------------
   DER TASTATUR-UMSCHALTER IN DER SUCHLEISTE (27.08.2026)
   ----------------------------------------------------------------------------------------------
   Er steht LINKS vom ✕, also weiter innen, und ist immer da — egal welche Tastatur gerade oben
   ist. Stünde er in unserer eigenen Tastatur, käme man nach dem Umschalten nicht mehr zurück.

   Ist die Geräte-Tastatur gewählt, leuchtet er: ein Zustand, den man nicht sieht, sucht man beim
   nächsten Mal in der falschen Ecke.
   ---------------------------------------------------------------------------------------------- */
.kasse-search-input .tastatur-wechsel { right: 38px; }
.kasse-search-input.has-toggle input { padding-right: 74px; }
.tastatur-wechsel.ist-geraet { color: var(--djk-yellow); opacity: 1; }


/* ==============================================================================================
   BEI EINER SUCHE STEHT DIE KATEGORIE AUF DER KACHEL (27.08.2026)
   ==============================================================================================
   Die Textsuche geht ueber alle Kategorien. "#142 Pita Gyro gerollt" neben "#214 Pizza Hawai" --
   ohne einen Hinweis weiss niemand, aus welcher Ecke der Karte die beiden kommen.

   Gelesen wird `data-kat-name`, das jede Kachel ohnehin traegt. Damit braucht es keinen Abgleich
   ueber Kennungen und keine zweite Liste -- und nichts, was leer werden koennte. Der erste Anlauf
   blendete stattdessen die Spalte links zusammen; sie blieb ganz leer.

   NUR waehrend der Suche (`.zeigt-kategorie` am Raster): steht man in einer Kategorie, weiss man
   ohnehin, in welcher, und der Name unter jeder Kachel waere nur Rauschen.

   `[data-gesperrt="1"]` bleibt aussen vor -- dort traegt `::after` schon das Schloss.
   ============================================================================================== */
#productGrid.zeigt-kategorie .product-tile:not(.kategorie-tile):not([data-gesperrt="1"])::after {
    content: attr(data-kat-name);
    display: block;
    margin-top: auto;
    padding-top: 4px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    /* Gedaempft: die Kategorie ist die Einordnung, nicht die Ware. Wer sucht, liest zuerst
       Nummer und Namen. */
    opacity: 0.62;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    pointer-events: none;
}


/* Offene Mitglieds-Antraege in der Verwaltung (05.09.2026). Sie stehen ganz oben und sollen
   auffallen, ohne zu schreien: die Warnfarbe des Hauses als Kante, sonst die gewohnte Karte.
   Ist nichts offen, entsteht der Block gar nicht erst (siehe admin/dashboard.php). */
.admin-antraege {
    border: 1px solid var(--djk-border);
    border-left: 4px solid var(--djk-yellow);
    border-radius: 8px;
    padding: 14px 16px;
    margin-bottom: 18px;
}
.admin-antraege-titel { margin: 0 0 4px; font-size: 1rem; display: flex; align-items: center; gap: 8px; }
.admin-antraege-zahl {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 22px; height: 22px; padding: 0 6px;
    border-radius: 11px; background: var(--djk-yellow); color: #fff;
    font-size: 0.78rem; font-weight: 800;
}

/* Die Bitte um eine Bewertung im Bereich des Gastes (07.09.2026). Der Block reist als fertiges
   HTML zur Gast-Website (siehe includes/bewertung.php) — deshalb steht sein Stil HIER und nicht
   dort: die Website hat kein Git, und ein Stil, der mit dem Baustein wandert, kann nicht
   vergessen werden. */
.bewertung-bitte {
    margin-top: 18px;
    padding: 16px 18px;
    border: 1px solid var(--djk-border);
    border-radius: 14px;
    text-align: center;
}
.bewertung-bitte p { margin: 0 0 12px; font-weight: 600; }

/* =============================================================================================
 * NICHT ANGEKOMMEN — das Vollbild (07.09.2026)
 *
 * Es liegt ueber allem, auch ueber dem Ziffernblock und den Fenstern: eine Bestellung, von der
 * die Kueche nichts weiss, ist wichtiger als alles, was gerade sonst offen ist. Rot ist hier
 * kein Schmuck — es ist die einzige Stelle in der Kasse, an der ein ganzer Bildschirm warnt.
 * ========================================================================================== */
.nichtda-schirm {
    position: fixed;
    inset: 0;
    z-index: 6000;
    background: rgba(9, 11, 16, .94);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    overscroll-behavior: contain;
}
/* `hidden` verliert gegen `display: flex` — deshalb ausdruecklich (Falle vom 03.09.2026). */
.nichtda-schirm[hidden] { display: none; }
.nichtda-kasten {
    width: min(680px, 100%);
    max-height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--djk-black-card);
    border: 2px solid var(--djk-danger);
    border-radius: 16px;
    overflow: hidden;
}
.nichtda-kopf {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    background: rgba(239, 68, 68, .14);
    border-bottom: 1px solid var(--djk-border);
}
.nichtda-zeichen svg { width: 30px; height: 30px; color: var(--djk-danger); }
.nichtda-titel { font-size: 1.15rem; font-weight: 800; color: var(--djk-danger); }
.nichtda-lead { font-size: .84rem; color: var(--djk-gray); margin-top: 2px; }
.nichtda-liste { overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
.nichtda-fall {
    border: 1px solid var(--djk-border);
    border-left: 4px solid var(--djk-danger);
    border-radius: 12px;
    padding: 11px 12px;
    background: var(--djk-black-soft);
}
.nichtda-fall-kopf { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.nichtda-tisch { font-size: 1.05rem; font-weight: 800; }
.nichtda-station { font-weight: 700; color: var(--djk-yellow); }
.nichtda-zeit { margin-left: auto; color: var(--djk-gray); font-variant-numeric: tabular-nums; }
.nichtda-grund { font-size: .82rem; color: var(--djk-gray); margin-top: 3px; }
.nichtda-posten { margin: 8px 0 10px; padding-left: 18px; line-height: 1.5; }
.nichtda-posten li { margin-bottom: 2px; }
.nichtda-fuss {
    display: flex;
    gap: 10px;
    padding: 12px 14px;
    border-top: 1px solid var(--djk-border);
}
.nichtda-fuss .btn { flex: 1 1 auto; }
/* Solange es steht, rollt darunter nichts mehr. */
body.hat-nichtda { overflow: hidden; }

/* source/style_css/510_form_errors.css - style.css part 76 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==========================================================================================
   DAS ROTE FELD UND SEIN SATZ  (formular_pruefen.js, 08.09.2026)
   ==========================================================================================
   Steht HIER und nicht in admin_design.css: die Kasse laedt admin_design.css gar nicht
   (gemessen), und dort haette das JavaScript eine Klasse gesetzt, die nichts tut. Die
   Verwaltung laedt style.css ohnehin zuerst.
   ========================================================================================== */
.feld-fehler,
input.feld-fehler,
select.feld-fehler,
textarea.feld-fehler {
    border: 2px solid var(--djk-danger) !important;
    background: color-mix(in srgb, var(--djk-danger) 6%, var(--feld-grund, transparent));
}
.feld-fehler:focus { outline: 2px solid var(--djk-danger); outline-offset: 1px; }
.feld-fehler-text {
    margin-top: 4px;
    font-size: 0.78rem;
    line-height: 1.35;
    color: var(--djk-danger);
    min-width: 0;
}

/*
 * IN EINER REIHE BEKOMMT DER SATZ EINE EIGENE ZEILE.
 *
 * `meldungHin()` haengt den Satz als GESCHWISTER des Feldes ein. Steht das Feld in einem
 * `display:flex`-Formular (die Nachtrag-Zeile der Z-Berichte etwa), wird der Satz dort das
 * dritte Element DERSELBEN Reihe: er bekommt den Rest der Breite, bricht auf sechs Zeilen um
 * und schiebt die Tabellenspalte von 169 auf 268 Pixel auseinander. Gemessen.
 *
 * NUR IN REIHEN, nicht in Spalten. `admin_design.css` setzt `.ausgabe-felder label` auf
 * `flex-direction: column` — dort ist die Hauptachse senkrecht, und `flex-basis: 100%` hiess
 * dann „nimm die volle HOEHE": der Satz wurde 88 Pixel hoch statt 17 und lief ueber den Rand
 * (Fund des Pruefers, 08.09.2026). Deshalb hier ausdruecklich `flex-direction: row`.
 */
form:has(> .feld-fehler-text),
.field:has(> .feld-fehler-text),
label:has(> .feld-fehler-text) { flex-wrap: wrap; }

.feld-fehler-text { flex: 1 0 100%; }
/*
 * Die AUSNAHMEN sind namentlich genannt, weil CSS nicht fragen kann, ob der Elternteil eine
 * Reihe oder eine Spalte ist. Diese drei setzen `flex-direction: column` (admin_design.css
 * 1254, 1331, 1705) — dort heisst `flex-basis: 100%` „nimm die volle Hoehe", und der Satz wird
 * 88 Pixel hoch statt 17. Wer eine vierte Spalte baut, traegt sie hier ein.
 */
.ausgabe-felder label > .feld-fehler-text,
.ausgabe-steuer-zeile label > .feld-fehler-text,
.kb-monat label > .feld-fehler-text { flex: none; }
/*
 * Und im RASTER: `display:none` nimmt die Spur nicht weg, und `flex-basis` gilt dort gar
 * nicht — der Griff heisst `grid-column` (siehe PROJEKT.md, „Rasterspur bleibt stehen").
 */
.feld-fehler-text { grid-column: 1 / -1; }

/* Die Vorschau der Aktions-Mail (09.09.2026).
   Ein eigener Rahmen, weil darin fremdes Aussehen steckt: die Mail bringt eigene Farben und
   eigene Tabellen mit und soll die Verwaltung nicht anfassen duerfen. */
.mail-vorschau {
    width: 100%;
    height: 620px;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius-sm);
    background: #fff;
    display: block;
}
@media (max-width: 640px) {
    .mail-vorschau { height: 480px; }
}

/* Das Farbfeld der Aktions-Mail. Ein `input[type=color]` ueber die ganze Spaltenbreite sieht
   aus wie ein liegengebliebener Balken; als Feld ist es ein SCHALTER, kein Textfeld. Hoehe
   bleibt das eine Hausmass, damit es neben den Textfeldern nicht springt. */
.mail-farbfeld {
    width: 84px;
    height: var(--feld-hoehe, 43px);
    padding: 4px;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius-sm);
    background: var(--djk-white, #fff);
    cursor: pointer;
}

/* DREI ZEILEN IM TISCH-KNOPF — nur bei einer Mitglieder-Zeche (09.09.2026).

   Ansage des Wirts: oben, wie lange er schon da ist (wie auf der Tisch-Kachel), unten, was er
   schuldet. Die HOEHE des Knopfes bleibt 48px: an ihr haengt die gemessene Kopfhoehe der
   Kasse, und ein hoeherer Knopf schoebe alles darunter nach unten. Deshalb kleine Schrift und
   enge Zeilen statt mehr Platz.

   Am normalen Tisch bleibt alles, wie es war — die beiden Zusatzzeilen sind dort leer und
   nehmen mit `display:none` auch keine Zeile weg. */
.kasse-tische-stapel {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    min-width: 0;
    line-height: 1.05;
}
.kasse-tische-zeit,
.kasse-tische-schuld { display: none; }
.kasse-tische-btn#tischeBtn.has-mitglied .kasse-tische-zeit,
.kasse-tische-btn#tischeBtn.has-mitglied .kasse-tische-schuld {
    display: block;
    font-size: 0.6rem;
    line-height: 1;
    font-weight: 600;
    opacity: .82;
}
/*
 * DER KNOPF DARF NICHT WACHSEN — gemessen, nicht angenommen (09.09.2026).
 *
 * Erst hiess es hier im Kommentar, die Hoehe bleibe. Nachgemessen im Browser stimmte das
 * nicht: 56px am normalen Tisch, 61px auf einer Zeche, und damit rutschten Suchleiste
 * (78 -> 83) und Produktraster (149 -> 154) mit nach unten. Alles, was mit
 * `top: var(--kasse-kopf-h, 74px)` festgemacht ist, saesse dann fuenf Punkte zu hoch.
 *
 * Zwei falsche Faehrten, beide gemessen und wieder verworfen:
 *   `height: var(--kasse-bedien-h)` machte ihn 48 statt 56 — auf einer Zeche kleiner als
 *   sonst; und `min-height: 0` allein aenderte gar nichts.
 *
 * DIE URSACHE steht weiter oben: `.kasse-search-bar #tischeBtn { height: auto; align-self:
 * stretch }`. Der Knopf ist so hoch wie die REIHE, und die Reihe ist so hoch wie die
 * quadratischen Knoepfe daneben (max-width: 56px, aspect-ratio: 1). Sein Polster von 10px
 * oben und unten war fuer EINE Zeile gerechnet; drei Zeilen passen damit nicht in die 56 und
 * schieben die Reihe auf.
 *
 * Also weniger Polster statt kleinerer Schrift: 2px oben und unten lassen 48 Punkte fuer den
 * Inhalt, und die Reihe bleibt bei ihren 56. Nur auf einer Zeche — am normalen Tisch soll
 * die eine Zeile mittig in ihrem gewohnten Polster stehen.
 */
.kasse-tische-btn#tischeBtn.has-mitglied {
    padding-top: 2px;
    padding-bottom: 2px;
    overflow: hidden;
}
.kasse-tische-btn#tischeBtn.has-mitglied .kasse-tische-stapel {
    min-height: 0;
    overflow: hidden;
}
/* Leer heisst weg: ein Strich oder „0,00 €" waere eine Zeile, die nichts sagt. */
.kasse-tische-btn#tischeBtn.has-mitglied .kasse-tische-zeit:empty,
.kasse-tische-btn#tischeBtn.has-mitglied .kasse-tische-schuld:empty { display: none; }

/* Der Haken „öffentlich" in der Sparten-Tabelle (09.09.2026).
   Er steht in einer Zeile neben Eingabefeldern; ohne diese Regel bekäme er die Grundgrösse
   des Browsers und die Zeile wäre höher als die anderen. */
.sparte-oeffentlich { display: inline-flex; align-items: center; justify-content: center; }
.sparte-oeffentlich input { width: 18px; height: 18px; accent-color: var(--djk-yellow); }
.sparte-haken { display: flex; align-items: flex-start; gap: 10px; }
.sparte-haken input { width: 18px; height: 18px; margin-top: 3px; accent-color: var(--djk-yellow); }

/*
 * DIE WAHL „WIE EIN FREIER TISCH AUSSIEHT" IN DER VERWALTUNG (13.09.2026) — Verwaltung → Tische →
 * Ansicht. Jede Moeglichkeit zeigt einen Tisch mit denselben Klassen wie der Plan der Kasse.
 */
.tisch-frei-karte-box { max-width: 720px; margin-bottom: 14px; }
.tisch-frei-titel { margin: 0 0 4px; }
.tisch-frei-hinweis { margin-bottom: 12px; }
.tisch-frei-wahl { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-bottom: 14px; }
.tisch-frei-moeglichkeit {
    display: flex; flex-direction: column; gap: 8px; cursor: pointer;
    border: 2px solid var(--djk-border); border-radius: 12px; padding: 8px;
}
.tisch-frei-moeglichkeit:has(input:checked) { border-color: var(--djk-yellow); box-shadow: 0 0 0 2px var(--djk-yellow); }
.tisch-frei-moeglichkeit input { position: absolute; opacity: 0; pointer-events: none; }
.tisch-frei-moeglichkeit .tisch-frei-boden { display: block; margin: 0; padding: 6px; }
.tisch-frei-bild { display: block; width: 100%; height: auto; }
.tisch-frei-bild .tp-view-tisch-shape { cursor: pointer; }
.tisch-frei-name { font-weight: 700; text-align: center; }
.tisch-frei-eigen { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 4px 16px; align-items: start; margin-bottom: 14px; }
.tisch-frei-eigen input[type="range"] { width: 100%; accent-color: var(--djk-yellow); }
.tisch-frei-eigen-hinweis { grid-column: 1 / -1; margin: 0; }


/*
 * DER RESERVIERTE TISCH SPIELT MIT SEINER FARBE (18.09.2026, der Wirt).
 *
 * Solange ein Tisch heute noch Gäste erwartet (Reservierung „aktiv"/„unbestätigt") und frei
 * ist, wandert seine Fläche langsam durch sechs Farben — man sieht quer durch den Raum, dass
 * er gebucht ist. Die Klasse setzt kasse.js (`tisch-reserviert`) aus tische_list.php. Sobald
 * jemand sitzt oder die Gäste als „da" vermerkt sind, ist er wieder ein Tisch wie jeder.
 *
 * Alle sechs Töne tragen weisse Schrift (Kontrast ≥ 4,5). Die Animation schlägt jede
 * Farbwahl der Verwaltung (`data-tisch-frei`), ohne !important: eine laufende Animation
 * steht in der Kaskade über den normalen Regeln. Nur das Verlaufsbild der Kachel muss weg,
 * sonst läge es über der Farbe.
 */
@keyframes rv-farbspiel-fuellung {
    0%, 100% { fill: #6d28d9; stroke: #a78bfa; }
    16.6%    { fill: #1d4ed8; stroke: #93c5fd; }
    33.3%    { fill: #0e7490; stroke: #67e8f9; }
    50%      { fill: #047857; stroke: #6ee7b7; }
    66.6%    { fill: #b45309; stroke: #fcd34d; }
    83.3%    { fill: #be185d; stroke: #f9a8d4; }
}
@keyframes rv-farbspiel-kachel {
    0%, 100% { background-color: #6d28d9; border-color: #a78bfa; }
    16.6%    { background-color: #1d4ed8; border-color: #93c5fd; }
    33.3%    { background-color: #0e7490; border-color: #67e8f9; }
    50%      { background-color: #047857; border-color: #6ee7b7; }
    66.6%    { background-color: #b45309; border-color: #fcd34d; }
    83.3%    { background-color: #be185d; border-color: #f9a8d4; }
}
.tp-view-tisch.tisch-reserviert .tp-view-tisch-shape { animation: rv-farbspiel-fuellung 12s linear infinite; }
.tp-view-tisch.tisch-reserviert :is(.tp-view-tisch-label, .tp-view-tisch-sublabel) { fill: #ffffff; }
.tisch-tile.tisch-reserviert { background-image: none !important; animation: rv-farbspiel-kachel 12s linear infinite; }
.tisch-tile.tisch-reserviert :is(.product-tile-photo .icon, .product-tile-name, .tisch-tile-kat) { color: #ffffff; }
/* Wer Bewegung abgestellt hat, bekommt EINE feste Farbe — reserviert bleibt erkennbar. */
@media (prefers-reduced-motion: reduce) {
    .tp-view-tisch.tisch-reserviert .tp-view-tisch-shape { animation: none; fill: #6d28d9; stroke: #a78bfa; }
    .tisch-tile.tisch-reserviert { animation: none; background-color: #6d28d9; border-color: #a78bfa; }
}
/* Die Frage beim Öffnen: Uhrzeit und Name gross, damit man sie mit einem Blick hat. */
.rv-frage-wann { font-size: 1.6rem; font-weight: 800; margin: 4px 0 2px; }
.rv-frage-wer { font-size: 1.05rem; font-weight: 700; margin: 0 0 10px; }

/* ------------------------------------------------------------------------------------------
   TISCHVORSCHLAG (19.09.2026) — die Leiste oben in der Tischwahl, die Hervorhebung auf Plan
   und Kacheln, der Hinweis nach dem Selbst-Öffnen.

   Die Knöpfe sind GROSS und stehen in einer Reihe, die am Telefon waagerecht rollt statt
   umzubrechen: eine zweite Zeile schöbe den Plan nach unten, und der Plan ist die Hauptsache.
   Die Nummer liest man aus einem Meter, der Grund darunter ist die leise Auskunft.

   Farben nur aus den Variablen des Hauses (--djk-*): im dunklen Bild tauschen sie mit, und
   Rot bleibt, was es auf dem Tisch-Bildschirm heisst — Küche/Bar hat noch etwas.

   Das linke Polster setzt kasse.js (tischOverlayFussPolstern) — dieselbe Zahl wie beim
   Raster, sonst läge die Leiste unter der Säule der Tischgruppen.
   ------------------------------------------------------------------------------------------ */
.tv-leiste {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: -6px 0 12px;
    min-width: 0;
}
.tv-leiste[hidden] { display: none; }
.tv-leiste-titel {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--djk-gray);
}
.tv-leiste-knoepfe {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
    /* Am Ende der Reihe bleibt der Zug hier (19.09.2026): er reicht nicht an das Fenster
       weiter — dort hiesse dieselbe Bewegung „naechste Tischgruppe" (siehe Blaettern in kasse.js). */
    overscroll-behavior-x: contain;
}
.tv-leiste-knoepfe::-webkit-scrollbar { display: none; }
.tv-knopf {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 2px;
    min-width: 112px;
    max-width: 200px;
    min-height: 64px;
    padding: 8px 14px;
    border: 2px solid var(--djk-yellow);
    border-radius: var(--radius);
    background: var(--djk-black-card);
    color: var(--djk-white);
    font: inherit;
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
    transition: background var(--transition), transform var(--transition);
}
.tv-knopf:hover { background: var(--djk-black-soft); }
.tv-knopf:active { transform: scale(0.97); }
.tv-knopf:focus-visible { outline: 3px solid var(--djk-yellow-dark); outline-offset: 2px; }
.tv-knopf-nummer { font-size: 1.5rem; font-weight: 800; line-height: 1.1; }
.tv-knopf-grund {
    font-size: 0.78rem;
    color: var(--djk-gray);
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Leise hervorgehoben: ein gestrichelter Rahmen in der Akzentfarbe. Nicht gefuellt — die
   Fuellung gehoert dem Zustand des Tisches (frei / wartet / bereit / reserviert). */
div.tisch-tile.tisch-vorschlag {
    outline: 2px dashed var(--djk-yellow);
    outline-offset: 2px;
}
.tp-view-tisch.tisch-vorschlag .tp-view-tisch-shape {
    stroke: var(--djk-yellow);
    stroke-width: 4px;
    stroke-dasharray: 8 5;
}

/* Der Hinweis nach dem Selbst-Öffnen. `position: fixed`: der Körper ist eine Flex-Zeile, ein
   Kind im Fluss stellte sich neben die Kasse. Unten mittig, über dem sicheren Rand des
   Telefons, und über den Fenstern der Kasse (die Tischwahl selbst liegt darunter). */
.tv-hinweis {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    margin: 0 auto;
    z-index: 3000;
    display: flex;
    align-items: center;
    gap: 12px;
    width: fit-content;
    max-width: 560px;
    padding: 10px 10px 10px 16px;
    border-radius: var(--radius);
    background: var(--kasse-leiste);
    color: #ffffff;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.35);
    animation: tv-hinweis-ein 0.2s ease-out;
}
.tv-hinweis-text { font-weight: 700; min-width: 0; }
.tv-hinweis-knopf {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 16px;
    border: 0;
    border-radius: var(--radius);
    background: var(--djk-yellow-dark);
    color: #ffffff;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
}
@keyframes tv-hinweis-ein {
    from { opacity: 0; transform: translateY(12px); }
    to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .tv-hinweis { animation: none; }
    .tv-knopf { transition: none; }
}
@media (max-width: 480px) {
    .tv-knopf { min-width: 96px; padding: 8px 12px; }
    .tv-knopf-nummer { font-size: 1.35rem; }
    .tv-hinweis { flex-wrap: wrap; }
}

/* Die Verwaltung des Tischvorschlags (admin/tische.php → Ansicht & Rechte): drei Zeilen wie die
   Schalter-Zeilen darüber, nur mit einem Kreis statt eines Schiebers — es ist EINE Wahl aus drei. */
.tv-karte { max-width: 720px; margin-top: 14px; }
.tv-modus { cursor: pointer; }
.tv-modus .schalter-text { display: flex; flex-direction: column; gap: 2px; }
.tv-modus input[type="radio"] { flex: 0 0 auto; width: 22px; height: 22px; margin: 2px 0 0; accent-color: var(--djk-yellow); }
.tv-modus:has(input:checked) { border-color: var(--djk-yellow); }
.tv-zahlen-titel { margin: 20px 0 8px; font-size: 0.95rem; }
.tv-zahlen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 10px;
    margin: 0;
}
.tv-zahlen > div {
    padding: 10px 12px;
    border: 1px solid var(--djk-border);
    border-radius: var(--radius);
    background: var(--djk-black-card);
    min-width: 0;
}
.tv-zahlen dt { font-size: 0.78rem; color: var(--djk-gray); }
.tv-zahlen dd { margin: 2px 0 0; font-size: 1.35rem; font-weight: 800; }
/* Grundlage und Schwelle (19.09.2026): dieselben Zeilen wie die Stufe; darüber ein Satz, darunter
   bei jeder Schwelle die nachgerechneten Zahlen. „Stand jetzt" steht als Kasten über allem — er
   beantwortet die Frage, die den Wirt hierher bringt: warum hat sie nicht geöffnet? */
.tv-gruppe-hinweis { margin: 0 0 8px; }
.tv-schwelle-zahlen { font-variant-numeric: tabular-nums; }
.tv-status {
    margin: 0 0 14px;
    padding: 10px 12px;
    border: 1px solid var(--djk-border);
    border-left: 3px solid var(--djk-yellow);
    border-radius: var(--radius);
    background: var(--djk-black-card);
    font-size: 0.85rem;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

/* source/style_css/515_form_errors_continued.css - style.css: form errors continued, part 77 of 78 (built by werkzeuge/parts_build.php) */
/* ==========================================================================================
   DAS BAND DER VERANSTALTUNG auf den Seiten des Personals ausserhalb der Kasse (25.09.2026)
   ========================================================================================== */
.personal-veranst-band { padding: calc(8px + env(safe-area-inset-top, 0px)) 16px 0; }
.personal-veranst-band .kasse-veranstaltung-band { cursor: default; }
body.personal-body:has(.personal-veranst-band) .section[style*="safe-area-inset-top"] { padding-top: 12px !important; }

/* source/style_css/520_order_spike_table_animation.css - style.css part 78 of 78 (built by werkzeuge/parts_build.php; the order of the parts is the order of the rules) */
/* ==========================================================================================
   DER BONSPIESS AM BRETT (25.09.2026) - assets/js/brett_spiess.js
   ========================================================================================== */
.brett-spiess-knopf { position: relative; display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 0; color: var(--djk-gray, #cbd5e1); cursor: pointer; padding: 4px; }
.brett-spiess-svg { width: 46px; height: 46px; display: block; }
.brett-spiess-nav .brett-spiess-svg { width: 40px; height: 40px; }
.brett-spiess-zahl { position: absolute; top: -2px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px;
    border-radius: 10px; background: var(--djk-yellow, #f59e0b); color: #fff; font-size: 11px; font-weight: 800; line-height: 20px;
    text-align: center; box-sizing: border-box; }
.brett-spiess-zahl[hidden] { display: none; }
.brett-spiess-nav { flex: 0 0 56px !important; }
.brett-spiess-schwebend { position: fixed; right: max(18px, env(safe-area-inset-right, 0px)); bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    z-index: 70; width: 88px; height: 88px; border-radius: 22px; background: var(--djk-black, #1f2937); border: 1px solid var(--djk-border, #374151);
    box-shadow: 0 10px 24px rgba(0, 0, 0, .35); }
.brett-spiess-schwebend .brett-spiess-svg { width: 66px; height: 66px; }
@media (max-width: 780px) { .brett-spiess-schwebend { display: none; } }
@media (min-width: 781px) { .brett-spiess-nav { display: none !important; } }
@keyframes brettSpiessNicken { 0% { transform: translateY(0); } 30% { transform: translateY(5px) scale(1.08, .92); } 60% { transform: translateY(-2px); } 100% { transform: none; } }
.brett-spiess-nickt { animation: brettSpiessNicken .45s ease; }
.brett-spiess-flug { position: fixed !important; z-index: 9999; margin: 0 !important; pointer-events: none;
    transform-origin: 50% 50%; box-shadow: 0 12px 28px rgba(0, 0, 0, .45); overflow: hidden; }

.brett-spiess-vollbild { position: fixed; inset: 0; z-index: 10000; display: flex; flex-direction: column;
    background: var(--djk-black, #0f1115); color: var(--djk-text, #e5e7eb);
    padding: calc(12px + env(safe-area-inset-top, 0px)) 16px calc(12px + env(safe-area-inset-bottom, 0px)); }
.brett-spiess-vollbild[hidden] { display: none; }
html.brett-spiess-offen, html.brett-spiess-offen body { overflow: hidden; }
.brett-spiess-kopf { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.brett-spiess-kopf h2 { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 1.25rem; }
.brett-spiess-kopf .brett-spiess-svg { width: 30px; height: 30px; color: #cbd5e1; }
.brett-spiess-liste { flex: 1 1 auto; overflow-y: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
    gap: 12px; align-content: start; -webkit-overflow-scrolling: touch; }
.brett-spiess-zettel { background: #fffdf5; color: #111827; border-radius: 4px 4px 10px 10px; padding: 12px 14px 14px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .3); font-family: ui-monospace, "Courier New", monospace;
    border-top: 6px dashed #e5e7eb; }
.brett-spiess-zettel header { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; padding-bottom: 8px;
    margin-bottom: 8px; border-bottom: 1px dashed #9ca3af; }
/* Lesbar aus einem Schritt Abstand (25.09.2026): Tisch und Zeiten gross, Positionen wie auf dem Brett. */
.bsz-nr { display: inline-flex; align-items: center; justify-content: center; min-width: 30px; height: 30px; padding: 0 6px;
    border-radius: 999px; background: #111827; color: #fff; font-size: 1rem; font-weight: 800; }
.bsz-tisch { font-size: 1.6rem; font-weight: 800; }
.bsz-zeit { flex: 1 1 100%; font-size: 1.1rem; color: #1f2937; }
.bsz-zeit b { font-size: 1.3rem; }
.bsz-zeit i { color: #6b7280; font-style: normal; }
.bsz-wer { margin-left: auto; font-size: .95rem; color: #4b5563; }
.brett-spiess-zettel ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; font-size: 1.2rem; line-height: 1.35; }
.brett-spiess-zettel li small { display: block; margin-left: 28px; color: #4b5563; font-size: 1rem; }
.brett-spiess-zettel li em { display: block; margin-left: 28px; color: #b45309; font-style: normal; font-size: 1rem; }

/* Das Menue links unten (25.09.2026): gegenueber vom Spiess, dieselbe Form. */
.brett-aus-schwebend { position: fixed; left: max(18px, env(safe-area-inset-left, 0px)); bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    z-index: 70; width: 88px; height: 88px; border-radius: 22px; display: inline-flex; align-items: center; justify-content: center;
    background: var(--djk-black, #1f2937); border: 1px solid var(--djk-border, #374151); color: var(--djk-gray, #cbd5e1);
    box-shadow: 0 10px 24px rgba(0, 0, 0, .35); cursor: pointer; }
.brett-aus-schwebend .icon { width: 40px; height: 40px; }
@media (max-width: 780px) { .brett-aus-schwebend { display: none; } }
@media (min-width: 781px) { .brett-aus-nav { display: none !important; } }
.brett-aus-liste { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.brett-aus-kategorie { margin: 18px 0 8px; font-size: 1.05rem; opacity: .75; }
.brett-aus-zeile { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 4px;
    border-bottom: 1px solid var(--djk-border, #374151); }
.brett-aus-name { font-size: 1.2rem; font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
.brett-aus-name small { opacity: .6; font-weight: 600; }
.brett-aus-name em { margin-left: 6px; padding: 2px 8px; border-radius: 999px; background: #b91c1c; color: #fff;
    font-size: .8rem; font-style: normal; font-weight: 800; }
.brett-aus-zeile.ist-aus .brett-aus-name { opacity: .6; }
.brett-aus-schalter { flex: 0 0 auto; min-width: 130px; min-height: 44px; }

/* ------------------------------------------------------------------------------------------
   DER ZETTEL IN DER KARTEN-FORM (25.09.2026, Verwaltung -> Bildschirme -> „Form des Zettels").
   Nach dem Foto des Wirts: weisse Karte, farbiger Balken oben (Tisch blau, Abholung/Sofort gruen,
   Lieferung orange), zwei Zeilen Bezeichnung - Wert, ein hellblauer Block mit Gruppe und Zahl der
   Artikel, die Zeiten in Rahmen, die Gerichte kraeftig blau. Die Farben sind die des Fotos und
   bleiben auch im dunklen Erscheinungsbild weiss - der Zettel ist Papier.
   ------------------------------------------------------------------------------------------ */
.kueche-ticket-mini.ticket-karte {
    background: #fff;
    color: #111827;
    border: 0;
    border-radius: 10px;
    padding: 0 0 10px;
    gap: 0;
    overflow: hidden;
    box-shadow: 0 4px 14px rgba(15, 23, 42, .18);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    letter-spacing: normal;
}
/* Neu / noch nicht angesehen: die Karte bleibt weiss, es blinkt ein Rahmen in der Farbe des Standes
   (Verwaltung -> Kueche). Das Blinken der klassischen Form faerbt den GRUND - hier wurde die Schrift
   dadurch unlesbar (Foto des Wirts, 25.09.2026). */
.kueche-ticket-mini.ticket-karte.kueche-ticket-flash-dynamic,
.kueche-ticket-mini.ticket-karte.kueche-ticket-mini-fertig { background: #fff; }
.kueche-ticket-mini.ticket-karte.kueche-ticket-flash-dynamic { animation: tk-karte-blinken 1s ease-in-out infinite; }
@keyframes tk-karte-blinken {
    0%, 40%, 80% { box-shadow: 0 0 0 4px var(--kueche-flash-color, #ef4444), 0 4px 14px rgba(15, 23, 42, .18); }
    20%, 60%, 100% { box-shadow: 0 4px 14px rgba(15, 23, 42, .18); }
}
.ticket-karte .kueche-ticket-mini-veranst { display: block; margin: 0; border-radius: 0; padding: 3px 14px; }
.ticket-karte .tk-balken { height: 10px; background: #0ea5e9; }
.ticket-karte .tk-balken-abholung, .ticket-karte .tk-balken-sofort { background: #22c55e; }
.ticket-karte .tk-balken-lieferung { background: #f59e0b; }
.ticket-karte .tk-zeichen { width: 1.25em; margin-right: 6px; text-align: center; color: #475569; }
.ticket-karte .tk-zeiten .tk-zeichen { margin-right: 2px; }
.ticket-karte .tk-kopf { padding: 10px 14px 8px; display: grid; gap: 4px; }
.ticket-karte .tk-zeile { display: flex; align-items: center; justify-content: space-between; gap: 8px;
    font-size: 1.05rem; color: #1f2937; }
.ticket-karte .tk-zeile b { font-weight: 800; color: #111827; }
.ticket-karte .tk-block-kopf { margin: 4px 10px 0; padding: 8px 10px; display: flex; justify-content: space-between; gap: 8px;
    border-top: 6px solid #0ea5e9; border-radius: 8px 8px 0 0; background: #eef7fd; font-size: .9rem; font-weight: 800; color: #111827; }
.ticket-karte .tk-zeiten { margin: 0 10px; padding: 6px 10px 8px; display: flex; align-items: center; gap: 8px;
    background: #eef7fd; font-size: .9rem; color: #111827; }
/* Beide Zeiten im selben Rahmen, Zeichen innen (25.09.2026, Foto des Wirts). */
.ticket-karte .tk-zeit { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid #94a3b8; border-radius: 6px;
    background: #fff; color: #111827; font-weight: 700; font-size: .95rem; font-variant-numeric: tabular-nums; line-height: 1.2; }
.ticket-karte .tk-zeit .kueche-ticket-mini-timer { padding: 0; border: 0; background: none; font: inherit; }
.ticket-karte .tk-zeit .tk-zeichen { margin: 0; width: auto; }
.ticket-karte .tk-trenner { color: #94a3b8; }
.ticket-karte .kueche-ticket-mini-items { margin: 0 10px; padding: 6px 10px 8px 14px; background: #eef7fd; border-radius: 0 0 8px 8px;
    border-left: 5px solid #0ea5e9; }
.ticket-karte .kueche-ticket-mini-items .kueche-ticket-menge,
.ticket-karte .kueche-ticket-mini-items .kueche-ticket-name { color: #0b5f8a; font-weight: 800; font-size: 1.05rem; }
.ticket-karte .kueche-mini-fuss { padding: 8px 10px 0; }
.ticket-karte .kueche-mini-fuss > .kueche-drucken-btn,
.ticket-karte .kueche-mini-fuss > .kueche-ticket-btn { min-height: 38px; padding: 6px 10px; border-radius: 8px; font-size: .95rem; box-shadow: none; }
.ticket-karte .kueche-ticket-mini-items .kueche-ticket-menge,
.ticket-karte .kueche-ticket-mini-items .kueche-ticket-name,
.ticket-karte .tk-zeit, .ticket-karte .tk-zeiten .kueche-ticket-mini-timer { font-family: inherit; }
.ticket-karte.kueche-ticket-mini-fertig .tk-block-kopf,
.ticket-karte.kueche-ticket-mini-fertig .tk-zeiten,
.ticket-karte.kueche-ticket-mini-fertig .kueche-ticket-mini-items { background: #ecfdf3; }

/* Ohne die grosse Ansicht links (Verwaltung -> Bildschirme): die Zettel nehmen die ganze Breite. */
.kueche-board.brett-ohne-detail .kueche-board-detail,
.kueche-board.brett-ohne-detail .kueche-board-resizer { display: none; }
.kueche-board.brett-ohne-detail .kueche-board-list { flex: 1 1 100%; }

/* Platz unter den Zetteln (25.09.2026): der letzte darf nicht hinter Menue und Spiess liegen bleiben. */
@media (min-width: 781px) {
    body:has(.brett-spiess-schwebend) .kueche-board-list { padding-bottom: 130px; }
}

/* Das Vollbild des Spiesses: etwas tiefer, grosses Zeichen, Zettel in der Form der Karte. */
.brett-spiess-vollbild { padding-top: calc(28px + env(safe-area-inset-top, 0px)); }
.brett-spiess-kopf { margin-bottom: 16px; }
.brett-spiess-kopf .brett-spiess-svg { width: 52px; height: 52px; }
.brett-spiess-zettel.ticket-karte { background: #fff; color: #111827; border: 0; border-radius: 10px; padding: 0 0 12px; overflow: hidden;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .3); font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; }
.brett-spiess-zettel.ticket-karte .bsz-nr { margin-right: 8px; }
.brett-spiess-zettel.ticket-karte .bsz-pos { padding: 2px 0; }
.brett-spiess-zettel.ticket-karte .bsz-pos small,
.brett-spiess-zettel.ticket-karte .bsz-pos em { display: block; margin-left: 28px; font-size: .9rem; color: #475569; font-style: normal; }

/* ==========================================================================
   FORM DER PRODUKTKACHELN (26.09.2026, auf Wunsch des Wirts)

   Verwaltung: Kasse » Ansicht » „Form der Produktkacheln" (Einstellung kasse_kachel_stil,
   includes/kasse_schriften.php). personal/kasse.php setzt EINE Klasse an den body:
   kachel-stil-flach|knopf|neigen|glas|dick|weich. Deshalb gelten die Regeln fuer beide
   Kachel-Bauer (PHP und buildProductTileHtml in kasse.js) ohne eigene Zeile dort. Kiosk und
   Verwaltung tragen die Klasse nicht und bleiben unberuehrt.

   - Die Farbe kommt aus --kachel-voll (Inline-Stil der Kachel). Der Inline-Verlauf steht im
     style-Attribut, darum braucht der eigene Anstrich !important — wie kasse-kachel-flach.
     Kacheln ohne Farbe behalten ihren Grund und bekommen nur Schatten und Druck.
   - Ein Foto (<img> in .product-tile-photo) liegt UEBER dem Grund; Glanz auf dem Foto kommt
     nur als Ueberlagerung (.product-tile-photo::after, pointer-events:none).
   - Im Ordnen-Modus gehoert der Druck dem Verschieben: kein Eindruecken.
   - Kategorie-Kacheln sind ebenfalls .product-tile und bekommen dieselbe Form; das Kippen
     („neigen") kommt aus EINEM Zuhoerer in kasse.js (NEIG_KACHELN), siehe unten.
   ========================================================================== */
/* Seit dem 26.09.2026 (Wirt: „auf allen Kacheln der Kasse") gilt die Form fuer JEDE Kachel
   der Personal-Kasse — dieselbe Liste wie NEIG_KACHELN in kasse.js: Produkte, Kategorien,
   Tische (.tisch-tile ist auch .product-tile), Tischgruppen (.tisch-kat-chip), Warengruppen,
   Zahlarten (.pay-method-btn), Menue-Flaeche (.kasse-menue-knopf, .pg-kachel). Saalplan-Tische sind
   <g class="product-tile"> im SVG und bleiben aussen vor (:not(g)).
   - Die Farbe der Kachel steckt in --ks-farbe: --kachel-voll (Produkt/Kategorie/Warengruppe),
     --pm-akzent (Zahlart), die Zustandsfarbe (Tisch frei/wartet/bereit). Nur wo --kachel-voll
     inline steht, wird der Grund neu gemalt; sonst bleibt er, und die Form kommt allein aus
     Schatten, Glanz (inset) und Druck — so bleiben Zustandsfarben unberuehrt.
   - Zustaende, die selbst box-shadow tragen (Tisch „mein"/„fremd", Aktion, gewaehlte Gruppe),
     reichen ihn als --ks-ring durch; er steht vorn in jedem Schatten. Das Radar des wartenden
     Tisches ist eine Animation und gewinnt ohnehin. */
body[class*="kachel-stil-"] { --ks-schatten: rgba(0, 0, 0, .45); --ks-schatten-weich: rgba(0, 0, 0, .55); }
body[class*="kachel-stil-"]:not(.thema-dunkel) { --ks-schatten: rgba(15, 23, 42, .28); --ks-schatten-weich: rgba(15, 23, 42, .30); }
body[class*="kachel-stil-"] :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel) { --ks-farbe: var(--kachel-voll, #475569); }
body[class*="kachel-stil-"] .pay-method-btn[class] { --ks-farbe: var(--pm-akzent, #475569); }
body[class*="kachel-stil-"] :is(.tisch-tile, .tisch-kat-chip).tisch-frei { --ks-farbe: #6b7683; }
body[class*="kachel-stil-"] :is(.tisch-tile, .tisch-kat-chip).tisch-wartet { --ks-farbe: #b8821c; }
body[class*="kachel-stil-"] :is(.tisch-tile, .tisch-kat-chip).tisch-bereit { --ks-farbe: #1f7594; }
body[class*="kachel-stil-"] .tisch-tile.tisch-mein { --ks-ring: inset 0 0 0 2px var(--djk-yellow), 0 0 0 1px rgba(59, 130, 246, 0.35); }
body[class*="kachel-stil-"] .tisch-tile.tisch-fremd { --ks-ring: inset 0 0 0 999px rgba(15, 23, 42, 0.55); }
body[class*="kachel-stil-"] .tisch-tile.tisch-fremd:active { --ks-ring: inset 0 0 0 999px rgba(15, 23, 42, 0.25); }
body[class*="kachel-stil-"] .kategorie-tile.hat-aktion { --ks-ring: inset 0 0 0 2px var(--kasse-aktion, transparent); }
body[class*="kachel-stil-"] .tisch-kat-chip.active.tisch-wartet { --ks-ring: 0 0 0 2px var(--djk-yellow); }

/* „flach" ist die Kasse wie bisher — keine Regel. */

/* A. Gewoelbter Knopf: Licht oben, dicke Unterkante, Druck drueckt ihn hinunter. */
body.kachel-stil-knopf :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel)[style*="--kachel-voll"] {
    background: linear-gradient(180deg, color-mix(in srgb, var(--kachel-voll) 80%, #fff) 0%, var(--kachel-voll) 45%, color-mix(in srgb, var(--kachel-voll) 80%, #000) 100%) !important;
}
body.kachel-stil-knopf :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel) {
    box-shadow: var(--ks-ring, 0 0 #0000), inset 0 1px 0 rgba(255, 255, 255, .35), inset 0 12px 14px -10px rgba(255, 255, 255, .18), 0 5px 0 color-mix(in srgb, var(--ks-farbe) 55%, #000), 0 8px 14px var(--ks-schatten);
    transition: transform .08s, box-shadow .08s, border-color var(--transition), background var(--transition);
    margin-bottom: 5px;
}
body.kachel-stil-knopf :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):hover { transform: none; }
body.kachel-stil-knopf:not(.kacheln-ordnen-an) :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):active {
    transform: translateY(4px);
    box-shadow: var(--ks-ring, 0 0 #0000), inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 0 color-mix(in srgb, var(--ks-farbe) 55%, #000), 0 2px 5px var(--ks-schatten);
}

/* B. Neigt sich zum Finger: kasse.js setzt beim Druecken transform und --ks-x/--ks-y. */
body.kachel-stil-neigen :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel)[style*="--kachel-voll"] {
    background: radial-gradient(circle at var(--ks-x, 50%) var(--ks-y, 0%), rgba(255, 255, 255, var(--ks-blick, 0)), transparent 55%),
                linear-gradient(135deg, color-mix(in srgb, var(--kachel-voll) 88%, #fff), var(--kachel-voll)) !important;
}
body.kachel-stil-neigen :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel) {
    box-shadow: var(--ks-ring, 0 0 #0000), 0 10px 20px var(--ks-schatten);
    transition: transform .15s ease-out, box-shadow .15s, border-color var(--transition), background var(--transition);
}
body.kachel-stil-neigen :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):hover { transform: none; }
body.kachel-stil-neigen :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel).ks-gedrueckt {
    --ks-blick: .28;
    box-shadow: var(--ks-ring, 0 0 #0000), inset 0 0 0 999px rgba(255, 255, 255, .06), 0 3px 8px var(--ks-schatten);
    will-change: transform;
    transition: box-shadow .15s;
}
body.kachel-stil-neigen .product-tile.ks-gedrueckt .product-tile-photo { position: relative; }
body.kachel-stil-neigen .product-tile.ks-gedrueckt .product-tile-photo::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(circle at var(--ks-x, 50%) var(--ks-y, 0%), rgba(255, 255, 255, .28), transparent 55%);
}

/* C. Glas mit Glanz: Spiegelung oben, Druck macht sie etwas kleiner. Ohne --kachel-voll
   (Tisch, Zahlart, Menue) kommt die Spiegelung als heller inset-Schatten oben. */
body.kachel-stil-glas :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel)[style*="--kachel-voll"] {
    background: radial-gradient(ellipse 70% 38% at 50% 0%, rgba(255, 255, 255, .35), rgba(255, 255, 255, 0) 100%),
                linear-gradient(160deg, color-mix(in srgb, var(--kachel-voll) 70%, #fff) 0%, var(--kachel-voll) 38%, color-mix(in srgb, var(--kachel-voll) 75%, #000) 100%) !important;
}
body.kachel-stil-glas :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel) {
    box-shadow: var(--ks-ring, 0 0 #0000), inset 0 0 0 1px rgba(255, 255, 255, .18), inset 0 18px 16px -12px rgba(255, 255, 255, .30), inset 0 -10px 18px rgba(0, 0, 0, .25), 0 8px 16px var(--ks-schatten);
    transition: transform .08s, border-color var(--transition), background var(--transition);
}
body.kachel-stil-glas :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):hover { transform: none; }
body.kachel-stil-glas:not(.kacheln-ordnen-an) :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):active { transform: scale(.97); }
/* Der Glanz auch ueber dem Foto — nur als Ueberlagerung, das Bild bleibt ganz. */
body.kachel-stil-glas .product-tile-photo { position: relative; }
body.kachel-stil-glas .product-tile-photo::after {
    content: ''; position: absolute; left: -10%; right: -10%; top: -40%; height: 70%;
    border-radius: 50%; pointer-events: none;
    background: linear-gradient(180deg, rgba(255, 255, 255, .30), rgba(255, 255, 255, 0));
}

/* D. Dicke Kachel: zum Betrachter geneigt, die Seitenflaeche ist sichtbar. perspective()
   steht im transform der Kachel selbst — so braucht das Raster keine Aenderung. */
body.kachel-stil-dick :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel) {
    transform: perspective(900px) rotateX(14deg);
    transform-origin: 50% 100%;
    box-shadow: var(--ks-ring, 0 0 #0000), 0 6px 0 color-mix(in srgb, var(--ks-farbe) 50%, #000), 0 14px 18px var(--ks-schatten);
    transition: transform .1s, box-shadow .1s, border-color var(--transition), background var(--transition);
    margin-bottom: 6px;
}
body.kachel-stil-dick :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel)[style*="--kachel-voll"] { background: var(--kachel-voll) !important; }
body.kachel-stil-dick :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):hover { transform: perspective(900px) rotateX(14deg); }
body.kachel-stil-dick:not(.kacheln-ordnen-an) :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):active {
    transform: perspective(900px) rotateX(4deg) translateY(4px);
    box-shadow: var(--ks-ring, 0 0 #0000), 0 2px 0 color-mix(in srgb, var(--ks-farbe) 50%, #000), 0 4px 8px var(--ks-schatten);
}

/* E. Weiche Tiefe: weiche Schatten, Druck geht nach innen. */
body.kachel-stil-weich :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel)[style*="--kachel-voll"] {
    background: linear-gradient(145deg, color-mix(in srgb, var(--kachel-voll) 92%, #fff), color-mix(in srgb, var(--kachel-voll) 90%, #000)) !important;
}
body.kachel-stil-weich :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel) {
    box-shadow: var(--ks-ring, 0 0 #0000), 6px 6px 14px var(--ks-schatten-weich), -3px -3px 10px rgba(255, 255, 255, .06), inset 1px 1px 0 rgba(255, 255, 255, .2);
    border-radius: max(var(--kasse-kachel-rundung, 2px), 14px);
    transition: box-shadow .1s, border-color var(--transition), background var(--transition);
}
body.kachel-stil-weich :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):hover { transform: none; }
body.kachel-stil-weich:not(.kacheln-ordnen-an) :is(.product-tile:not(g), .warengruppe-chip, .pay-method-btn, .tisch-kat-chip, .kasse-menue-knopf, .pg-kachel):active {
    box-shadow: var(--ks-ring, 0 0 #0000), inset 5px 5px 10px rgba(0, 0, 0, .45), inset -2px -2px 6px rgba(255, 255, 255, .08);
}

/* KEIN ZIEHEN UEBER DEN RAND (26.09.2026, Foto des Wirts: „почему шапка тянется вниз?").
   Am iPhone laesst sich die Seite oben ueber den Rand ziehen; der feste Kopf wandert dabei mit,
   darueber klafft leerer Grund. Die Kasse ist ein Arbeitsplatz, kein Dokument - der Rand bleibt
   stehen. (Ziehen zum Neuladen gibt es im Heim-Bildschirm-Programm ohnehin nicht.) */
html:has(> body.personal-body),
body.personal-body { overscroll-behavior-y: none; }

/* ═══ ANIMATION DES TISCH-FENSTERS (26.09.2026, dritter Anlauf) ═══
   kasse.js (tischAnimSpielen) + assets/js/tisch_anim.js legen für ~0,7 s eine Leinwand mit dem
   BILD des Fensters über alles; sie fängt jeden Tipp ab. Keine DOM-Kopien mehr.
   `tisch-anim-verdeckt` = das echte Fenster steht offen, bleibt aber unsichtbar (Öffnen).
   `tisch-anim-blende`   = das Fenster ist logisch zu, bleibt aber für das kurze Ausblenden
                           sichtbar (Schliessen ohne aktuelles Bild). */
#tischOverlay.tisch-anim-verdeckt { visibility: hidden; }
#tischOverlay.tisch-anim-blende { display: block; pointer-events: none; }
.tisch-anim-schild { position: fixed; inset: 0; background: transparent; }
.tisch-anim-buehne {
    z-index: 2147483000;
    pointer-events: auto;
    touch-action: none;
}
@media (prefers-reduced-motion: reduce) {
    .tisch-anim-buehne { display: none; }
    #tischOverlay.tisch-anim-verdeckt { visibility: visible; }
}

/* BLATT AUCH ZUGEKLAPPT (26.09.2026, Foto des Wirts: „так же оставить, когда она закрыта").
   Seit 26.09. abends fuer JEDE Korb-Animation (Wirt: „во всех этих сделай как на фото 2"):
   runde obere Ecken, Griff, weicher Schatten nach oben statt des gelben Strichs.
   Nur bis 1199 px - darueber ist die Leiste die linke Bon-Spalte, keine Bodenleiste. */
@media (max-width: 1199px) {
body.kasse-body .kasse-bottom-bar:not(.expanded) {
    position: relative;   /* Halt fuer den Griff (::after) */
    border-top: none;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.4);
    /* 8 px + 10 px Polster der Kopfzeile = 18 px: genau das obere Polster der OFFENEN Kopfzeile.
       So ist das letzte Bild des Zuklappens pixelgleich mit der zugeklappten Leiste (kasse.js
       korbBlattWeg: die Blattkante landet auf der Oberkante der Leiste). */
    padding-top: 8px;
}
body.kasse-body .kasse-bottom-bar:not(.expanded)::after {
    content: '';
    position: absolute;
    top: 6px;
    left: 50%;
    width: 36px;
    height: 4px;
    margin-left: -18px;
    border-radius: 2px;
    background: #94a3b8;
    pointer-events: none;
}
}

/* BLATT: glatt aufsetzen und kein Spalt ueber „Bezahlen" (26.09.2026, Video des Wirts:
   „в самом конце садится и немного пружинит"; Foto: zwischen Liste und Bezahlen schien die
   Kasse durch). Die Kurve eines iOS-Blatts: lange, weiche Abbremsung ohne Nachwippen - fuer
   Karte, Liste und die zuruecktretende Kasse gleich, damit nichts nachruckelt. */
body.korb-anim-blatt { --korb-kurve: cubic-bezier(.32, .72, 0, 1); }
@media (max-width: 1199px) {
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded .kasse-bottom-actions {
    background: var(--djk-black-card);
    margin-top: 0;
    padding-top: 8px;
    box-shadow: 0 -12px 0 var(--djk-black-card);
}
}

/* BLATT: die Knopfreihe traegt den Blatt-Grund bis an beide Raender (26.09.2026, Foto des Wirts:
   links und rechts neben „Bezahlen" je ein schmaler abweichender Streifen). Sie stand innerhalb
   der 14 px Polster der Leiste; jetzt reicht sie mit negativem Rand bis an die Kante und holt
   die 14 px als eigenes Polster zurueck. Nach unten liegt sie schon bis an den Rand (gemessen:
   Unterkante 844 von 844, die sichere Zone steckt in ihrem Polster). Nur bis 1199 px. */
@media (max-width: 1199px) {
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded .kasse-bottom-actions {
    margin-left: -14px;
    margin-right: -14px;
    padding-left: 14px;
    padding-right: 14px;
    box-shadow: 0 -12px 0 var(--djk-black-card);
}
}

/* BLATT: die Kopfzeile liegt UEBER der Liste, aber unter der Knopfreihe (26.09.2026, Bilder des
   Wirts beim Zuklappen: die Zeile „Tisch …" verschwand unter der Liste und tauchte erst am Ende
   wieder auf). Beide hatten z-index 0, die Liste kommt spaeter im Dokument und malte darueber. */
@media (max-width: 1199px) {
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded .kasse-cart-summary { z-index: 1; }
}

/* BLATT: die grosse Summe faehrt beim Zuklappen GANZ hinaus (26.09.2026, Video des Wirts: ihr
   unterer Rand blieb oben im Polster der Leiste sichtbar und verschwand erst mit dem Klassen-
   wechsel - ein Sprung im letzten Bild). Um ihre Hoehe PLUS den Abstand zur Oberkante. */
@media (max-width: 1199px) {
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded.korb-eingang .kasse-summe-gross {
    transform: translateY(calc(-100% - 16px - env(safe-area-inset-top, 0px)));
}
}
/* BLATT: das letzte Bild des Zuklappens muss dem zugeklappten gleichen (Messung 26.09.2026:
   der Grund der Knopfreihe - Schatten 12 px nach oben - schnitt die Kopfzeile unten ab, und der
   Pfeil drehte erst mit dem Klassenwechsel). Die Kopfzeile liegt ueber der Knopfreihe, der Pfeil
   dreht schon beim Losfahren. */
@media (max-width: 1199px) {
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded .kasse-cart-summary { z-index: 2; }
body.korb-anim-blatt.kasse-body .kasse-bottom-bar.expanded.korb-eingang .kasse-cart-chevron { transform: none; }
}
