﻿/* OpenDyslexic - optionale Schriftart fuer Legastheniker, umschaltbar ueber
   das Barrierefreiheit-Widget (siehe .a11y-widget/.dyslexic-font weiter unten
   sowie globals.js applyDyslexicFontPreference()). Dateien liegen lokal unter
   styles/fonts/, damit die Funktion auch ohne externe Font-CDNs funktioniert. */
@font-face {
    font-family: 'OpenDyslexic';
    src: url('fonts/OpenDyslexic-Regular.otf') format('opentype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'OpenDyslexic';
    src: url('fonts/OpenDyslexic-Bold.otf') format('opentype');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'OpenDyslexic';
    src: url('fonts/OpenDyslexic-Italic.otf') format('opentype');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}
@font-face {
    font-family: 'OpenDyslexic';
    src: url('fonts/OpenDyslexic-BoldItalic.otf') format('opentype');
    font-weight: 700;
    font-style: italic;
    font-display: swap;
}

/* Plus Jakarta Sans - lokal gehostet statt live von fonts.googleapis.com/
   fonts.gstatic.com geladen, damit beim Seitenaufruf keine Verbindung (und
   damit IP-Adresse) mehr an Google uebertragen wird. Google liefert fuer
   dieses Font-Subset (v12, latin) fuer alle vier Schnitte dieselbe Datei aus
   (identisches Verhalten wie zuvor ueber Google Fonts) - daher genuegt eine
   einzelne woff2-Datei fuer alle vier font-weight-Deklarationen. */
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/PlusJakartaSans.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/PlusJakartaSans.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/PlusJakartaSans.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/PlusJakartaSans.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

:root {
    --bg-color: #f3f4f6;
    --card-bg: #ffffff;
    --text-color: #1f2937;
    --text-muted: #5f6b7c;
    --primary-color: #3b82f6;
    --primary-hover: #2563eb;
    --secondary-color: #64748b;
    --secondary-hover: #475569;
    --border-color: #e5e7eb;
    --success-color: #10b981;
    --danger-color: #ef4444;
    --warning-color: #f59e0b;
    --perfect-color: #8b5cf6;

    /* WCAG-AA-konforme Text-Varianten (min. 4.5:1) der obigen Akzentfarben -
       fuer echten Text (Ueberschriften, Links, Badges) auf --card-bg/--bg-color.
       Die "normalen" --primary-color/--danger-color/... bleiben fuer rein
       dekorative Zwecke (Icons, Chart-Linien, Fortschrittsbalken, Status-Punkte)
       unveraendert, da dort kein 4.5:1-Textkontrast noetig ist. Werden in
       body.dark-mode auf hellere, gegen dunkle Hintergruende geprüfte Toene
       umgeschaltet. */
    --primary-color-text: #1d4ed8;
    --danger-color-text: #b91c1c;
    --success-color-text: #047857;
    --warning-color-text: #b45309;
    --secondary-color-text: #334155;

    /* Feste, NICHT themenabhaengige Button-Hintergrundfarben fuer Buttons mit
       weisser Schrift (z.B. .action-btn) - brauchen unabhaengig vom Light-/
       Dark-Mode denselben dunklen Ton, damit der weisse Text lesbar bleibt
       (anders als reiner Text auf der Seite duerfen sie nicht im Dark Mode
       aufhellen). */
    --primary-btn-bg: #1d4ed8;
    --danger-btn-bg: #b91c1c;
    --success-btn-bg: #047857;
    --danger-hover: #991b1b;
}

body.dark-mode {
    --bg-color: #111827;
    --card-bg: #1f2937;
    --text-color: #f9fafb;
    --text-muted: #9ca3af;
    --border-color: #374151;

    --primary-color-text: #60a5fa;
    --danger-color-text: #f87171;
    --success-color-text: #34d399;
    --warning-color-text: #fbbf24;
    --secondary-color-text: #94a3b8;
}

/* Hoher-Kontrast-Modus (per Skip-Link-Button und Einstellungen umschaltbar,
   siehe globals.js applyHighContrastPreference()). Erzwingt reines Schwarz/
   Weiss statt der abgestuften Grautoene und ersetzt alle Akzentfarben durch
   AAA-taugliche Varianten (>=7:1 auf Schwarz) - unabhaengig davon, ob Hell-
   oder Dunkelmodus zusaetzlich aktiv ist (ueberschreibt beide). */
body.high-contrast {
    --bg-color: #000000;
    --card-bg: #000000;
    --text-color: #ffffff;
    --text-muted: #ffffff;
    --primary-color: #66b3ff;
    --primary-hover: #99ccff;
    --secondary-color: #000000;
    --secondary-hover: #333333;
    --border-color: #ffffff;
    --success-color: #6bff6b;
    --danger-color: #ff6b6b;
    --warning-color: #ffd60a;
    --perfect-color: #d8b4fe;

    --primary-color-text: #66b3ff;
    --danger-color-text: #ff6b6b;
    --success-color-text: #6bff6b;
    --warning-color-text: #ffd60a;
    --secondary-color-text: #ffffff;

    --primary-btn-bg: #000000;
    --danger-btn-bg: #000000;
    --success-btn-bg: #000000;
}

/* Die eigentliche Aufhebung des "Glas-Effekts" (.card/.progress-section/
   .leaderboard-sticky-header, siehe weiter unten in dieser Datei) steht ganz
   am Ende der Datei: body.high-contrast .card & Co. haben dieselbe
   Selektor-Spezifitaet wie body.dark-mode .card & Co. (je ein Element- +
   zwei Klassen-Selektor) - bei gleicher Spezifitaet gewinnt die Regel, die
   spaeter im Quelltext steht, das High-Contrast-!important ist nur die
   zweite Absicherung dafuer. */

.input-group input,
.input-group select {
    width: 100%;
    box-sizing: border-box;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* Jedes Bild oeffnet per Klick eine Lightbox (siehe openImageLightbox() in
   globals.js) - der Cursor zeigt das schon vor dem Klick an. Bilder
   innerhalb der Lightbox selbst brauchen den Hinweis nicht mehr. */
img {
    cursor: zoom-in;
}

#imageLightbox img {
    cursor: default;
}

/* Tag-/Status-Icons (Bio/Vegetarisch/Vegan/.../"Verifiziert") loesen bewusst
   keine Lightbox aus (siehe globals.js) - der Zoom-Cursor waere hier
   irrefuehrend. */
img[src="img/checkmark.svg"],
img[src^="img/tag_"] {
    cursor: default;
}

body {
    background-color: var(--bg-color);
    /* NEU: Dezente Farb-Blobs im Hintergrund für den perfekten Glass-Effekt */
    background-image: 
        radial-gradient(at 0% 0%, rgba(59, 130, 246, 0.15) 0px, transparent 50%),
        radial-gradient(at 100% 0%, rgba(139, 92, 246, 0.12) 0px, transparent 50%),
        radial-gradient(at 100% 100%, rgba(16, 185, 129, 0.12) 0px, transparent 50%);
    background-attachment: fixed;
    
    color: var(--text-color);
    line-height: 1.5;
    padding: 20px;
    transition: background-color 0.3s, color 0.3s;
    min-height: 100vh;
}

/* Sanfter Sonnenschein-Akzent in der oberen rechten Ecke - bewusst als weicher,
   halbtransparenter Verlauf (statt einer flaechigen Volltonflaeche) und mit dem
   Zentrum GENAU auf der Bildschirmecke platziert, damit nur ein Viertelkreis
   hereinragt. So bleibt er ein dezenter Akzent im Stil der uebrigen Farb-Blobs
   oben, statt wie zuvor als grelle gelbe Flaeche hinter den Header-Buttons zu
   wirken (dort sass er bei "circle at 90% 10%" optisch mitten im Button-Bereich). */
body:not(.dark-mode).is-day {
    background: var(--bg-color) radial-gradient(circle at 100% 0%, rgba(253, 224, 71, 0.4) 0px, rgba(253, 224, 71, 0.18) 60px, transparent 140px) no-repeat fixed;
}

body.dark-mode.is-night {
    background-color: var(--bg-color);
    background-image:
        radial-gradient(2px 2px at 20px 30px, #ffffff, rgba(0,0,0,0)),
        radial-gradient(2px 2px at 60px 80px, #ffffff, rgba(0,0,0,0)),
        radial-gradient(2px 2px at 130px 40px, #fde047, rgba(0,0,0,0)),
        radial-gradient(2px 2px at 180px 120px, #ffffff, rgba(0,0,0,0)),
        radial-gradient(2px 2px at 250px 50px, #ffffff, rgba(0,0,0,0)),
        radial-gradient(2px 2px at 300px 150px, #ffffff, rgba(0,0,0,0));
    background-repeat: repeat;
    background-size: 350px 200px;
    background-attachment: fixed;
}



.admin-badge {
    border-color: rgba(245, 158, 11, 0.5);
    background-color: rgba(245, 158, 11, 0.1); 
    margin-left: 6px; 
}

.container {
    max-width: 800px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 20px;
    position: relative;
    z-index: 1;
    /* Reserviert Platz fuer den fixed positionierten Sync-Status-Banner
       (siehe updateSyncBannerHeightVar in offlineSync.js), damit der beim
       Einblenden nicht einfach ueber dem Header liegt und ihn verdeckt -
       0px per Default, wenn der Banner nicht sichtbar ist. */
    margin-top: var(--sync-banner-height, 0px);
    transition: margin-top 0.25s ease;
}

/* Auf Mobilgeräten soll die Erfassungs-Karte vor den Statistiken stehen,
   auf großen Bildschirmen aber weiterhin rechts neben ihnen (siehe
   @media min-width: 1024px, wo die DOM-Reihenfolge wiederhergestellt wird).
   Alle nachfolgenden Sektionen brauchen ebenfalls eine explizite Order,
   da sie sonst (order: 0) vor die verschobene Erfassungs-Karte rutschen
   wuerden - flexbox sortiert global ueber alle Kinder, nicht nur lokal. */
#newEntryCard {
    order: 1;
}
#weightStatsGrid {
    order: 2;
}
.calendar-full-width {
    order: 3;
}
#communityDivider {
    order: 4;
}
#globalStatsCard {
    order: 5;
}

.section-divider {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    margin: 4px 0;
}
.section-divider::before,
.section-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, transparent, var(--border-color), transparent);
}
.section-divider-label {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--text-muted);
    white-space: nowrap;
    letter-spacing: 0.8px;
    text-transform: uppercase;
}
.app-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap; /* Erlaubt auf extrem kleinen Displays einen sauberen Zeilenumbruch der ganzen Button-Leiste */
    gap: 12px;
}

.app-header h1 {
    font-size: clamp(1.2rem, 5vw, 1.75rem); /* Schrumpft auf Handys elegant und automatisch mit */
    display: flex;
    align-items: center;
    margin: 0;
    white-space: nowrap; /* Hält Überschrift und Symbole zwingend in einer Zeile */
}

.header-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* Menuebuttons oben (Einkaufsliste/Produkte/Einstellungen/Bilanz, sowie der
   "Zurueck zur App"-Button auf products.php/shopping.php) wirkten etwas klein
   - horizontales Padding um Faktor 1.5 vergroessert (16px -> 24px), Hoehe
   bewusst unveraendert gelassen. Der Profil-Button (.avatar-btn) behaelt sein
   eigenes, an das Avatarbild angepasstes Padding. */
.header-actions .icon-btn:not(.avatar-btn) {
    padding-left: 24px;
    padding-right: 24px;
}

/* Textlabel neben dem Emoji in Einkaufsliste/Produkte/Einstellungen/Meine
   Bilanz - unterhalb des bestehenden 1024px-Breakpoints ausgeblendet (siehe
   @media weiter unten), damit bei wenig Platz nur noch die Icons
   stehenbleiben statt die ganze Zeile umzubrechen. Bewusst an den
   bestehenden ".container"-Breakpoint gekoppelt (siehe "Desktop-
   Optimierung" @media min-width:1024px weiter unten): erst dort wird
   .app-header zum ueber beide Grid-Spalten spannenden Element und hat
   dadurch wirklich genug Platz fuer 5 Buttons mit vollem Text - darunter
   bleibt .container bei max-width:800px, zu schmal dafuer. "Profil"
   (#authBtnLabel) nutzt bewusst eine ANDERE Klasse und ist von dieser Regel
   nicht betroffen - der Button soll immer Bild+Text zeigen. */
@media (max-width: 1023px) {
    .header-actions .icon-btn-label {
        display: none;
    }

    /* Gleiche Hoehe wie die anderen Header-Buttons auf dieser Breite (siehe
       Regel direkt darunter) - sonst wirkt der Profil-Button (36px, nie
       angepasst) neben den auf 40px vergroesserten Icon-Buttons zu klein/
       vertikal versetzt. */
    .header-actions .avatar-btn {
        height: 40px;
    }

    .header-actions .icon-btn:not(.avatar-btn) {
        width: 48px;
        height: 40px;
        padding: 0 !important;
        font-size: 1.2rem !important;
    }

    /* "Zur App" auf products.php/shopping.php ist dort (neben dem
       Profil-Button auf products.php bzw. ganz allein auf shopping.php) die
       einzige Navigationsaktion im Header, statt einer von fuenf gleich
       gewichteten Buttons wie auf index.php - bekommt deshalb dieselbe
       "immer mit Text" Darstellung statt auf ein reines Icon-Quadrat
       zusammenzuschrumpfen. Korrektur (Audit): beide Buttons haben zwar
       keinen .icon-btn-label-Span (daher von der Label-ausblenden-Regel
       oben unberuehrt), die Breiten-/Padding-/Font-Size-Werte der
       Icon-only-Regel oben griffen aber trotzdem unabhaengig davon - ohne
       dieses !important auf width waere der Text in einem 48px-Quadrat mit
       0 Padding uebergelaufen. width:auto hier gewinnt dadurch ausserdem
       gegen shopping.css's aeltere ".header-actions button { width:100%
       !important }"-Regel fuer Bildschirme <=600px (hoehere Spezifitaet
       schlaegt gleich wichtige Regel), die dort inzwischen entfernt wurde. */
    #productsBackToAppBtn,
    #shoppingBackToAppBtn {
        width: auto !important;
        height: 40px;
        padding: 0 18px !important;
        font-size: 0.9rem !important;
    }
    #productsBackToAppBtn .icon-btn-label {
        display: inline;
    }
}

/* --- Die Aktions-Buttons --- */
.icon-btn {
    background-color: var(--card-bg);
    border: 1px solid var(--border-color);
    color: var(--text-color);
    font-size: 0.95rem;
    height: 36px;
    padding: 0 16px;
    border-radius: 18px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.3s, border-color 0.3s, box-shadow 0.3s;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
    
    /* NEU: Der Schutz vor dem Umbrechen auf Handys */
    white-space: nowrap; /* Verbietet das Stapeln von Symbol und Text */
    flex-shrink: 0; /* Verbietet das Zusammenquetschen des Buttons */
    gap: 6px; /* Sorgt für konstanten Abstand zwischen Emoji und Text */
}

.icon-btn:hover {
    border-color: var(--primary-color);
    box-shadow: 0 2px 5px rgba(0,0,0,0.12);
}

/* Profil-Button: rundes Avatarbild links vom Label, ansonsten ein normaler .icon-btn */
.avatar-btn {
    padding: 0 14px 0 4px;
}
.auth-avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    display: block;
}

.admin-section {
    padding: 15px;
    background-color: var(--bg-color);
    border-radius: 8px;
    margin-top: 15px;
    border: 1px solid var(--border-color);
}


/* --- Sub-Tabs Layout (Standard für Desktop: Vertikal links) --- */
#chartLayoutWrapper,
#waterLayoutWrapper {
    display: flex;
    flex-direction: row;
    gap: 15px;
    align-items: stretch;
}

.sub-tabs-vertical {
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--border-color);
    padding-right: 15px;
    gap: 8px;
    min-width: 150px;
    flex-shrink: 0;
}

.sub-tab-btn {
    background: none;
    border: 1px solid transparent;
    text-align: left;
    padding: 10px 14px;
    cursor: pointer;
    color: var(--text-muted);
    border-radius: 6px;
    transition: all 0.2s;
    font-size: 0.9rem;
    white-space: nowrap;
}

.sub-tab-btn.active {
    background: var(--primary-btn-bg);
    color: white;
}

.sub-tab-btn:hover:not(.active) {
    background: var(--border-color);
    color: var(--text-color);
}

/* --- Mobile Ansicht (Handy): Horizontal oben/untereinander --- */
@media (max-width: 768px) {
    /* #waterLayoutWrapper traegt ein Inline-style="...flex-direction: row..."
       (siehe index.php) - dafuer bleibt !important hier noetig. #chartLayoutWrapper
       braucht es eigentlich nicht (kein Inline-flex-direction), wird hier aber
       aus Einfachheit ueber denselben Selektor mitgeregelt. */
    #chartLayoutWrapper,
    #waterLayoutWrapper {
        flex-direction: column !important;
    }

    /* Ab hier kein !important mehr noetig: dieselben Selektoren wie die
       Basis-Regeln oben, gleiche Spezifitaet, steht spaeter im Quelltext -
       gewinnt schon per normaler Kaskade. Kein konkurrierendes Inline-style. */
    .sub-tabs-vertical {
        flex-direction: row;
        border-right: none;
        border-bottom: 1px solid var(--border-color);
        padding-right: 0;
        padding-bottom: 10px;
        overflow-x: auto;
        min-width: 100%;
        width: 100%;
    }

    .sub-tab-btn {
        flex: 1;
        text-align: center;
        white-space: nowrap;
        padding: 8px 10px;
        font-size: 0.85rem;
    }
}

.user-list-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;
    border-bottom: 1px solid var(--border-color);
}

.user-list-item:last-child {
    border-bottom: none;
}

.user-info {
    display: flex;
    flex-direction: column;
}

.user-info strong {
    font-size: 0.95rem;
    color: var(--text-color);
}

.user-stats {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 2px;
}

.greeting {
    font-size: 1.5rem;
    font-weight: 600;
    margin-bottom: -5px;
    color: var(--text-color);
}

/* --- Saubere Status-Indikatoren (ohne klobige Kreise) --- */
.auth-status-badge {
    font-size: 1.3rem; /* Etwas größer für optimale Lesbarkeit */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 8px;
    line-height: 1;
    transition: transform 0.3s ease;
    
    /* Hintergrund, Rahmen und Box-Shadow restlos entfernen. Kein !important
       noetig: gleiche Selektor-Spezifitaet wie .admin-badge (Zeile weiter
       oben), steht spaeter im Quelltext und gewinnt daher schon per Kaskade;
       kein Element hier hat ein konkurrierendes Inline-style. */
    background: none;
    border: none;
    box-shadow: none;
}

.auth-status-badge.online, .admin-badge {
    /* Überschreibt die vorherigen Farb-Hintergründe restlos */
    background: none;
    border: none;
}

body.dark-mode .auth-status-badge {
    filter: drop-shadow(0 2px 4px rgba(255, 255, 255, 0.15));
}

.card {
    background-color: var(--card-bg);
    border-radius: 12px;
    padding: 20px;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
    transition: background-color 0.3s;
}

h1 {
    font-size: 1.5rem;
    margin-bottom: 15px;
    color: var(--text-color);
}

h2 {
    font-size: 1.25rem;
    margin-bottom: 15px;
    color: var(--text-color);
}

h3 {
    font-size: 1rem;
    margin-bottom: 8px;
    color: var(--text-color);
}

/* Informelle "Mini-Überschrift" zwischen h2 und h3, z.B. Abschnittstitel
   in Info-Boxen (Datenschutz, API-Doku, Admin-Formulare). */
.section-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--primary-color-text);
}

.tabs {
  display: flex;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 15px;
    flex: 1; /* NEU: Nimmt den verfügbaren Platz im Header voll ein */
    width: 100%; /* NEU: Zwingt die Leiste zur vollen Breite */
}

.tab-btn {
    flex: 1;
    text-align: center;
    position: relative;
    padding: 10px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    font-weight: 600;
    transition: color 0.2s, border-color 0.2s;
    font-size: 1rem;
}

.tab-btn:hover {
    color: var(--text-color);
}

.tab-btn.active {
    color: var(--primary-color-text);
    border-bottom-color: var(--primary-color);
}

.tab-content {
    display: none;
}

.tab-content.active {
    display: block;
}

/* Lebensmittel-Modal: beide Tab-Panels liegen uebereinander im selben Grid-Feld,
   damit die Container-Hoehe sich am groesseren Panel orientiert und das Modal
   beim Wechseln zwischen "Suchen" und "Neu anlegen" nicht seine Groesse aendert. */
.food-tab-panels {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    /* Containing Block fuer das absolut positionierte #foodSearchPanel (siehe unten) -
       ohne position:relative hier wuerde es sich stattdessen am naechsten positionierten
       Vorfahren (.modal-content) orientieren und ueber Tabs/Ueberschrift ragen. */
    position: relative;
}

.food-tab-panels > .tab-content {
    grid-area: 1 / 1;
    display: block;
    visibility: hidden;
    pointer-events: none;
    /* Ohne min-width:0 nutzen Grid-Items als Mindestbreite die Min-Content-Breite
       ihrer Kinder statt der Spaltenbreite - dadurch lief der Inhalt rechts aus
       dem Modal heraus, statt innen zu umbrechen. */
    min-width: 0;
}

.food-tab-panels > .tab-content.active {
    visibility: visible;
    pointer-events: auto;
}

/* Der Such-Tab wird absolut auf die vom "Neu anlegen"-Tab vorgegebene Zellengroesse
   gelegt, statt selbst zur Gitter-Hoehe beizutragen - so kann seine Ergebnisliste bis
   zum unteren Rand des Modals reichen (und dort intern scrollen), ohne dass viele
   Treffer das ganze Modal (und damit auch den "Neu anlegen"-Tab) aufblaehen. */
#foodSearchPanel {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
}

.stats-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    text-align: center;
}

.stat-item {
    flex: 1;
    min-width: 130px;
    padding: 15px;
    background-color: var(--bg-color);
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    transition: background-color 0.3s;
}

.stat-label {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 5px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.stat-value {
    font-size: 1.25rem;
    font-weight: bold;
}

.stat-sub {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 4px;
}

/* Zweigeteilte "Doppelbox" (z.B. Veraenderung + Meilenstein) - eine Kachel,
   zwei unabhaengige Haelften nebeneinander statt eines einzelnen Werts. */
.stat-item-combo {
    flex: 3;
    min-width: 340px;
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 15px;
}
.stat-item-combo-left {
    flex: 1;
    border-right: 1px solid var(--border-color);
    padding-right: 15px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.stat-item-combo-right {
    flex: 1.2;
    padding-left: 15px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
}
.stat-item-combo-right-label {
    margin-bottom: 5px;
    font-size: 0.75rem;
    letter-spacing: 0.5px;
}
.stat-item-combo-symbol {
    font-size: 1.8rem;
    line-height: 1;
    margin-bottom: 5px;
}

/* Dreigeteilte "Dreifachbox" (Naehrwerte: Fett/Kohlenhydrate/Eiweiss) - eine
   Kachel, drei gleichwertige Segmente nebeneinander statt eines Werts oder
   zweier ungleicher Haelften wie bei .stat-item-combo. */
.stat-item-triple {
    flex: 3;
    min-width: 340px;
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 15px;
}
.stat-item-triple-segment {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    padding: 0 10px;
}
.stat-item-triple-segment:not(:last-child) {
    border-right: 1px solid var(--border-color);
}

/* Fuer Statistik-Boxen, deren Wert ein Name/Satz statt einer kurzen Zahl ist
   (Meilenstein-Name, Lieblingssportart) - bei voller .stat-value-Groesse
   wirken solche Texte unverhaeltnismaessig wuchtig. */
.stat-value-text {
    font-size: 0.95rem;
}

/* --- Frei konfigurierbare Dashboard-Statistik-Boxen (scripts/statsEngine.js) --- */
.dashboard-stats-header {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
    min-height: 28px;
}

.dashboard-stats-edit-btn {
    background: none;
    border: 1px solid var(--border-color);
    color: var(--text-muted);
    border-radius: 18px;
    padding: 4px 12px;
    font-size: 0.8rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 5px;
    transition: color 0.2s, border-color 0.2s;
}
.dashboard-stats-edit-btn:hover {
    color: var(--primary-color-text);
    border-color: var(--primary-color);
}

/* Sitzt jetzt (statt oben rechts im .dashboard-stats-header) als letztes Kind
   von #weightStatsGrid, direkt nach den Statistik-Boxen - dessen Inline-Style
   "display:flex; flex-direction:column" macht daraus einen Flex-Container, in
   dem der Button per Default auf volle Breite gestreckt wuerde. width:fit-
   content + margin:auto zusaetzlich zu align-self, damit die Zentrierung
   robust bleibt, egal ob er per Flex-Cross-Axis oder Block-Fluss positioniert
   wird. */
#weightStatsGrid > #dashboardStatsEditBtn {
    align-self: center;
    width: fit-content;
    margin: 14px auto 0;
}

/* .dashboard-stats-header enthaelt jetzt nur noch den Gast-Hinweis (der
   "Anpassen"-Button sitzt oben stattdessen am Ende der Karte) - ist dieser bei
   eingeloggten Nutzern ausgeblendet, bliebe sonst ein leerer Abstandhalter
   (min-height/margin-bottom) uebrig. */
.dashboard-stats-header:has(#dashboardStatsGuestHint[style*="display: none"]) {
    display: none;
}

/* Ersetzt beim Gast den Bearbeiten-Button 1:1 an derselben Stelle - macht
   direkt am Ort der (fehlenden) Personalisierung klar, was ein Account
   bringt, statt nur auf die separate Login-Werbekarte weiter oben zu setzen. */
.dashboard-stats-guest-hint {
    background: none;
    border: 1px dashed var(--border-color);
    color: var(--text-muted);
    border-radius: 18px;
    padding: 4px 12px;
    font-size: 0.78rem;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s;
}
.dashboard-stats-guest-hint:hover {
    color: var(--primary-color-text);
    border-color: var(--primary-color);
}

.dashboard-stats-preset-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 15px;
    padding-bottom: 12px;
    border-bottom: 1px dashed var(--border-color);
}
.dashboard-stats-preset-label {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-right: 4px;
}
#dashboardStatsPresetSelect {
    flex: 1;
    min-width: 160px;
    padding: 8px;
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 0.9rem;
}

.dashboard-stats-editor-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 10px;
    margin-bottom: 8px;
    background-color: var(--bg-color);
    border-radius: 8px;
    position: relative;
}
.dashboard-stats-row-label-input {
    flex-basis: 100%;
    padding: 6px 8px;
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 0.85rem;
    margin-bottom: 2px;
}
.dashboard-stats-editor-row select {
    flex: 1;
    min-width: 120px;
    padding: 8px;
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 0.9rem;
}
.dashboard-stats-row-controls {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
    margin-left: auto;
}
.dashboard-stats-row-btn {
    background-color: var(--card-bg);
    border: 1px solid var(--border-color);
    color: var(--text-muted);
    font-size: 0.9rem;
    cursor: pointer;
    width: 30px;
    height: 30px;
    border-radius: 6px;
    line-height: 1;
    transition: color 0.2s, border-color 0.2s;
}
.dashboard-stats-row-btn:hover:not(:disabled) {
    color: var(--primary-color-text);
    border-color: var(--primary-color);
}
.dashboard-stats-row-btn:disabled {
    opacity: 0.35;
    cursor: default;
}
.dashboard-stats-row-btn.dashboard-stats-row-remove:hover:not(:disabled) {
    color: var(--danger-color);
    border-color: var(--danger-color);
}

/* Wochenrückblick-Kacheln (2x2 Grid, siehe #weeklyReportStats): feste
   Mindesthöhe + Umbruch, damit Kacheln mit .stat-sub (Meilenstein-Vergleich)
   nicht unruhig neben kürzeren Kacheln ohne Subline wirken. */
.weekly-report-stat-item {
    min-height: 84px;
    box-sizing: border-box;
    text-align: center;
}
.weekly-report-stat-item .stat-value,
.weekly-report-stat-item .stat-sub {
    overflow-wrap: break-word;
    word-break: break-word;
}

.form-group {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    margin-bottom: 15px;
}

.input-group {
    flex: 1;
    min-width: 120px;
    display: flex;
    flex-direction: column;
}

label {
    font-size: 0.875rem;
    margin-bottom: 5px;
    font-weight: 500;
}

input,
select {
    padding: 10px;
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 1rem;
    outline: none;
    transition: border-color 0.2s, background-color 0.3s, color 0.3s;
    /* color-scheme wird eigentlich vererbt - <html> bekommt per JS
       (updateThemeColorMeta() in globals.js) bereits "light" bzw. "dark"
       passend zum tatsaechlich gewaehlten App-Theme gesetzt. Ein hartes
       "light dark" HIER hat diese Vererbung fuer input/select durchbrochen
       und dem Browser stattdessen erlaubt, sich bei nativ gerenderten
       Controls (v.a. unstyled Checkboxen/Radios, siehe .message-* Umfrage-
       Optionen) am System-Farbschema zu orientieren - bei System-Dark +
       App-Light wurden Checkboxen dadurch dunkel statt hell gerendert. */
    color-scheme: inherit;
}

input:focus,
select:focus {
    border-color: var(--primary-color);
}

input:focus-visible,
select:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 1px;
}

/* Checkboxen/Radios sollen die native, kleine Kontrollkaestchen-Optik behalten -
   die generische .input-Regel oben (Padding/Hintergrund/Border/Radius) ist fuer
   Text-/Select-Felder gedacht und macht jede Checkbox sonst zu einer
   unterschiedlich grossen, verschachtelten Box statt eines gleichfoermigen
   kleinen Haekchens (auffaellig bei mehreren gestapelten Checkboxen). */
input[type="checkbox"],
input[type="radio"] {
    width: 16px;
    height: 16px;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    flex-shrink: 0;
}

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

.skip-link {
    position: absolute;
    top: -100px;
    left: 10px;
    z-index: 10000;
    padding: 10px 16px;
    background: var(--primary-btn-bg);
    color: white;
    border-radius: 0 0 6px 6px;
    text-decoration: none;
    font-weight: 600;
    transition: top 0.2s;
}

.skip-link:focus {
    top: 0;
}

button.action-btn {
    background-color: var(--primary-btn-bg);
    color: white;
    border: none;
    padding: 12px 20px;
    border-radius: 6px;
    font-size: 1rem;
    cursor: pointer;
    font-weight: 500;
    transition: background-color 0.2s;
    width: 100%;
}

button.action-btn:hover {
    background-color: var(--primary-hover);
}

button.secondary {
    background-color: var(--secondary-color);
}

button.secondary:hover {
    background-color: var(--secondary-hover);
}

button.danger {
    background-color: var(--danger-btn-bg);
}

button.danger:hover {
    background-color: var(--danger-hover);
}

.row {
    display: flex;
    gap: 15px;
    align-items: flex-end;
    flex-wrap: wrap;
}

.calendar-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

/* Pfeil-Optik wie die Auf/Ab-Buttons beim Bearbeiten der Statistik-Boxen
   (.dashboard-stats-row-btn in style.css) - dasselbe feste 30x30-Quadrat,
   derselbe dezente Rahmen/Hover, nur mit ◀/▶ statt ▲/▼ als Inhalt (siehe
   index.php). */
.calendar-header button {
    background-color: var(--card-bg);
    border: 1px solid var(--border-color);
    color: var(--text-muted);
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    transition: color 0.2s, border-color 0.2s;
}

.calendar-header button:hover {
    color: var(--primary-color-text);
    border-color: var(--primary-color);
}

/* Monat/Jahr bekommt einen eigenen, leichten Rahmen als Box - grenzt die
   Anzeige zwischen den beiden Pfeil-Buttons sichtbar ab, statt frei zu
   schweben. Feste Hoehe + eigene, kleinere Schriftgroesse statt der
   ererbten h2-Groesse (1.25rem) - siehe .day-modal-nav h2 fuer denselben
   Fix bei der Tages-Detailansicht: wirkte sonst deutlich hoeher/wuchtiger
   als die 30x30px Pfeil-Buttons daneben (.calendar-header button). */
#calendarMonthTitle {
    height: 30px;
    line-height: 28px;
    font-size: 0.9rem;
    padding: 0 12px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background-color: var(--card-bg);
    font-weight: 500;
    cursor: pointer;
    box-sizing: border-box;
}

.day-modal-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin-top: 34px;
    margin-bottom: 15px;
}

.day-modal-nav h2 {
    flex: 1;
    text-align: center;
    margin-bottom: 0;
    /* Feste Hoehe + eigene, kleinere Schriftgroesse statt der ererbten
       h2-Groesse (1.25rem) - die Box wirkte dadurch deutlich hoeher/
       wuchtiger als die 30x30px Pfeil-Buttons daneben (.day-modal-nav
       button). Jetzt exakt auf deren Hoehe/Optik abgestimmt. */
    height: 30px;
    line-height: 28px;
    font-size: 0.9rem;
    padding: 0 12px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background-color: var(--card-bg);
    box-sizing: border-box;
    /* Klick springt zu heute (siehe tracking.js) - analog zu #calendarMonthTitle. */
    cursor: pointer;
}

.day-modal-nav button {
    background-color: var(--card-bg);
    border: 1px solid var(--border-color);
    color: var(--text-muted);
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    flex-shrink: 0;
    transition: color 0.2s, border-color 0.2s;
}

.day-modal-nav button:hover {
    color: var(--primary-color-text);
    border-color: var(--primary-color);
}

.calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 5px;
    text-align: center;
}

.calendar-weekday {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: 600;
    padding-bottom: 5px;
}

.calendar-day {
    aspect-ratio: 1;
    background-color: var(--bg-color);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
    cursor: pointer;
    font-size: 0.95rem;
    transition: background-color 0.2s, border-color 0.2s;
    border: 1px solid var(--border-color);
}

.calendar-day:hover {
    border-color: var(--primary-color);
}

/* Leere Fuellzellen vor dem Monatsanfang sind keine echten Tage - bleiben
   ohne den neuen Rahmen, sonst wirkt der Kalender links oben verzahnt. */
.calendar-day.empty {
    background: none;
    cursor: default;
    border-color: transparent;
}

/* "Heute" auf einen Blick erkennbar: gefuellter Akzent-Kreis um die Zahl,
   der Status-Balken (siehe .status-bar) bleibt unveraendert bestehen -
   beides ergaenzt sich, statt sich zu ersetzen. */
.calendar-day-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.calendar-day.today .calendar-day-number {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background-color: var(--primary-color);
    color: #fff;
    font-weight: 700;
}

.status-bar {
    width: 70%;
    height: 4px;
    border-radius: 2px;
    position: absolute;
    bottom: 8px;
}

/* Zweiter Balken fuer den Sport-Status (siehe renderCalendar() in
   tracking.js) - duenner und weiter unten in der Zelle, damit beide
   Balken nebeneinander (untereinander) sichtbar bleiben. */
.status-bar.status-bar-activity {
    width: 55%;
    height: 3px;
    bottom: 3px;
}

.status-bar.green { background-color: var(--success-color); }
.status-bar.red { background-color: var(--danger-color); }
.status-bar.blue { background-color: var(--primary-color); }
.status-bar.orange { background-color: var(--warning-color); }
.status-bar.purple { background-color: var(--perfect-color); }

/* Notiz-Indikator (siehe renderCalendar() in tracking.js) - kleines Icon
   oben rechts in der Tageszelle, Notiztext selbst steht im title-Attribut
   (natives Mouseover-Tooltip). */
.calendar-day-note-icon {
    position: absolute;
    top: 2px;
    right: 3px;
    font-size: 0.65rem;
    line-height: 1;
}

.modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.5);
    backdrop-filter: blur(4px);
    align-items: center;
    justify-content: center;
}

.modal.show {
    display: flex;
}

.modal-content {
    width: 100%;
    max-width: 420px;
    position: relative;
    margin: 20px;
    max-height: 90vh;
    overflow-y: auto;
}

.close-btn {
    position: absolute;
    top: 15px;
    right: 20px;
    font-size: 1.5rem;
    cursor: pointer;
    color: var(--text-muted);
    line-height: 1;
    background: none;
    border: none;
    padding: 0;
    font-family: inherit;
}

.close-btn:hover {
    color: var(--text-color);
}

.day-entry-item, .goal-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 0;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.9rem;
}

.day-entry-item:last-child, .goal-item:last-child {
    border-bottom: none;
}

.btn-group {
    display: flex;
    gap: 5px;
}

.small-btn {
    padding: 4px 8px;
    font-size: 0.8rem;
    border-radius: 4px;
    border: none;
    cursor: pointer;
    color: white;
}

.edit-btn { background-color: var(--primary-btn-bg); }
.delete-btn-sm { background-color: var(--danger-btn-bg); }

.auth-section, .io-section, .goal-section {
    padding: 15px;
    background-color: var(--bg-color);
    border-radius: 8px;
    margin-top: 15px;
    border: 1px solid var(--border-color);
}

@media (max-width: 600px) {
    .form-group, .row {
        flex-direction: column;
        align-items: stretch;
    }
}

/* Admin: Lebensmittelverwaltung - auf schmalen Bildschirmen reichen die vier
   festbreiten Spalten (ID 50px + Logo 60px + Mutterkonzern-Logo 120px) plus
   Gaps/Padding nicht annähernd fürs Displaybreite; ID und Mutterkonzern-Logo
   sind ueber die aufgeklappten Details weiterhin einsehbar und werden hier
   ausgeblendet, damit der Name genug Platz bekommt. */
@media (max-width: 600px) {
    .admin-food-col-id,
    .admin-food-col-parent {
        display: none !important;
    }
    .admin-food-col-logo {
        width: 50px !important;
        padding-right: 8px !important;
    }
    .admin-food-col-action {
        width: auto !important;
        white-space: nowrap;
    }
    .admin-food-details {
        flex-direction: column !important;
    }
}

/* Floating Action Button (FAB) */
.fab-btn {
    position: fixed;
    bottom: 30px;
    right: 30px;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background-color: var(--primary-color);
    color: white;
    border: none;
    box-shadow: 0 4px 10px rgba(0,0,0,0.3);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 900;
    transition: transform 0.2s, background-color 0.3s;
}

.fab-btn:hover {
    background-color: var(--primary-hover);
    transform: scale(1.05);
}

.fab-btn:active {
    transform: scale(0.95);
}

@media (max-width: 600px) {
    .fab-btn {
        bottom: 20px;
        right: 20px;
        width: 55px;
        height: 55px;
    }
}

/* Kalorien-Tracking: Mehrfach-Erfassungszeilen. Der Name steht immer in
   eigener Zeile; Menge/Einheit/kcal/Löschen wandern darunter, sobald der
   Platz auf Mobile knapp wird - sonst quetscht sich die Mengen-Box bei
   langen Einheitennamen (z.B. "Esslöffel") auf unlesbar klein zusammen. */
.calorie-dynamic-row {
    flex-wrap: wrap;
}

.cal-row-controls {
    display: flex;
    gap: 8px;
    align-items: center;
    flex: 3;
    min-width: 220px;
}

@media (max-width: 600px) {
    /* .cal-row-name-col traegt ein Inline-style="flex: 2; min-width: 120px;"
       (siehe tracking.js) - dafuer bleibt !important hier noetig. */
    .cal-row-name-col {
        flex: 1 1 100% !important;
        min-width: 0 !important;
    }
    /* .cal-row-controls hat dagegen kein Inline-style - kein !important noetig. */
    .cal-row-controls {
        flex: 1 1 100%;
        min-width: 0;
    }
}

/* Menge/Kalorien-Faktor (siehe applyCalorieFactor() in tracking.js) - als
   <details>/<summary> ("schlichtes Dropdown") umgesetzt statt permanent
   sichtbarer Zeile, damit die selten genutzte Faktor-Eingabe nicht staendig
   Platz im Kalorien-Tab beansprucht - Eingabe + beide Buttons erscheinen erst
   nach Aufklappen. */
.cal-factor-row {
    margin-bottom: 10px;
    padding: 8px 10px;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
}

.cal-factor-label {
    display: block;
    font-size: 0.8rem;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
}

.cal-factor-row[open] .cal-factor-label {
    margin-bottom: 6px;
}

.cal-factor-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
}

.cal-factor-controls input {
    flex: 1 1 80px;
    min-width: 70px;
    padding: 6px 8px;
    box-sizing: border-box;
}

.cal-factor-controls button {
    flex: 1 1 calc(50% - 4px);
    min-width: 110px;
    width: auto;
    padding: 6px 10px;
    font-size: 0.85rem;
    white-space: nowrap;
}

/* Auf sehr schmalen Karten (v.a. App-Layout auf dem Handy, wo die
   Erfassungs-Karte durch Container-/Karten-Padding nochmal schmaler ist als
   die reine Geraetebreite) reicht der Platz oft nicht mal fuer Eingabe +
   einen Button nebeneinander - dann lieber sauber untereinander stapeln als
   krumm umbrechen. */
@media (max-width: 480px) {
    .cal-factor-controls input,
    .cal-factor-controls button {
        flex: 1 1 100%;
    }
}

/* --- Visuelle Fortschrittsleiste --- */
.progress-section {
    background-color: var(--card-bg);
    border-radius: 12px;
    padding: 20px;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
    margin-bottom: 2px;
    display: none; /* Wird nur eingeblendet, wenn ein Ziel gesetzt ist */
}

.progress-header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 12px;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.progress-track {
    width: 100%;
    height: 14px;
    background-color: var(--bg-color);
    border-radius: 7px;
    position: relative;
    overflow: hidden;
    box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}

.progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--primary-color), var(--success-color));
    border-radius: 7px;
    width: 0%;
    transition: width 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- Trend-Pfeile (SVGs) --- */
.trend-icon {
    display: inline-block;
    vertical-align: middle;
    margin-left: 4px;
    margin-top: -2px;
    width: 20px;
    height: 20px;
    transition: transform 0.3s ease;
}

.trend-up { color: var(--danger-color-text); }
.trend-down { color: var(--success-color-text); }
.trend-flat { color: var(--text-muted); }


/* --- 2FA Toggle Switch --- */
.switch-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;
    margin-top: 15px;
    border-top: 1px solid var(--border-color);
}

.switch {
    position: relative;
    display: inline-block;
    width: 46px;
    height: 24px;
}

.switch input { 
    opacity: 0;
    width: 0;
    height: 0;
}

.slider-round {
    position: absolute;
    cursor: pointer;
    top: 0; left: 0; right: 0; bottom: 0;
    background-color: var(--border-color);
    transition: .3s;
    border-radius: 24px;
}

.slider-round:before {
    position: absolute;
    content: "";
    height: 18px; width: 18px;
    left: 3px; bottom: 3px;
    background-color: white;
    transition: .3s;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}

input:checked + .slider-round {
    background-color: var(--success-color);
}

input:checked + .slider-round:before {
    transform: translateX(22px);
}

/* --- Mobile Header Optimierung --- */
@media (max-width: 600px) {
    .app-header {
        flex-direction: column;
        align-items: center; /* Zentriert die Überschrift */
        gap: 15px;
        margin-bottom: 15px;
    }
    
    .app-header h1 {
        justify-content: center; /* Symbole zentriert an die Überschrift binden */
        font-size: 1.5rem;
    }
    
    .header-actions {
        display: flex;
        width: 100%;
        justify-content: center; /* Buttons perfekt in der Mitte sammeln */
        gap: 15px;
    }
    
    .icon-btn {
        flex-shrink: 0;
        /* Minimale Anpassung des Paddings, damit alles geschmeidig passt */
        padding: 0 14px; 
    }
}

/* --- Aufklappbare Einstellungen (Accordion) --- */
.settings-accordion {
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    margin-bottom: 15px;
    overflow: hidden;
}

.settings-accordion summary {
    padding: 12px 15px;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: var(--primary-color-text);
}

.settings-accordion summary::-webkit-details-marker { display: none; }
.settings-accordion summary::after { content: "▼"; font-size: 0.8rem; transition: transform 0.2s; }
.settings-accordion[open] summary::after { transform: rotate(180deg); }

.settings-accordion-content {
    padding: 15px;
    border-top: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    gap: 15px;
}

/* --- Ausklappbare Mahlzeiten im Tages-Detail-Popup (analog zu .settings-accordion, aber kompakter) --- */
.meal-accordion {
    border-bottom: 1px solid var(--border-color);
}

.meal-accordion:last-of-type {
    border-bottom: none;
}

.meal-accordion summary {
    padding: 10px 0;
    font-weight: bold;
    font-size: 0.9rem;
    cursor: pointer;
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.meal-accordion summary::-webkit-details-marker { display: none; }
.meal-accordion summary::after { content: "▼"; font-size: 0.7rem; color: var(--text-muted); margin-left: 8px; transition: transform 0.2s; }
.meal-accordion[open] summary::after { transform: rotate(180deg); }

.meal-accordion-sum {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: normal;
}

.meal-accordion-content {
    padding-bottom: 8px;
}

/* --- Animiertes Wasserglas --- */
.water-chart-container {
    text-align: center;
    padding: 10px 0;
}

/* --- Animiertes Wasserglas (Kompakte Höhe, dynamische Breite) --- */
/* Breite folgt fluessig der (jetzt festen) Breite von .water-chart-side
   (siehe dort und .water-layout-wrapper), statt einer eigenen festen Breite.
   max-width wurde bewusst auf 65px (statt vorher 130px) halbiert - auf
   schmalen Handys nahm das Glas sonst zu viel Platz ein, der eigentlich den
   Stat-Boxen in .water-stats-side fehlte. min-width haelt das Glas trotzdem
   bei 30px (4px Rahmen + 24px Eck-Radius bleibt auch dabei noch klar als Glas
   erkennbar). */
.water-glass {
    width: 100%;
    max-width: 65px; /* Mobil schmaler, damit die Stat-Boxen genug Platz haben */
    min-width: 30px;
    height: 150px; /* Angenehme, feste Höhe */
    position: relative;
    overflow: hidden;
    border: 4px solid var(--border-color);
    border-top: none;
    border-radius: 0 0 24px 24px;
    background: var(--bg-color);
    margin: 0 auto;
    box-shadow: inset 0 4px 6px rgba(0,0,0,0.03);
}

.water-fill {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    background: linear-gradient(180deg, #60a5fa, var(--primary-color));
    height: 0%; 
    transition: height 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}

.water-wave {
    position: absolute;
    top: -5px; /* Perfekt bündig, kein Spalt mehr */
    left: 0;
    width: 200%;
    height: 8px;
    background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 120 8" xmlns="http://www.w3.org/2000/svg"><path d="M0 4 C 30 8, 30 0, 60 4 C 90 8, 90 0, 120 4 L 120 8 L 0 8 Z" fill="%2393c5fd"/></svg>') repeat-x;
    background-size: 40px 8px;
    animation: wave-slide 2s linear infinite;
}

@keyframes wave-slide {
    0% { transform: translateX(0); }
    100% { transform: translateX(-40px); }
}

.water-stats-text {
    font-size: 1.1rem;
    color: var(--text-color);
    margin-bottom: 10px;
}

/* --- Side-by-Side Layout für den Wasser-Tab (auch mobil nebeneinander) --- */
.water-layout-wrapper {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 15px;
    padding: 5px 0;
    width: 100%;
}

/* Feste (statt anteilige) Breite: .water-chart-side und .water-stats-side
   hatten vorher flex:1 / flex:1.2 mit flex-basis:0% - die Spaltenbreite kam
   dadurch rein aus dem Grow-Verhaeltnis und war komplett unabhaengig davon,
   wie breit das Glas (.water-glass, max-width) tatsaechlich gerendert wurde.
   Das Glas schmaler zu machen hat den Stat-Boxen dadurch KEINEN zusaetzlichen
   Platz gebracht, es entstand nur Leerraum neben dem Glas. Jetzt bekommt die
   Glas-Spalte nur noch so viel fixe Breite, wie das Glas selbst braucht (siehe
   .water-glass max-width), und .water-stats-side (flex:1) uebernimmt den
   kompletten Rest. */
.water-chart-side {
    flex: 0 0 90px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.water-stats-side {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
}

.water-stat-card {
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 8px 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.85rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.02);
}

.water-stat-card .stat-label {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.water-funfact-card {
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 10px;
    text-align: center;
    font-size: 0.8rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.02);
}

/* Extra Feinabstimmung für sehr kleine Displays, damit das Grid stabil bleibt */
@media (max-width: 400px) {
    .water-layout-wrapper {
        gap: 10px;
    }
    .water-glass {
        /* Breite ergibt sich weiterhin fluessig aus der Basis-Regel (min-width: 30px) */
        height: 130px;
    }
    .water-stat-card, .water-funfact-card {
        padding: 6px 8px;
        font-size: 0.75rem;
    }
    .water-stats-text {
        font-size: 0.8rem;
    }
}


/* --- Bestenliste Styling --- */
#chartLeaderboard table th, #chartLeaderboard table td {
    padding: 12px 10px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-color);
}
#chartLeaderboard table tbody tr:hover {
    background-color: var(--bg-color);
}

/* --- Ziele-Verlauf (Profil > Koerpermasse & Ziele), siehe renderCalorieGoalList()
   in tracking.js - eine Zeile pro Verlaufseintrag, eine Spalte je Zielgroesse.
   #goalListContainer selbst traegt overflow-x:auto (siehe modals_main.php),
   damit die Tabelle auf schmalen Bildschirmen scrollt statt sich zu quetschen. */
.goal-history-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
    white-space: nowrap;
}
.goal-history-table th, .goal-history-table td {
    padding: 8px 10px;
    text-align: left;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-color);
}
.goal-history-table th {
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.7rem;
    letter-spacing: 0.03em;
}
.goal-history-table td.goal-history-empty-cell {
    color: var(--text-muted);
}
.goal-history-table td.goal-history-actions {
    text-align: right;
    white-space: nowrap;
}
.goal-history-table tbody tr:hover {
    background-color: var(--bg-color);
}


/* --- Glassmorphism Design für Karten --- */
/* Kein !important mehr noetig: die spaeter im Quelltext stehende
   ".card"-Strukturregel setzt kein eigenes background mehr, dark-mode/
   high-contrast-Varianten gewinnen ueber hoehere Selektor-Spezifitaet. */
.card {
    /* Etwas transparenter (0.65 statt 0.75), damit man den Hintergrund besser sieht */
    background: rgba(255, 255, 255, 0.65);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.6);
    box-shadow: 0 4px 24px -1px rgba(0, 0, 0, 0.05);
}

body.dark-mode .card {
    background: rgba(30, 41, 59, 0.65);
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 4px 24px -1px rgba(0, 0, 0, 0.2);
}

/* Standard für Mobilgeräte: Kompakte Diagramm-Höhe */
.chart-container {
    position: relative;
    height: 280px; 
    width: 100%;
}

/* Eigenstaendige Hilfsprogramm-Seiten (Backup, Bilder aufraeumen, ...) nutzen
   .container fuer die Grundlagen (Flex-Spalte, Abstand), sollen aber NICHT wie
   das Hauptdashboard weiter unten in ein 2-spaltiges Desktop-Grid wechseln -
   die Elemente/Reihenfolge (app-header/greeting/etc.), auf die sich dieses
   Grid stuetzt, gibt es auf diesen Seiten gar nicht. Kompund-Selektor (zwei
   Klassen) hat hoehere Spezifitaet als die einfache .container-Regel weiter
   unten und gewinnt daher unabhaengig von der Reihenfolge im Quelltext -
   vorher blockierte ein inline max-width auf diesen Seiten die
   Desktop-Erweiterung komplett, wodurch sie auf grossen Bildschirmen sehr
   schmal wirkten. */
.container.tool-page-container {
    max-width: 800px;
}
@media (min-width: 1024px) {
    .container.tool-page-container {
        max-width: 1100px;
        /* Ueberschreibt die 2-spaltige Desktop-Grid-Regel der Basis-.container-Klasse
           weiter unten (gleiche Media Query) - Tool-Seiten wie backup.php haben keines
           der Grid-Elemente (app-header/greeting/etc.), auf die sich dieses Layout
           stuetzt, und wuerden ihre Karten sonst faelschlich nebeneinander statt
           untereinander anordnen. */
        display: block;
    }

    /* display:block oben macht das gap:20px der Basis-.container-Klasse wirkungslos
       (gap gilt nur fuer flex/grid) - ohne dieses Ersatz-margin ruecken Ueberschrift
       und Inhalt sowie alle Karten auf Tool-Seiten ab 1024px nahtlos aneinander. */
    .container.tool-page-container > * + * {
        margin-top: 20px;
    }
}

/* --- Desktop-Optimierung (Maximale Breite ausreizen) --- */
@media (min-width: 1024px) {
    .container {
        max-width: 1800px; /* Noch mehr maximale Breite auf großen Bildschirmen - kein !important noetig, einzige weitere .container-Regel ist die Basis-Regel weiter oben mit gleicher Spezifitaet */
        padding: 20px 50px;
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 28px;
        align-items: stretch;
    }

    .app-header,
    .greeting,
    .progress-section,
    .dashboard-full-width,
    #motivationContainer,
    .calendar-full-width {
        grid-column: span 2;
    }

    /* Ab hier wieder normale DOM-Reihenfolge: Statistiken links, Erfassungs-Karte rechts */
    #newEntryCard,
    #weightStatsGrid,
    .calendar-full-width,
    #communityDivider,
    #globalStatsCard {
        order: 0;
    }

    .chart-container {
        height: 480px;
    }

    .calendar-day {
        aspect-ratio: auto;
        height: 48px;
    }

    /* Das Glas wird deutlich breiter, bleibt aber in der Höhe kompakt (150px).
       max-width muss hier explizit erhoeht werden, sonst begrenzt die
       Basis-Regel (max-width: 65px, fuer die schmale Mobil-Breite) das
       Glas weiterhin auf 65px. .water-chart-side braucht dafuer ebenfalls
       mehr feste Breite als die 90px der Mobil-Basis-Regel, sonst wuerde das
       220px breite Glas seine eigene Spalte sprengen. */
    .water-chart-side {
        flex: 0 0 240px;
    }

    .water-glass {
        width: 220px;
        max-width: 220px;
        height: 150px;
    }
}

/* --- Toast-Benachrichtigung (Feedback) --- */
.toast {
    position: fixed;
    bottom: 30px;
    left: 50%;
    transform: translateX(-50%) translateY(100px);
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    padding: 12px 24px;
    border-radius: 30px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.15);
    z-index: 2000;
    opacity: 0;
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s ease;
    font-size: 0.9rem;
    font-weight: 500;
    pointer-events: none;
    white-space: nowrap;
}

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

/* --- Mahlzeiten Tags --- */
.meal-tag {
    font-size: 0.75rem;
    padding: 2px 6px;
    border-radius: 4px;
    background-color: var(--bg-color);
    color: var(--text-muted);
    border: 1px solid var(--border-color);
    margin-right: 8px;
    display: inline-block;
}
.meal-group-title {
    font-size: 0.9rem;
    color: var(--text-color);
    margin-top: 10px;
    margin-bottom: 5px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 3px;
}

.motivation-timer-bar {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 4px; /* Etwas satter gemacht */
    background-color: var(--border-color);
}

.motivation-timer-fill {
    height: 100%;
    width: 0%;
    background-color: var(--primary-color);
    animation: motivationProgress 60s linear infinite;
    border-radius: 0 2px 2px 0;
}

@keyframes motivationProgress {
    0% { width: 0%; }
    100% { width: 100%; }
}

.moon-element {
    position: fixed;
    top: 30px;
    right: 40px;
    width: 60px;
    height: 60px;
    /* Muss ueber .container (position:relative; z-index:1) liegen, sonst
       verschwindet die Dekoration ueberall dort, wo eine opake Karte/der
       Header darunterliegt - vorher z-index:0 liess nur die Stellen sichtbar,
       an denen zufaellig kein Content darueber lag (siehe .stars-element
       unten fuer das gleiche, dort viel deutlicher sichtbare Problem: von 25
       zufaellig ueber die ganze Seite verteilten Sternen blieben nur die paar
       in echten Luecken sichtbar). pointer-events:none verhindert weiterhin
       jede Interaktions-Blockade trotz des jetzt hoeheren z-index. */
    z-index: 2;
    pointer-events: none;
    opacity: 0.9;
    transition: opacity 0.5s ease;
    display: none;
    filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.6));
}

/* Der Mond erscheint EXAKT NUR nachts - bewusst unabhaengig vom Farbschema
   (siehe unten, Sonne/Sterne folgen derselben rein zeitbasierten Logik statt
   an Dark/Light Mode gekoppelt zu sein). Kein !important noetig:
   body.is-night .moon-element hat mit 2 Klassen eine hoehere Spezifitaet als
   die einfache .moon-element-Regel oben und gewinnt daher immer,
   unabhaengig von der Reihenfolge im Quelltext. */
body.is-night .moon-element {
    display: block;
}

/* Sonne: Pendant zum Mond oben, gleiche Position/Groesse, ebenfalls rein
   zeitbasiert (Tag) statt an das Farbschema gekoppelt. */
.sun-element {
    position: fixed;
    top: 30px;
    right: 40px;
    width: 60px;
    height: 60px;
    z-index: 2;
    pointer-events: none;
    opacity: 0.9;
    transition: opacity 0.5s ease;
    display: none;
    filter: drop-shadow(0 0 12px rgba(251, 191, 36, 0.6));
}

body.is-day .sun-element {
    display: block;
}

/* Sterne: erscheinen zusammen mit dem Mond nachts (siehe populateStars() in
   globals.js fuer die zufaellig plazierten .star-Kinder). */
.stars-element {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 2;
    display: none;
}

body.is-night .stars-element {
    display: block;
}

.star {
    position: absolute;
    border-radius: 50%;
    background: #ffffff;
    box-shadow: 0 0 4px 1px rgba(255, 255, 255, 0.8);
    animation: starTwinkle 3s ease-in-out infinite;
}

/* Im Hellmodus etwas gedaempft, reines Weiss war dort kaum sichtbar/wirkte
   wie ein Darstellungsfehler statt einer Dekoration. */
body:not(.dark-mode) .star {
    background: #94a3b8;
    box-shadow: 0 0 3px 1px rgba(148, 163, 184, 0.5);
}

@keyframes starTwinkle {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 1; }
}

/* Harter Aus-Schalter fuer alle drei Himmelselemente, siehe Einstellungen >
   Anzeige > "Sonne, Mond & Sterne zeigen" (applyCelestialDecorationsPreference
   in globals.js). !important noetig, da die einzelnen Sichtbarkeits-Regeln
   oben ueber Mehrfach-Klassen-Selektoren eine hoehere Spezifitaet haben. */
body.celestial-decorations-off .moon-element,
body.celestial-decorations-off .sun-element,
body.celestial-decorations-off .stars-element {
    display: none !important;
}


/* Standardgröße für mobile Geräte (strikt begrenzt) */
.app-logo {
    width: 32px;
    height: 32px;
    max-width: 32px;
    max-height: 32px;
    object-fit: contain;
    border-radius: 8px;
    flex-shrink: 0;
}

/* Automatisch größer auf Desktop-Bildschirmen (ab 768px Breite) */
@media (min-width: 768px) {
    .app-logo {
        width: 50px;
        height: 50px;
        max-width: 50px;
        max-height: 50px;
        border-radius: 10px;
    }
}


/* Progress-Section und andere Container mit dem Glas-Effekt ausstatten */
.progress-section {
    background: rgba(255, 255, 255, 0.65);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.6);
    box-shadow: 0 4px 24px -1px rgba(0, 0, 0, 0.05);
}

body.dark-mode .progress-section {
    background: rgba(30, 41, 59, 0.65);
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 4px 24px -1px rgba(0, 0, 0, 0.2);
}

/* --- Account Löschen Slider --- */
.delete-slider-container {
    display: none; 
    position: relative; 
    width: 100%; 
    height: 50px; 
    background: var(--bg-color); 
    border-radius: 25px; 
    border: 1px solid var(--danger-color); 
    overflow: hidden; 
    touch-action: none; /* Wichtig für mobiles Wischen */
    user-select: none;
    margin-top: 10px;
}
.delete-slider-fill {
    position: absolute; 
    left: 0; top: 0; 
    height: 100%; width: 0%; 
    background: rgba(239, 68, 68, 0.2); /* var(--danger-color) transparent */
}
.delete-slider-text {
    position: absolute; 
    width: 100%; 
    text-align: center; 
    line-height: 50px; 
    font-weight: bold; 
    pointer-events: none; 
    color: var(--text-color);
    font-size: 0.9rem;
    z-index: 2;
}
.delete-slider-thumb {
    position: absolute;
    left: 0; top: 0;
    width: 50px; height: 50px;
    background: var(--danger-btn-bg);
    border-radius: 50%; 
    cursor: grab; 
    display: flex; 
    align-items: center; 
    justify-content: center; 
    color: white; 
    font-weight: bold; 
    box-shadow: 0 2px 5px rgba(0,0,0,0.3);
    z-index: 3;
}
.delete-slider-thumb:active {
    cursor: grabbing;
}

/* Einheitliches Karten-Design und Boxen-Struktur */
/* background bewusst NICHT hier gesetzt - das wuerde die weiter oben stehende
   Glassmorphism-.card-Regel unbeabsichtigt ueberschreiben (gleiche
   Selektor-Spezifitaet, aber diese Regel steht spaeter im Quelltext). Der
   Hintergrund wird ausschliesslich von der Glassmorphism-Regel bestimmt. */
.card {
    /* Kein eigenes border mehr (genau wie beim background oben) - sonst
       gewinnt diese Regel in Light Mode per Quelltext-Reihenfolge gegen die
       Glassmorphism-Regel weiter oben (gleiche Spezifitaet) und der
       durchscheinende Glas-Rand rendert nie. Dark Mode/High-Contrast sind
       unbetroffen, deren eigene .card-Regeln haben hoehere Spezifitaet. */
    border-radius: 12px;
    padding: 20px;
    margin-bottom: 16px;
    box-sizing: border-box;
    width: 100%;
}

#globalStatsContainer {
    width: 100%;
    box-sizing: border-box;
}

#globalStatsContainer .card {
    margin-bottom: 0;
}

.leaderboard-sticky-header {
    position: sticky;
    top: 0;
    background: rgba(255, 255, 255, 0.65);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    z-index: 5;
}

body.dark-mode .leaderboard-sticky-header {
    background: rgba(30, 41, 59, 0.65);
}

/* Das Mahlzeiten-Dropdown in einem frischen, markanten Smaragdgrün */
#mealDropdownBtn {
    background: linear-gradient(135deg, #10b981, #059669); /* Satte, frische Smaragd-Töne */
    color: #ffffff;
    border: none;
    font-weight: 500;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
    transition: filter 0.2s ease;
}

#mealDropdownBtn:hover {
    filter: brightness(1.1);
}

/* Das zugehörige Dropdown-Menü mit grünem Akzent */
#mealDropdownMenu {
    background-color: var(--card-bg, #1e293b);
    border: 1px solid #10b981;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}

#mealDropdownMenu button {
    color: var(--text-color, #f8fafc);
}

#mealDropdownMenu button:hover {
    background-color: rgba(16, 185, 129, 0.15);
    /* War hartcodiert auf den Dark-Mode-Wert von --success-color-text - in
       Light Mode dadurch blassgruener Text auf weissem Grund (Audit:
       Kontrast). Der Token liefert in Dark Mode denselben Farbwert, also
       keine sichtbare Aenderung dort. */
    color: var(--success-color-text);
}

/* Dyslexie-freundliche Schrift - siehe @font-face oben und
   globals.js applyDyslexicFontPreference(). "*" oben in dieser Datei setzt
   font-family direkt auf JEDES Element (nicht nur vererbt auf body), daher
   muss der Override hier ebenfalls jedes Element treffen, nicht nur body
   selbst. */
body.dyslexic-font,
body.dyslexic-font * {
    font-family: 'OpenDyslexic', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
}

/* OpenDyslexic wirkt bei gleicher font-size deutlich breiter/groesser als
   die normale Schrift und sprengt sonst so manches Layout (Buttons, Tabs,
   Karten). rem-Groessen sind ueberall relativ zu <html>, daher genuegt eine
   einzige Anpassung hier - wird zusaetzlich zu body auch auf <html> gesetzt,
   siehe globals.js applyDyslexicFontPreference(). */
/* Schriftgroesse aus dem Barrierefreiheit-Menue (Aa-/Aa+, siehe
   applyFontScalePreference in globals.js): skaliert die Wurzel-Schriftgroesse,
   praktisch alle Groessen der App sind in rem angegeben. */
html {
    font-size: calc(100% * var(--a11y-font-scale, 1));
}

html.dyslexic-font {
    font-size: calc(90% * var(--a11y-font-scale, 1));
}

/* Auf kleinen Screens (siehe "Mobile Ansicht"-Breakpoint weiter oben in
   dieser Datei) reicht die generelle 90%-Kompensation nicht: die breitere
   Schrift sprengt dort schneller Buttons/Tabs/Karten, weil kein Platz mehr
   zum Ausweichen da ist - anders als am Desktop, wo der grosse Screen das
   noch kompensiert. */
@media (max-width: 768px) {
    html.dyslexic-font {
        font-size: calc(80% * var(--a11y-font-scale, 1));
    }
}

/* --- Barrierefreiheit-Widget (schwebender Button unten links) --- */
.a11y-widget {
    position: fixed;
    bottom: 30px;
    left: 30px;
    z-index: 9999;
}

.a11y-widget-btn {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background-color: var(--secondary-color, #64748b);
    color: white;
    border: none;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.2s, transform 0.2s;
}

.a11y-widget-btn:hover {
    background-color: var(--secondary-hover, #475569);
    transform: scale(1.05);
}

.a11y-widget-panel {
    position: absolute;
    bottom: 72px;
    left: 0;
    min-width: 260px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.a11y-widget-panel[hidden] {
    display: none;
}

.a11y-widget-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    background: none;
    border: none;
    border-radius: 6px;
    color: var(--text-color);
    text-align: left;
    font-size: 0.9rem;
    padding: 10px 12px;
    cursor: pointer;
}

.a11y-widget-item:hover {
    background-color: var(--bg-color);
}

.a11y-widget-item-check {
    visibility: hidden;
    color: var(--primary-color-text);
    font-weight: 700;
}

.a11y-widget-item[aria-pressed="true"] .a11y-widget-item-check {
    visibility: visible;
}

@media (max-width: 600px) {
    .a11y-widget {
        bottom: 20px;
        left: 20px;
    }
    .a11y-widget-btn {
        width: 55px;
        height: 55px;
    }
}

/* Hoher-Kontrast-Modus: hebt den Glas-Effekt (.card/.progress-section/
   .leaderboard-sticky-header) auf. Muss ganz am Ende der Datei stehen, da
   diese Regeln bei gleicher Spezifitaet sonst von den (spaeter im Quelltext
   stehenden) hell-/dunkelmodus-Glas-Regeln weiter oben ueberschrieben wuerden. */
body.high-contrast {
    background-image: none !important;
}

body.high-contrast .card,
body.high-contrast .progress-section,
body.high-contrast .leaderboard-sticky-header {
    background: var(--bg-color) !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    border: 2px solid var(--border-color) !important;
}

body.high-contrast input,
body.high-contrast select,
body.high-contrast textarea,
body.high-contrast button.action-btn,
body.high-contrast .modal-content {
    border: 2px solid var(--border-color) !important;
}

body.high-contrast :focus-visible {
    outline: 3px solid var(--warning-color) !important;
    outline-offset: 2px !important;
}

/* Die "Heute"-Markierung im Kalender (.calendar-day.today .calendar-day-number
   weiter oben) fuellt normalerweise mit --primary-color + weisser Schrift -
   in High-Contrast ist --primary-color aber ein blasses Pastellblau, das nur
   fuer Text AUF Schwarz gedacht ist, nicht als Flaeche UNTER weisser Schrift
   (Audit: Kontrastrisiko genau im Modus, der maximalen Kontrast garantieren
   soll). Hier stattdessen die garantiert AAA-taugliche Text/Hintergrund-Paarung. */
body.high-contrast .calendar-day.today .calendar-day-number {
    background-color: var(--text-color) !important;
    color: var(--bg-color) !important;
}

/* ============================================================
   MOBILE APP-SHELL (experimentelles Feature - Tab-Leiste unten)
   ------------------------------------------------------------
   Kompletter Rueckbau: $mobileAppShellFeatureEnabled in index.php
   auf false setzen - das zusaetzliche Markup entfaellt dann komplett
   und dieser gesamte Block wird wirkungslos. Ansonsten bleiben alle
   Regeln hier zusaetzlich auf die Klasse "mobile-app-shell-enabled"
   auf <html> beschraenkt, die scripts/globals.js
   (applyMobileAppLayoutPreference) nur setzt, wenn der Schalter
   "App-Layout auf Mobiltelefonen verwenden" in Einstellungen > Anzeige
   aktiv ist - am Desktop und fuer alle anderen Handy-Nutzer aendert
   sich dadurch nichts.
   ============================================================ */

/* Wrapper sind per Default "display: contents" (unsichtbar fuers Boxmodell),
   damit ihre Kinder (Chart-Karte, Statistik-Karten, Footer, ...) sich exakt
   wie bisher als direkte Flex-/Grid-Kinder von .container verhalten, solange
   das Feature nicht aktiv ist - inklusive der bestehenden order/grid-column-
   Regeln fuer #newEntryCard, #weightStatsGrid & Co. weiter oben. */
#mobileScrollArea,
.mobile-tab-group,
#mobileBottomBar {
    display: contents;
}

.mobile-tab-bar {
    display: none;
}

/* Der "Mehr"-Tab-Inhalt (Profil/Einkaufsliste/Einstellungen/Meine Bilanz/
   Barrierefreiheit) hat KEIN Desktop-Aequivalent im Grid - anders als
   .mobile-tab-group oben (das bereits vorhandenen Desktop-Content nur
   umhuellt) darf dieser Wrapper also nicht "contents" sein, sonst wuerde
   sein Inhalt auf dem Desktop-Grid als Streuelemente auftauchen. Per Default
   daher komplett unsichtbar. */
.mobile-only-tab-group {
    display: none;
}

/* Kontextuelle zweite Tab-Leiste (Tracking-Unterreiter bzw. Persoenlich/Global-
   Umschalter fuer Statistiken), die direkt ueber #mobileBottomBar sitzt -
   ebenfalls ohne Desktop-Aequivalent, siehe .mobile-only-tab-group oben. */
.mobile-secondary-tab-bar {
    display: none;
}

/* #entryTabsBar (Gewicht/Kalorien/Wasser/Sport) wird per JS unveraendert in
   die zweite Leiste verschoben (siehe relocateMobileSecondaryNav) und traegt
   dort dieselben .tab-btn-Elemente wie auf dem Desktop - Icon-Spans sind
   daher immer im Markup vorhanden, aber nur dort sichtbar (siehe
   #mobileSecondaryTabBar .tab-btn .mobile-tab-icon weiter unten), damit die
   Desktop-Tabs weiterhin reiner Text bleiben. */
.tab-btn .mobile-tab-icon {
    display: none;
}

@media (max-width: 767px) {
    html.mobile-app-shell-enabled body {
        height: 100vh;
        height: 100dvh;
        overflow: hidden;
        padding: 0;
    }

    html.mobile-app-shell-enabled .container {
        /* Schrumpft statt nur nach unten verschoben zu werden (anders als
           die margin-top-Regel bei .container oben) - body selbst hat hier
           eine harte height:100vh + overflow:hidden (siehe oben), ein reines
           Verschieben wuerde den unteren Teil (Tab-Leiste) also einfach
           abschneiden statt Platz fuer den Sync-Status-Banner zu schaffen. */
        height: calc(100vh - var(--sync-banner-height, 0px));
        height: calc(100dvh - var(--sync-banner-height, 0px));
        max-width: 100%;
        margin: 0;
        margin-top: var(--sync-banner-height, 0px);
        transition: margin-top 0.25s ease, height 0.25s ease;
        gap: 10px;
        padding: 16px 16px 0;
        box-sizing: border-box;
    }

    html.mobile-app-shell-enabled .app-header,
    html.mobile-app-shell-enabled .greeting {
        flex-shrink: 0;
    }

    /* Solange der Sync-Status-Banner sichtbar ist (siehe sync-banner-visible
       in offlineSync.js), nimmt er im App-Layout den Platz des Logo-Headers
       ein, statt zusaetzlich Platz zu beanspruchen - sonst muesste man auf
       der (hier per overflow:hidden eigentlich fixen) Seite zusaetzlich
       scrollen, nur weil kurzzeitig kein Internet da ist. */
    html.mobile-app-shell-enabled.sync-banner-visible .app-header {
        display: none;
    }

    /* Begruessung ist fest oberhalb von #mobileScrollArea verankert (siehe
       oben) statt Teil eines .mobile-tab-group-Wrappers zu sein, daher hier
       per data-active-mobile-tab (siehe activateMobileTab in
       mobileAppShell.js) ausgeblendet, sobald ein anderer Haupt-Tab als
       "Uebersicht" aktiv ist. */
    html.mobile-app-shell-enabled .greeting {
        display: none;
    }

    html.mobile-app-shell-enabled[data-active-mobile-tab="home"] .greeting {
        display: block;
    }

    /* Kompakter Header: kleineres Logo linksbuendig, Begruessung (per
       relocateMobileGreeting in mobileAppShell.js in .app-header verschoben)
       rechts daneben. Das Logo-Fragment (logo.html) setzt seine Groessen
       inline mit !important, daher Verkleinerung per zoom statt ueber
       einzelne font-size/height-Regeln. */
    html.mobile-app-shell-enabled .app-header {
        flex-direction: row;
        flex-wrap: nowrap;
        justify-content: flex-start;
        align-items: center;
        gap: 14px;
        margin-bottom: 0;
    }

    html.mobile-app-shell-enabled .app-header .logo-wrapper {
        zoom: 0.72;
        flex-shrink: 0;
    }

    html.mobile-app-shell-enabled .app-header .greeting {
        flex: 1 1 auto;
        min-width: 0;
        margin: 0;
        font-size: 1.1rem;
        line-height: 1.25;
        text-align: left;
    }

    /* Einziger scrollender Bereich: Header (oben) und Bottom-Bar (unten)
       bleiben fix, dazwischen scrollt nur der aktive Tab-Inhalt.
       position:relative verankert den Pull-to-refresh-Indikator weiter unten. */
    html.mobile-app-shell-enabled #mobileScrollArea {
        display: flex;
        flex-direction: column;
        gap: 20px;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        padding-bottom: calc(var(--mobile-bottom-bar-height, 110px) + var(--mobile-secondary-bar-height, 0px) + 16px);
        position: relative;
    }

    html.mobile-app-shell-enabled .mobile-tab-group {
        display: none;
    }

    html.mobile-app-shell-enabled .mobile-tab-group.mobile-tab-active,
    html.mobile-app-shell-enabled .mobile-only-tab-group.mobile-tab-active {
        display: flex;
        flex-direction: column;
        gap: 20px;
    }

    /* Verlauf/Kalender im App-Layout: keine eigene "Verlauf"-Ueberschrift
       (steht ja schon im Tab-Label unten in der Bottom-Bar) - die normale
       Karten-Box (.card) bleibt aber bewusst erhalten, wie auf jeder anderen
       Seite/Tab auch, statt eigens dafuer aus der Designsprache
       auszuscheren. Der Kalender soll trotzdem die ganze verfuegbare Flaeche
       fuellen OHNE dass darin gescrollt werden muss (siehe grid-auto-rows
       weiter unten fuer den eigentlichen Mechanismus dahinter). */
    html.mobile-app-shell-enabled .calendar-history-title {
        display: none;
    }

    html.mobile-app-shell-enabled .mobile-tab-group[data-mobile-tab="history"].mobile-tab-active {
        flex: 1;
        min-height: 0;
    }

    html.mobile-app-shell-enabled .calendar-full-width {
        box-sizing: border-box;
        flex: 1;
        display: flex;
        flex-direction: column;
        min-height: 0;
    }

    /* Nur EINE explizite Zeile (Wochentags-Kuerzel, "auto" = Inhaltshoehe) -
       die eigentlichen Wochen-Zeilen entstehen implizit durchs Auto-Placement
       (renderCalendar() erzeugt je nach Monat 4-6 Wochen-Zeilen, OHNE
       auf eine feste Anzahl aufzufuellen) und teilen sich per
       grid-auto-rows die verbleibende Hoehe gleichmaessig - so bleibt es bei
       jeder Wochenanzahl exakt bildschirmfuellend ohne Leerraum oder Scrollen. */
    html.mobile-app-shell-enabled .calendar-full-width .calendar-grid {
        flex: 1;
        min-height: 0;
        grid-template-rows: auto;
        grid-auto-rows: 1fr;
    }

    html.mobile-app-shell-enabled .calendar-full-width .calendar-day {
        aspect-ratio: unset;
    }

    html.mobile-app-shell-enabled .mobile-tab-bar {
        display: flex;
    }

    /* Logo + Begruessung bleiben oben - Shop/Einstellungen/Bilanz/Profil
       ziehen in den "Mehr"-Tab um (siehe .mobile-only-tab-group), der
       schwebende FAB und das Barrierefreiheit-Widget entfallen: die
       Tab-Leiste und die Switches im "Mehr"-Tab uebernehmen ihre Funktion. */
    html.mobile-app-shell-enabled .header-actions,
    html.mobile-app-shell-enabled .fab-btn,
    html.mobile-app-shell-enabled .a11y-widget {
        display: none;
    }

    /* Admin-Dashboard-Link zieht ebenfalls in den "Mehr"-Tab um (#moreAdminItem
       in index.php) - #adminSection traegt ein JS-gesetztes Inline-style
       (display:block/none je nach isAdmin), daher hier !important noetig. */
    html.mobile-app-shell-enabled #adminSection {
        display: none !important;
    }

    html.mobile-app-shell-enabled #mobileBottomBar {
        display: flex;
        flex-direction: column;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 950;
        background: var(--card-bg);
        border-top: 1px solid var(--border-color);
        box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }

    /* Sitzt direkt ueber der Haupt-Tab-Leiste (deren gemessene Hoehe als
       CSS-Var), wird per JS (mobileAppShell.js) nur fuer die Haupt-Tabs
       "tracking"/"stats" eingeblendet - siehe .mobile-secondary-visible. */
    html.mobile-app-shell-enabled .mobile-secondary-tab-bar {
        display: none;
        position: fixed;
        left: 0;
        right: 0;
        bottom: var(--mobile-bottom-bar-height, 110px);
        z-index: 940;
        background: var(--card-bg);
        border-top: 1px solid var(--border-color);
        box-shadow: 0 -1px 6px rgba(0, 0, 0, 0.05);
        padding: 4px 8px;
        box-sizing: border-box;
    }

    html.mobile-app-shell-enabled .mobile-secondary-tab-bar.mobile-secondary-visible {
        display: flex;
    }

    html.mobile-app-shell-enabled .mobile-secondary-tab-group {
        display: none;
        width: 100%;
    }

    html.mobile-app-shell-enabled .mobile-secondary-tab-group.mobile-secondary-active {
        display: flex;
    }

    /* Nur die Tracking-Gruppe stapelt zwei Reihen (Unterreiter + Kurzuebersicht)
       untereinander - die Stats-Gruppe (Persoenlich/Global) bleibt eine einzelne
       Button-Reihe und ist von dieser Regel nicht betroffen. */
    html.mobile-app-shell-enabled #mobileSecondaryTrackingGroup.mobile-secondary-active {
        flex-direction: column;
    }

    /* Kurzuebersicht (aktuelles+Tiefstgewicht / Kalorien+Rest+Ziel / Kcal
       verbrannt / Wasser "heute") direkt OBERHALB der Gewicht/Kalorien/Wasser/
       Sport-Unterreiter, auf allen 4 Unterreitern an derselben Stelle - nur
       der Inhalt wechselt (siehe updateMobileTrackingSummary() in
       mobileAppShell.js). */
    html.mobile-app-shell-enabled .mobile-tracking-summary-bar {
        display: flex;
        justify-content: center;
        flex-wrap: wrap;
        gap: 6px 22px;
        padding: 6px 8px 4px;
        border-bottom: 1px solid var(--border-color);
    }

    html.mobile-app-shell-enabled .mobile-tracking-summary-stat {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 1px;
    }

    html.mobile-app-shell-enabled .mobile-tracking-summary-label {
        font-size: 0.65rem;
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: 0.02em;
    }

    /* Ersetzt durch "Noch offen"/"Ziel" in der Kurzuebersicht-Box oben (siehe
       updateMobileTrackingSummary() in mobileAppShell.js) - der Fliesstext
       waere im App-Layout doppelt gemoppelt. Ausserhalb des App-Layouts
       (Desktop, Mobile-Browser-Ansicht) bleibt er unveraendert sichtbar. */
    html.mobile-app-shell-enabled #calRemainingText {
        display: none;
    }

    html.mobile-app-shell-enabled .mobile-tracking-summary-value {
        font-size: 0.9rem;
        font-weight: 700;
        color: var(--primary-color-text);
    }

    /* #entryTabsBar traegt bereits die .tabs-Klasse (siehe #newEntryCard) -
       deren margin-bottom/border-bottom sind fuers Einbetten im Kartenkopf
       gedacht, nicht fuer diese fixierte Leiste. */
    html.mobile-app-shell-enabled .mobile-secondary-tab-bar .tabs {
        margin-bottom: 0;
        border-bottom: none;
    }

    /* "Dicker" + Icons wie beim Hauptmenü (#mobileTabBar): die Unterreiter
       verlassen hier ihren Desktop-Look (duenne Unterstrich-Tabs) zugunsten
       desselben Icon-oben/Label-unten-Layouts wie die Haupt-Tab-Leiste - siehe
       .mobile-tab-btn weiter unten, dessen Icon-Pille (.mobile-tab-icon) hier
       wiederverwendet wird. */
    html.mobile-app-shell-enabled #mobileSecondaryTabBar .tab-btn {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        padding: 10px 4px 8px;
        border-bottom: none;
        font-size: 0.7rem;
        font-weight: 500;
    }

    html.mobile-app-shell-enabled #mobileSecondaryTabBar .tab-btn.active {
        border-bottom: none;
    }

    html.mobile-app-shell-enabled #mobileSecondaryTabBar .tab-btn .mobile-tab-icon {
        display: inline-flex;
    }

    html.mobile-app-shell-enabled #mobileSecondaryTabBar .tab-btn.active .mobile-tab-icon {
        background: color-mix(in srgb, var(--primary-color) 18%, transparent);
    }

    /* Persoenlich/Global-Umschalter (siehe #mobileSecondaryStatsGroup): steuert,
       welche der beiden data-mobile-tab="stats"-Gruppen (persoenliche Statistik-
       Boxen bzw. Community-Statistiken) innerhalb des "stats"-Haupt-Tabs sichtbar
       ist. Ohne gesetztes data-active-stats-view (vor dem ersten JS-Tick) gilt
       "personal" als Default, damit es keinen kurzen Flash beider Bloecke gibt. */
    html.mobile-app-shell-enabled[data-active-stats-view="global"] .mobile-tab-group[data-mobile-stats-view="personal"] {
        display: none !important;
    }

    html.mobile-app-shell-enabled:not([data-active-stats-view="global"]) .mobile-tab-group[data-mobile-stats-view="global"] {
        display: none !important;
    }

    /* Footer wird per JS in den "Mehr"-Tab verschoben (siehe
       scripts/mobileAppShell.js, relocateMobileFooter) statt unter der
       fixierten Tab-Leiste zu stehen. Sein eigener margin-top ueberschneidet
       sich dort mit dem flex gap zwischen den Karten - hier reduziert. */
    html.mobile-app-shell-enabled #mobileMoreTab footer {
        margin-top: 4px !important;
    }

    /* "Boxen rundherum ausblenden": Tracking- und Statistik-Tabs sind bereits
       durch die kontextuelle zweite Leiste (siehe oben) eindeutig eingerahmt -
       der Karten-Look (Hintergrund/Rahmen/Schatten/Innenabstand) wirkt hier
       nur wie doppelte Umrandung. Ohne ihn fuellt der Tab-Inhalt praktisch
       den ganzen Bildschirm statt wie eine Karte im Grid zu wirken. */
    html.mobile-app-shell-enabled #newEntryCard,
    html.mobile-app-shell-enabled #weightStatsGrid,
    html.mobile-app-shell-enabled #globalStatsCard {
        background: none;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border: none;
        border-radius: 0;
        box-shadow: none;
        padding: 0;
        margin-bottom: 0;
    }

    /* Trennt im Normalzustand persoenliche von Community-Statistiken - im
       App-Layout uebernimmt der Persoenlich/Global-Umschalter (siehe oben)
       diese Trennung bereits eindeutig, die Linie waere hier nur redundant. */
    html.mobile-app-shell-enabled #communityDivider {
        display: none;
    }

    /* .stat-item nutzt normalerweise var(--bg-color) als Kontrast zum
       umgebenden (helleren) Karten-Hintergrund von #weightStatsGrid - mit
       entferntem Karten-Hintergrund (siehe oben) ist das identisch mit dem
       Seitenhintergrund, die einzelnen Statistik-Boxen wuerden also unsichtbar
       verschwimmen. var(--card-bg) + Rahmen stellen den Kontrast hier wieder
       her, unabhaengig vom (jetzt fehlenden) Karten-Hintergrund. */
    html.mobile-app-shell-enabled #weightStatsGrid .stat-item {
        background-color: var(--card-bg);
        border: 1px solid var(--border-color);
    }

    /* Community-Statistik-Boxen (siehe main.js loadPublicCommunityStats) sind
       inline mit "background: var(--bg-color)" gestylt - statt jede einzelne
       Box per !important zu ueberschreiben, wird --bg-color hier innerhalb des
       Containers einfach lokal auf var(--card-bg) umdefiniert. Die Inline-
       Styles referenzieren die Variable weiterhin live und uebernehmen so
       automatisch denselben Hintergrund wie die persoenlichen .stat-item-Boxen
       oben, ohne main.js oder die Inline-Styles selbst anzufassen. */
    html.mobile-app-shell-enabled #globalStatsContainer {
        --bg-color: var(--card-bg);
    }

    /* "Daten & Fakten"-Ueberschrift ueber den Community-Boxen ist im
       App-Layout redundant - der Persoenlich/Global-Umschalter (siehe oben)
       benennt den Bereich bereits eindeutig. */
    html.mobile-app-shell-enabled #globalStatsCardTitle {
        display: none;
    }

    /* Alle Scrollbars im App-Layout unsichtbar (Scroll-Funktion bleibt
       erhalten) - betrifft v.a. #mobileScrollArea, aber pauschal auch
       verschachtelte Scroll-Container (Dropdowns, Kalender, Modals). */
    html.mobile-app-shell-enabled * {
        scrollbar-width: none;
        -ms-overflow-style: none;
    }

    html.mobile-app-shell-enabled *::-webkit-scrollbar {
        display: none;
    }

}

.mobile-tab-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 4px 6px;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 500;
    cursor: pointer;
    transition: color 0.2s;
}

.mobile-tab-icon {
    position: relative;
    font-size: 1.3rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 3px 14px;
    border-radius: 999px;
    transition: background-color 0.2s;
}

/* Reiner Farbwechsel war zu subtil, um den aktiven Tab auf einen Blick zu
   erkennen - zusaetzlich fetteres Label plus dezente Pille hinter dem Icon
   (Material-Bottom-Nav-Stil). */
.mobile-tab-btn.active {
    color: var(--primary-color-text);
    font-weight: 700;
}

.mobile-tab-btn.active .mobile-tab-icon {
    background: color-mix(in srgb, var(--primary-color) 18%, transparent);
}

/* Eigenes Pull-to-refresh (siehe scripts/mobileAppShell.js): das native
   Chrome-Gesture greift nur, wenn die Seite (nicht ein innerer Container)
   scrollt - im App-Layout scrollt aber #mobileScrollArea statt der Seite,
   daher haette man sonst kein Pull-to-refresh mehr. position:absolute nimmt
   es aus dem Flex-Gap-Layout heraus, damit es bei Hoehe 0 keinen Platz
   beansprucht und stattdessen ueber dem Inhalt "aufklappt". */
.mobile-pull-refresh {
    display: none;
}

@media (max-width: 767px) {
    html.mobile-app-shell-enabled .mobile-pull-refresh {
        display: flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 0;
        overflow: hidden;
        color: var(--text-muted);
        pointer-events: none;
        z-index: 1;
    }

    html.mobile-app-shell-enabled .mobile-pull-refresh.snapping {
        transition: height 0.2s ease-out;
    }
}

/* Pull-to-refresh-Variante fuer normal scrollende Seiten (admin.php,
   shopping.php) - dort scrollt die ganze Seite statt eines inneren
   Containers, daher fixed am Viewport statt absolute in einem Scroll-Bereich,
   und unabhaengig von der mobile-app-shell-enabled-Klasse (die es dort gar
   nicht gibt). Siehe scripts/globals.js initPullToRefresh(). */
.page-pull-refresh {
    display: none;
}

@media (max-width: 767px) {
    .page-pull-refresh {
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: 0;
        overflow: hidden;
        color: var(--text-muted);
        background: var(--bg-color);
        pointer-events: none;
        /* War 1200 (ueber .modal's 1000) - die Pull-Geste ist zwar nicht ans
           Vorhandensein eines offenen Modals gekoppelt (pointer-events:none
           verhindert zumindest, dass sie Klicks blockiert), aber der
           Indikator konnte trotzdem sichtbar UEBER einem offenen Modal
           rendern (Audit). Jetzt unter allen ueblichen Ebenen (FAB 900,
           Bottom-Bar 950, Modal 1000), aber noch ueber normalem
           Seiteninhalt. */
        z-index: 800;
    }

    .page-pull-refresh.snapping {
        transition: height 0.2s ease-out;
    }
}

.mobile-pull-refresh-icon {
    display: inline-block;
    font-size: 1.3rem;
    transition: transform 0.15s;
}

.mobile-pull-refresh-icon.ready {
    transform: rotate(180deg);
}

.mobile-pull-refresh-icon.loading {
    animation: mobilePullRefreshSpin 0.7s linear infinite;
}

@keyframes mobilePullRefreshSpin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* "Mehr"-Tab: Liste aus Profil/Einkaufsliste/Einstellungen/Meine Bilanz */
.mobile-more-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.mobile-more-item {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    background: none;
    border: none;
    border-radius: 8px;
    color: var(--text-color);
    text-align: left;
    font-size: 0.95rem;
    font-weight: 500;
    padding: 12px 10px;
    cursor: pointer;
    transition: background-color 0.2s;
}

.mobile-more-item:hover {
    background-color: var(--bg-color);
}

.mobile-more-item-icon {
    font-size: 1.25rem;
    width: 28px;
    text-align: center;
    flex-shrink: 0;
}

.mobile-more-item-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

/* "Uebersicht"-Tages-Dashboard (Lifesum-Stil), neuer erster Haupt-Tab
   (data-mobile-tab="home") - Kalorien-Restbudget-Gauge, Naehrwert-Balken,
   Mahlzeiten-Protokoll, Aktivitaet. Live-Logik in mobileAppShell.js
   (updateMobileHomeDashboard()/populateHomeMealsList()). */
@media (max-width: 767px) {
    .home-date-nav {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 14px;
    }

    .home-date-nav-btn {
        background: none;
        border: none;
        color: var(--text-color);
        font-size: 1.4rem;
        line-height: 1;
        cursor: pointer;
        padding: 4px 10px;
    }

    .home-date-nav-btn:disabled {
        color: var(--text-muted);
        cursor: default;
        opacity: 0.4;
    }

    .home-date-label {
        font-size: 0.85rem;
        font-weight: 700;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--text-muted);
        cursor: pointer;
        /* Feste Breite (auf den laengsten Fall "📅 HEUTE, 29. SEPT."
           ausgelegt), damit die ‹/›-Pfeile beim Tageswechsel nicht springen,
           nur weil der Text dazwischen breiter/schmaler wird. In em, damit
           sie mit der Schriftgroesse (Aa+/Aa-) mitwaechst. */
        flex: 0 0 auto;
        width: 14em;
        max-width: calc(100vw - 120px);
        text-align: center;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .home-gauge-card {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
    }

    .home-gauge-side {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 4px;
        flex: 1;
        min-width: 0;
    }

    .home-gauge-side-label {
        font-size: 0.8rem;
        color: var(--text-muted);
    }

    .home-gauge-side-value {
        font-size: 1.15rem;
        font-weight: 700;
        color: var(--text-color);
    }

    .home-gauge-wrap {
        position: relative;
        width: 150px;
        flex-shrink: 0;
    }

    .home-gauge-svg {
        width: 100%;
        height: auto;
        overflow: visible;
    }

    .home-gauge-track {
        fill: none;
        stroke: var(--border-color);
        stroke-width: 12;
        stroke-linecap: round;
    }

    .home-gauge-fill {
        fill: none;
        stroke: var(--success-color);
        stroke-width: 12;
        stroke-linecap: round;
        transition: stroke-dasharray 0.4s ease, stroke 0.3s ease;
    }

    .home-gauge-center {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 2px;
        display: flex;
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .home-gauge-label {
        font-size: 0.7rem;
        color: var(--text-muted);
    }

    .home-gauge-value {
        font-size: 1.6rem;
        font-weight: 800;
        color: var(--text-color);
        line-height: 1.1;
    }

    .home-gauge-goal {
        font-size: 0.7rem;
        color: var(--text-muted);
    }

    .home-macros-row {
        display: flex;
        gap: 10px;
    }

    .home-macro-box {
        flex: 1;
        min-width: 0;
        background: var(--card-bg);
        border-radius: 12px;
        padding: 10px 12px;
        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        display: flex;
        flex-direction: column;
        gap: 6px;
    }

    .home-macro-label {
        font-size: 0.75rem;
        color: var(--text-muted);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .home-macro-text {
        font-size: 0.85rem;
        font-weight: 700;
        color: var(--text-color);
    }

    .home-macro-bar {
        height: 5px;
        border-radius: 3px;
        background: var(--border-color);
        overflow: hidden;
    }

    .home-macro-bar-fill {
        height: 100%;
        border-radius: 3px;
        width: 0%;
        transition: width 0.4s ease;
    }

    .home-macro-bar-carbs { background: #6d8cff; }
    .home-macro-bar-protein { background: #ff6d9a; }
    .home-macro-bar-fat { background: #c084fc; }

    .home-section-title {
        margin: 4px 2px 0;
        font-size: 1.05rem;
        font-weight: 700;
        color: var(--text-color);
    }

    .home-meals-list {
        display: flex;
        flex-direction: column;
        gap: 10px;
    }

    .home-meal-row,
    .home-water-card,
    .home-activity-card {
        display: flex;
        align-items: center;
        gap: 12px;
        background: var(--card-bg);
        border-radius: 12px;
        padding: 12px 14px;
        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
    }

    .home-meal-icon {
        font-size: 1.6rem;
        flex-shrink: 0;
    }

    .home-meal-info {
        flex: 1;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 2px;
    }

    .home-meal-name {
        font-size: 1rem;
        font-weight: 600;
        color: var(--text-color);
    }

    .home-meal-sub {
        font-size: 0.8rem;
        color: var(--text-muted);
    }

    .home-activity-card {
        justify-content: space-between;
        font-size: 1rem;
        font-weight: 600;
        color: var(--text-color);
    }

    .home-add-btn {
        flex-shrink: 0;
        width: 34px;
        height: 34px;
        border-radius: 50%;
        border: none;
        background: var(--bg-color);
        color: var(--text-color);
        font-size: 1.3rem;
        line-height: 1;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .home-water-card .home-macro-bar {
        margin-top: 4px;
    }

    .home-water-bar-fill {
        background: #38bdf8;
    }

    .home-water-card .home-add-btn {
        background: #38bdf8;
        color: #fff;
        width: 40px;
        height: 40px;
    }

    .home-activity-card .home-add-btn {
        background: var(--success-color);
        color: #fff;
        width: 40px;
        height: 40px;
    }

    /* Gleiches "Pill"-Design des Datumwechsels (siehe .home-date-nav oben)
       auch fuer den Monats-Umschalter im "Verlauf"-Tab (.calendar-header) und
       fuer die Tages-Detailansicht darin (.day-modal-nav, siehe dayModal in
       php/modals_main.php) - jeweils nur im App-Layout, Desktop behaelt die
       urspruengliche kastenfoermige Optik mit Rahmen um Pfeile/Titel. */
    html.mobile-app-shell-enabled .calendar-header,
    html.mobile-app-shell-enabled .day-modal-nav {
        justify-content: center;
        gap: 14px;
    }

    html.mobile-app-shell-enabled .calendar-header button,
    html.mobile-app-shell-enabled .day-modal-nav button {
        background: none;
        border: none;
        width: auto;
        height: auto;
        padding: 4px 10px;
        color: var(--text-color);
        /* Versteckt die eigentlichen ◀/▶-Zeichen (font-size:0 macht den
           Text-Node unsichtbar, ohne den Button selbst zu verstecken) -
           ::before ersetzt sie durch dieselben duennen ‹/›-Pfeile wie bei
           .home-date-nav-btn (index.php), fuer eine WIRKLICH identische
           Optik statt nur aehnlicher Farben/Abstaende. */
        font-size: 0;
        line-height: 1;
    }

    html.mobile-app-shell-enabled #prevMonthBtn::before,
    html.mobile-app-shell-enabled #prevDayBtn::before {
        content: "‹";
        font-size: 1.4rem;
    }

    html.mobile-app-shell-enabled #nextMonthBtn::before,
    html.mobile-app-shell-enabled #nextDayBtn::before {
        content: "›";
        font-size: 1.4rem;
    }

    html.mobile-app-shell-enabled .calendar-header button:hover,
    html.mobile-app-shell-enabled .day-modal-nav button:hover {
        color: var(--primary-color-text);
    }

    html.mobile-app-shell-enabled #calendarMonthTitle,
    html.mobile-app-shell-enabled .day-modal-nav h2 {
        background: none;
        border: none;
        height: auto;
        line-height: normal;
        padding: 0;
        flex: initial;
        font-size: 0.85rem;
        font-weight: 700;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--text-muted);
    }

    /* Gleiches Kalender-Emoji-Praefix wie #homeDateLabel (dort Teil des per JS
       gesetzten Textinhalts, hier bewusst rein per CSS ergaenzt statt den
       gemeinsam mit Desktop genutzten JS-Text anzufassen). */
    html.mobile-app-shell-enabled #calendarMonthTitle::before,
    html.mobile-app-shell-enabled .day-modal-nav h2::before {
        content: "📅 ";
    }
}

/* ============================================================
   PRODUCTS.PHP (oeffentliche Lebensmittel-Datenbank, /products/)
   ------------------------------------------------------------
   Nutzt bewusst dieselben Design-Tokens (--card-bg, --border-color, ...)
   wie der Rest der App statt eines eigenstaendigen Looks - siehe
   [[project_products_page]].
   ============================================================ */
.products-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 15px;
    width: 100%;
    box-sizing: border-box;
}

.product-card {
    position: relative;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    overflow: hidden;
    transition: border-color 0.2s;
}

.product-card:hover {
    border-color: var(--primary-color);
}

.product-card-link {
    display: block;
    color: inherit;
    text-decoration: none;
}

.product-card-img {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: contain;
    background: #ffffff;
    padding: 10px;
    box-sizing: border-box;
}

.product-card-body {
    padding: 10px 12px 12px;
}

.product-card-brand {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 2px;
}

.product-card-name {
    font-weight: 600;
    font-size: 0.95rem;
    line-height: 1.3;
    /* Auf max. 2 Zeilen begrenzen, damit unterschiedlich lange Namen die
       Kartenhoehen im Grid nicht zu stark auseinanderreissen. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.product-card-kcal {
    margin-top: 4px;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.product-card-edit-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 1;
}

/* --- Admin-Nachrichten-System (Announcements + Umfragen) --- */

/* Runde Zaehler-Bubble am Nachrichten-Button (messagesBtn/moreMessagesItem) -
   kein Vorbild im Projekt (bestehende .admin-badge/.auth-status-badge sind
   reine Icon-Indikatoren ohne Zahl/Hintergrund), daher komplett neu. */
.messages-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background-color: var(--danger-color);
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
}

/* Im mobilen "Mehr"-Menue steht die Bubble inline hinter dem Label statt
   absolut positioniert ueber einem Icon. */
.mobile-more-item .messages-badge {
    position: static;
}

/* Tag-Bubble rechts neben dem Nachrichten-Betreff (Admin-Liste UND
   Nutzer-Ansicht) - Hintergrundfarbe kommt inline pro Tag mit (siehe
   MESSAGE_TAG_META in admin.js/tracking.js), hier nur die gemeinsame Form. */
.message-tag-badge {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 999px;
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.6;
    vertical-align: middle;
}

/* Listen-Spalte im Nachrichten-Modal (nur sichtbar bei >1 offener Nachricht,
   siehe renderMessagesList() in tracking.js). */
.message-list-item {
    padding: 8px 10px;
    border-radius: 6px;
    cursor: pointer;
    transition: background-color 0.2s;
}
.message-list-item:hover {
    background-color: var(--bg-color);
}
.message-list-item.active {
    background-color: var(--bg-color);
    border-left: 3px solid var(--primary-color);
    padding-left: 7px;
}
/* Bereits bestaetigte (gelesene) Nachrichten bleiben jetzt in der Liste
   stehen, treten aber optisch zurueck. */
.message-list-item.read {
    opacity: 0.6;
}
.message-list-item.read.active {
    opacity: 0.85;
}
/* Trennstrich zwischen offenen und bereits gelesenen Nachrichten (siehe
   renderMessagesList() in tracking.js). */
.message-list-divider {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    padding: 10px 10px 4px;
    border-top: 1px solid var(--border-color);
    margin-top: 4px;
}
/* Steht anstelle der (dann leeren) "neu"-Gruppe ueber dem Trennstrich, wenn
   es aktuell keine offenen Nachrichten gibt. */
.message-list-empty-hint {
    padding: 8px 10px;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-style: italic;
}

/* Rendert das bereits serverseitig sanitisierte content_html (siehe
   sanitizeMessageHtml() in backend.php) im aktuellen Theme - Bilder duerfen
   die Modal-Breite nicht sprengen. */
.message-content-body {
    line-height: 1.5;
    word-break: break-word;
}
.message-content-body img {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
}
/* Forum-typischer Zitat-Block (Hintergrund-Kasten statt nur duennem
   Rahmenstrich) - gilt sowohl fuer die gerenderte Nachricht als auch fuer
   den Compose-Editor selbst, damit der Admin beim Klick auf "Zitat" sofort
   sieht, dass die Formatierung tatsaechlich angewendet wurde. */
.message-content-body blockquote,
.message-editor-content blockquote {
    background-color: var(--bg-color);
    border-left: 3px solid var(--primary-color);
    padding: 8px 12px;
    margin: 8px 0;
    border-radius: 0 6px 6px 0;
    color: var(--text-muted);
    font-style: italic;
}
/* "Code"-Formatierung (formatBlock "pre") - Monospace-Schrift, eigener
   Hintergrund-Kasten, Zeilenumbrueche/Leerzeichen bleiben erhalten
   (white-space: pre-wrap) und lange Zeilen scrollen statt die Modal-Breite
   zu sprengen. Ebenfalls in beiden Ansichten (Editor + gerenderte Nachricht),
   aus demselben Grund wie beim Zitat oben. */
.message-content-body pre,
.message-editor-content pre {
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 8px 12px;
    margin: 8px 0;
    font-family: monospace;
    font-size: 0.9rem;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-x: auto;
}
.message-content-body ul,
.message-content-body ol {
    padding-left: 22px;
}

/* Admin-Compose: Formatierungs-Toolbar + gemeinsame Box-Optik fuer
   contenteditable-Editor und den alternativen HTML-Quelltext-Textarea. */
.message-editor-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 6px;
}
/* .small-btn selbst setzt nur color:white und erwartet eine Modifier-Klasse
   (.edit-btn/.delete-btn-sm) fuer den Hintergrund - ohne die faellt die
   Toolbar auf den Browser-Standardhintergrund (hell) mit weisser Schrift
   zurueck, im Dark Mode praktisch unlesbar. Eigener Hintergrund/Rahmen fix. */
.message-editor-toolbar .small-btn {
    background-color: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--border-color);
}
.message-editor-toolbar .small-btn:hover {
    background-color: var(--border-color);
}
.message-editor-content {
    width: 100%;
    min-height: 160px;
    max-height: 320px;
    overflow-y: auto;
    box-sizing: border-box;
    padding: 10px;
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    line-height: 1.5;
}
.message-editor-content:focus {
    outline: none;
    border-color: var(--primary-color);
}
.message-editor-content img {
    max-width: 100%;
    height: auto;
}
/* Der globale "* { margin:0; padding:0; }"-Reset (Zeile ~165) nimmt ul/ol
   jeden Innenabstand - der Listenpunkt (list-style-position: outside) wird
   dann links ausserhalb der editierbaren Box gerendert statt eingerueckt. */
.message-editor-content ul,
.message-editor-content ol {
    padding-left: 22px;
}

/* Empfaenger-Chips (Vorbild: Chip-Eingabe wie ein E-Mail-"An:"-Feld, kein
   bestehendes Muster im Projekt). */
.message-recipient-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}
.message-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    font-size: 0.85rem;
}
.message-chip button {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 0;
}
.message-chip button:hover {
    color: var(--danger-color-text);
}

/* Sterne-Bewertungs-Widget (Umfrage-Typ "rating") - klickbare 1-5-Sterne-Reihe,
   kein Vorbild im Projekt. */
.message-star-rating {
    display: inline-flex;
    gap: 2px;
    font-size: 1.4rem;
    color: var(--warning-color);
    line-height: 1;
}
.message-star-rating span {
    cursor: pointer;
    transition: transform 0.1s;
}
.message-star-rating span:hover {
    transform: scale(1.15);
}

/* --- Admin-Bereich "Sprachen" --- */
.language-translate-row {
    display: grid;
    grid-template-columns: 200px 1fr 1fr 20px;
    gap: 10px;
    align-items: start;
    padding: 8px 0;
    border-bottom: 1px solid var(--border-color);
}
.language-translate-key {
    font-size: 0.75rem;
    color: var(--text-muted);
    word-break: break-word;
    padding-top: 7px;
}
.language-translate-source {
    font-size: 0.9rem;
    color: var(--text-color);
    padding-top: 7px;
    word-break: break-word;
}
/* Kein globales "textarea"-Grundstyling im Projekt (nur input/select) - ohne
   eigene Farben faellt dieses Feld auf den hellen Browser-Standard zurueck,
   im Dark Mode also derselbe Lesbarkeits-Bug wie schon bei der Nachrichten-
   Toolbar weiter oben. */
.language-translate-target {
    width: 100%;
    min-height: 34px;
    padding: 6px 8px;
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-family: inherit;
    font-size: 0.9rem;
    resize: vertical;
}
.language-translate-target:focus {
    outline: none;
    border-color: var(--primary-color);
}
.language-translate-saved-icon {
    color: var(--success-color);
    font-weight: 700;
    padding-top: 7px;
}
@media (max-width: 767px) {
    /* War 700px, ein Einzelwert ohne erkennbaren Grund - an den sonst im
       Projekt genutzten Breakpoint (500/600/767/1023) angeglichen. */
    .language-translate-row {
        grid-template-columns: 1fr;
    }
}

/* --- Saisonale Effekte (Halloween/Weihnachten/Silvester) --- */
/* Ersetzt nur den SVG-Mondphasen-Inhalt durch einen Kuerbis-Emoji, solange
   Halloween aktiv ist (siehe applyMoonHalloweenSkin() in tracking.js) - die
   Sichtbarkeits-Logik (nur Dunkelmodus + Nacht, .moon-element weiter oben)
   bleibt komplett unangetastet, es aendert sich nur, WAS im Kasten steckt. */
.jack-o-lantern-emoji {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    font-size: 46px;
    line-height: 1;
}

.seasonal-overlay {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 1;
    display: none;
}
.seasonal-overlay.active {
    display: block;
}

.snowflake {
    position: absolute;
    top: -20px;
    /* Reines Weiss (siehe body.dark-mode weiter unten) war gegen den hellen
       Standard-Hintergrund praktisch unsichtbar (Audit) - dieses kuehle Blau
       liest sich in Light Mode als "Eis/Schnee" und bleibt sichtbar. */
    color: #6b93b8;
    opacity: 0.85;
    text-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
    animation-name: snowfall;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
body.dark-mode .snowflake {
    color: #ffffff;
    text-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
}
@keyframes snowfall {
    0% { transform: translateY(-20px) translateX(0); }
    100% { transform: translateY(110vh) translateX(var(--drift, 20px)); }
}

.firework-rocket {
    position: absolute;
    bottom: 0;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    box-shadow: 0 0 6px 2px currentColor;
    animation: fireworkRise 1s ease-out forwards;
}
@keyframes fireworkRise {
    0% { transform: translateY(0); opacity: 1; }
    100% { transform: translateY(var(--rise)); opacity: 0.9; }
}
.firework-particle {
    position: absolute;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    box-shadow: 0 0 6px 1px currentColor;
    animation: fireworkExplode 1s ease-out forwards;
}
@keyframes fireworkExplode {
    0% { transform: translate(0, 0) scale(1); opacity: 1; }
    100% { transform: translate(var(--dx), var(--dy)) scale(0.3); opacity: 0; }
}
/* Trainings-Import (GPX/TCX/FIT) im Sport-Formular, siehe scripts/workoutImport.js */
.activity-import-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 12px;
}

.activity-import-btn {
    width: auto;
    padding: 6px 15px;
    font-size: 0.9rem;
    font-weight: 500;
}

.activity-import-hint {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.activity-import-status {
    margin-bottom: 12px;
    padding: 8px 12px;
    border-radius: 8px;
    background: var(--bg-color);
    font-size: 0.85rem;
    color: var(--text-color);
    overflow-wrap: anywhere;
}

.activity-import-status-error {
    color: var(--danger-color);
}

/* "Neu anlegen": weitere Einheiten direkt mit anlegen (siehe renderNewFoodUnitRow in food.js) */
.new-food-units {
    margin-bottom: 15px;
    padding: 10px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
}
.new-food-units-title {
    font-size: 0.85rem;
    color: var(--text-muted);
    display: block;
    margin-bottom: 8px;
}
.new-food-units-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.new-food-units-list:not(:empty) {
    margin-bottom: 8px;
}
.new-food-unit-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
}
.new-food-unit-row .nfu-top,
.new-food-unit-row .nfu-values {
    display: flex;
    gap: 6px;
    align-items: center;
}
.new-food-unit-row input {
    min-width: 0;
    padding: 6px;
    font-size: 0.9rem;
    box-sizing: border-box;
}
.new-food-unit-row .nfu-name { flex: 1 1 auto; }
.new-food-unit-row .nfu-amount { flex: 0 0 70px; width: 70px; }
.new-food-unit-row .nfu-values { align-items: flex-end; }
.new-food-unit-row .nfu-values .labeled-field { flex: 1 1 0; min-width: 0; }
.new-food-unit-row .nfu-values input { width: 100%; }
.new-food-unit-row .nfu-amount-label {
    font-size: 0.85rem;
    color: var(--text-muted);
    flex-shrink: 0;
}
.new-food-unit-row .nfu-remove {
    flex-shrink: 0;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}
.new-food-unit-row .nfu-remove:hover { color: var(--danger-color-text); }
.new-food-add-unit-btn {
    width: 100%;
    padding: 8px 12px;
}
.new-food-add-unit-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.new-food-units-hint {
    display: block;
    margin-top: 6px;
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* Eingabefeld mit dauerhaft sichtbarer Beschriftung - der Placeholder allein
   verschwindet, sobald etwas eingetragen ist (kcal/Eiweiss/Fett/KH). */
.labeled-field {
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.labeled-field > label {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ============================================================
   SEITEN-APP-SHELL (shopping.php, products.php)
   Dieselbe Haupt-Tab-Leiste wie in index.php (php/app_tab_bar.php,
   scripts/pageAppShell.js), nur bei html.page-app-shell-enabled
   (php/app_shell_head.php bzw. applyMobileAppLayoutPreference in
   globals.js). Die Seiten scrollen weiter ganz normal ueber den Body.
   ============================================================ */
.page-app-bottom-bar {
    display: none;
}

@media (max-width: 767px) {
    html.page-app-shell-enabled .page-app-bottom-bar {
        display: flex;
        flex-direction: column;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 950;
        background: var(--card-bg);
        border-top: 1px solid var(--border-color);
        box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }

    html.page-app-shell-enabled .page-app-tab-bar {
        display: flex;
    }

    html.page-app-shell-enabled body {
        padding-bottom: calc(var(--page-bottom-bar-height, 70px) + 16px);
    }

    /* "Zurueck zur App" uebernimmt die Tab-Leiste. */
    html.page-app-shell-enabled #shoppingBackToAppBtn,
    html.page-app-shell-enabled #productsBackToAppBtn {
        display: none;
    }

    /* Kompakter Kopf wie auf der Uebersicht in index.php. */
    html.page-app-shell-enabled .app-header .logo-wrapper {
        zoom: 0.72;
    }

    /* Wie in der App-Shell von index.php: kein schwebender Barrierefreiheit-
       Button (die Einstellungen liegen im "Mehr"-Tab unter "Sonstige"). */
    html.page-app-shell-enabled .a11y-widget {
        display: none;
    }

    /* Header wie in der App: kompaktes Logo linksbuendig, daneben der
       Seitentitel im Stil der Begruessung. Die rechte Button-Gruppe
       (Zurueck zur App, auf products.php zusaetzlich Profil) entfaellt -
       beides erreicht man ueber die Tab-Leiste bzw. "Mehr" > Profil.
       !important noetig wegen der Inline-Styles am Header (flex-wrap/gap)
       und der Handy-Regeln in shopping.css (flex-direction: column). */
    html.page-app-shell-enabled .app-header {
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        justify-content: flex-start !important;
        align-items: center !important;
        gap: 14px !important;
        margin-bottom: 0;
    }

    html.page-app-shell-enabled .app-header > div:first-child {
        gap: 14px !important;
        min-width: 0;
    }

    html.page-app-shell-enabled .app-header .header-actions {
        display: none !important;
    }

    html.page-app-shell-enabled .app-header h1 {
        font-size: 1.1rem;
        font-weight: 600;
        line-height: 1.25;
        min-width: 0;
    }
}

/* "Mehr"-Unterleiste (php/more_sub_bar.php) - in index.php innerhalb von
   #mobileSecondaryTabBar (Sichtbarkeit ueber .mobile-secondary-active), auf
   products.php als .page-app-sub-bar in der Seiten-Tab-Leiste. Bis zu 6
   Eintraege, daher kompakter als die Haupt-Tabs. */
.more-sub-group {
    display: none;
}

.more-sub-btn {
    min-width: 0;
}

.more-sub-btn .mobile-tab-icon {
    font-size: 1.1rem;
    padding: 3px 10px;
}

.more-sub-label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.more-sub-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    object-fit: cover;
}

@media (max-width: 767px) {
    html.page-app-shell-enabled .page-app-sub-bar {
        display: flex;
        border-bottom: 1px solid var(--border-color);
        padding: 2px 4px;
    }
}

/* Sync-/Offline-Banner (siehe updateSyncStatusBanner in offlineSync.js):
   eine Zeile - Logo + Name, Hinweistext (gekuerzt statt umgebrochen), Button. */
.sync-status-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 9998;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 10px;
    padding-top: calc(4px + env(safe-area-inset-top, 0px));
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.2;
    background: var(--warning-color, #f59e0b);
    color: #1f2937;
    transition: transform 0.25s ease;
    box-sizing: border-box;
}

.sync-status-banner {
    cursor: pointer;
}

.sync-status-banner-brand {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-weight: 700;
    flex-shrink: 0;
}

.sync-status-banner-brand img {
    height: 18px;
    width: auto;
}

.sync-status-banner-text {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sync-status-banner-btn {
    flex-shrink: 0;
    border: 1px solid #1f2937;
    background: transparent;
    color: #1f2937;
    border-radius: 6px;
    padding: 2px 8px;
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

/* Modals beginnen unterhalb des Banners, statt von ihm verdeckt zu werden
   (z.B. Kopfzeile/Schliessen-Button des Profil-Modals). */
html.sync-banner-visible .modal {
    top: var(--sync-banner-height, 0px);
    height: calc(100% - var(--sync-banner-height, 0px));
}

html.sync-banner-visible .modal .modal-content {
    max-height: calc(100% - 20px) !important;
}

/* Tageswechsel per Wischgeste auf der "Uebersicht" (initHomeDateSwipe in
   mobileAppShell.js): Inhalt gleitet kurz aus der Wischrichtung herein. */
@keyframes homeSwipeInFromRight {
    from { opacity: 0.4; transform: translateX(24px); }
    to { opacity: 1; transform: translateX(0); }
}

@keyframes homeSwipeInFromLeft {
    from { opacity: 0.4; transform: translateX(-24px); }
    to { opacity: 1; transform: translateX(0); }
}

#mobileHomeTab.home-swipe-next {
    animation: homeSwipeInFromRight 0.2s ease-out;
}

#mobileHomeTab.home-swipe-prev {
    animation: homeSwipeInFromLeft 0.2s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    #mobileHomeTab.home-swipe-next,
    #mobileHomeTab.home-swipe-prev {
        animation: none;
    }
}

/* Schriftgroesse Aa-/Aa+ (Barrierefreiheit-Widget und "Mehr" > "Sonstige") */
.a11y-font-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 12px;
    font-size: 0.9rem;
    color: var(--text-color);
}

.a11y-font-controls {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.a11y-font-btn {
    min-width: 44px;
    height: 36px;
    padding: 0 8px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--card-bg);
    color: var(--text-color);
    font-weight: 700;
    font-size: 0.9rem;
    cursor: pointer;
}

.a11y-font-btn:hover:not(:disabled) {
    background: var(--bg-color);
}

.a11y-font-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.a11y-font-value {
    min-width: 3.2em;
    text-align: center;
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

/* Zoom-Sperre in der App-Shell (siehe syncAppShellZoomLock in globals.js):
   nur Scrollen erlauben - kein Pinch-Zoom, kein Doppeltipp-Zoom. */
html.mobile-app-shell-enabled,
html.admin-app-shell-enabled,
html.page-app-shell-enabled {
    touch-action: pan-x pan-y;
}

/* kcal <-> kJ (siehe attachKjField in globals.js): zwei Felder nebeneinander,
   jeweils mit Einheit dahinter, damit auch ausgefuellt klar ist, welches
   Feld was ist. */
.kcal-kj-pair {
    display: flex;
    gap: 8px;
    width: 100%;
}

.kcal-kj-field {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 4px;
}

.kcal-kj-field input {
    flex: 1 1 auto;
    min-width: 0;
    width: 100% !important;
}

.kcal-kj-unit {
    flex-shrink: 0;
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* In den kompakten Einheiten-Zeilen ("Neu anlegen" > weitere Einheiten) ist
   kein Platz fuer zwei Felder nebeneinander - dort untereinander. */
.new-food-unit-row .kcal-kj-pair {
    flex-direction: column;
    gap: 4px;
}

/* Restlaufzeit der Anmeldung unter "Abmelden" im Profil (auth.js) */
.session-expiry-info {
    margin: 8px 0 0;
    font-size: 0.8rem;
    color: var(--text-muted);
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.session-expiry-info:empty {
    display: none;
}
