diff --git a/backend/static/css/components.css b/backend/static/css/components.css
index afdcb80..750fc4a 100644
--- a/backend/static/css/components.css
+++ b/backend/static/css/components.css
@@ -441,6 +441,7 @@ textarea.form-control {
padding: var(--space-4);
backdrop-filter: blur(2px);
animation: overlay-in var(--transition-normal) ease;
+ touch-action: manipulation;
}
@media (min-width: 768px) {
.modal-overlay { align-items: center; }
@@ -812,3 +813,409 @@ textarea.form-control {
/* Leaflet-Attribution ausblenden */
.leaflet-control-attribution { display: none !important; }
+
+/* ============================================================
+ GESUNDHEIT
+ ============================================================ */
+
+/* Header mit KI-Button */
+.health-header {
+ display: flex;
+ justify-content: flex-end;
+ padding: var(--space-3) 0 var(--space-2);
+}
+
+/* Tab-Leiste — Mobile: horizontal scrollbar, Desktop: umbrechen */
+.health-tabs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-1) var(--space-1);
+ padding-bottom: var(--space-2);
+ margin-bottom: var(--space-3);
+}
+/* Auf sehr kleinen Screens: scrollen statt umbrechen */
+@media (max-width: 480px) {
+ .health-tabs {
+ flex-wrap: nowrap;
+ overflow-x: auto;
+ padding-right: var(--space-4);
+ scrollbar-width: none;
+ }
+ .health-tabs::-webkit-scrollbar { display: none; }
+}
+
+.health-tab {
+ flex-shrink: 0;
+ padding: var(--space-2) var(--space-3);
+ border: 2px solid var(--c-border);
+ border-radius: var(--radius-full);
+ background: var(--c-surface);
+ color: var(--c-text-secondary);
+ font-size: var(--text-sm);
+ font-weight: var(--weight-medium);
+ cursor: pointer;
+ white-space: nowrap;
+ transition: all var(--transition-fast);
+ touch-action: manipulation;
+}
+.health-tab.active {
+ background: var(--c-primary);
+ border-color: var(--c-primary);
+ color: var(--c-text-inverse);
+}
+
+/* Karten-Liste */
+.health-list {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-3);
+}
+
+/* Einzelne Karte */
+.health-card {
+ background: var(--c-surface);
+ border: 1px solid var(--c-border);
+ border-radius: var(--radius-md);
+ padding: var(--space-4);
+ cursor: pointer;
+ display: flex;
+ gap: var(--space-3);
+ align-items: flex-start;
+ transition: box-shadow var(--transition-fast), transform var(--transition-fast);
+}
+.health-card:active { transform: scale(0.985); }
+.health-card--inactive { opacity: 0.55; }
+
+.health-card-body { flex: 1; min-width: 0; }
+.health-card-title { font-weight: var(--weight-semibold); margin-bottom: var(--space-1); }
+.health-card-meta { font-size: var(--text-sm); color: var(--c-text-secondary); }
+.health-card-next { font-size: var(--text-sm); font-weight: var(--weight-medium); margin-top: var(--space-1); }
+.health-card-note { font-size: var(--text-sm); color: var(--c-text-secondary); margin-top: var(--space-1); }
+
+/* Ampel-Punkt (links an der Karte) */
+.health-card-ampel {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ flex-shrink: 0;
+ margin-top: 5px;
+}
+.ampel-green { background: #22c55e; }
+.ampel-yellow { background: #f59e0b; }
+.ampel-red { background: #ef4444; }
+.ampel-grey { background: var(--c-border); }
+
+.ampel-text-green { color: #16a34a; }
+.ampel-text-yellow { color: #d97706; }
+.ampel-text-red { color: #dc2626; }
+
+/* Gruppen-Label (z.B. "Aktuelle Medikamente") */
+.health-group-label {
+ font-size: var(--text-sm);
+ font-weight: var(--weight-semibold);
+ color: var(--c-text-secondary);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ padding: var(--space-3) 0 var(--space-1);
+}
+
+/* Gewicht-Diagramm-Wrapper */
+.health-chart-wrap {
+ background: var(--c-surface);
+ border: 1px solid var(--c-border);
+ border-radius: var(--radius-md);
+ padding: var(--space-4);
+ margin-bottom: var(--space-4);
+ overflow: hidden;
+}
+
+/* Dokument-Thumbnail und Icon */
+.health-doc-thumb {
+ width: 56px;
+ height: 56px;
+ object-fit: cover;
+ border-radius: var(--radius-sm);
+ flex-shrink: 0;
+}
+.health-doc-icon {
+ width: 56px;
+ height: 56px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 2rem;
+ background: var(--c-surface-2);
+ border-radius: var(--radius-sm);
+ flex-shrink: 0;
+}
+
+/* Detail-Dialog DL */
+.health-detail-dl {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ gap: var(--space-1) var(--space-4);
+ font-size: var(--text-sm);
+}
+.health-detail-dl dt {
+ color: var(--c-text-secondary);
+ font-weight: var(--weight-medium);
+ white-space: nowrap;
+}
+.health-detail-dl dd { margin: 0; }
+
+/* ------------------------------------------------------------
+ DOG SWITCHER
+ Avatar-Leiste in Header (Mobile) + Sidebar-Logo (Desktop)
+ ------------------------------------------------------------ */
+
+/* Aktiver (linker) Hund — primärer Ring */
+.dog-sw-active {
+ width: 34px;
+ height: 34px;
+ border-radius: var(--radius-full);
+ overflow: hidden;
+ background: var(--c-surface-2);
+ flex-shrink: 0;
+ cursor: pointer;
+ border: 2.5px solid var(--c-primary);
+ transition: transform var(--transition-fast),
+ box-shadow var(--transition-fast);
+}
+.dog-sw-active:hover {
+ transform: scale(1.06);
+ box-shadow: 0 0 0 3px var(--c-primary-subtle);
+}
+.dog-sw-active img { width:100%; height:100%; object-fit:cover; display:block; }
+.dog-sw-active span {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ font-size: 17px;
+}
+
+/* "Ban Yaro" Label — füllt den Zwischenraum */
+.dog-sw-title {
+ flex: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* Gruppe der inaktiven Hunde (rechts) */
+.dog-sw-others {
+ display: flex;
+ align-items: center;
+ position: relative; /* Anker für Quickpicker-Dropdown */
+ flex-shrink: 0;
+}
+
+/* Inaktiver Hund-Avatar */
+.dog-sw-other {
+ width: 28px;
+ height: 28px;
+ border-radius: var(--radius-full);
+ overflow: hidden;
+ background: var(--c-surface-2);
+ border: 2px solid var(--c-surface);
+ cursor: pointer;
+ flex-shrink: 0;
+ transition: transform var(--transition-fast);
+ position: relative;
+}
+.dog-sw-other:hover { transform: scale(1.12); }
+.dog-sw-other img { width:100%; height:100%; object-fit:cover; display:block; }
+.dog-sw-other span {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ font-size: 14px;
+}
+
+/* Gestapelter Avatar-Stack (3+ Hunde) */
+.dog-sw-stack {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+}
+.dog-sw-stack .dog-sw-other { margin-left: -9px; }
+.dog-sw-stack .dog-sw-other:first-child { margin-left: 0; }
+.dog-sw-stack .dog-sw-other--0 { z-index: 3; }
+.dog-sw-stack .dog-sw-other--1 { z-index: 2; }
+.dog-sw-stack .dog-sw-other--2 { z-index: 1; }
+.dog-sw-stack:hover .dog-sw-other { filter: brightness(1.05); }
+
+/* +N Überlauf-Badge */
+.dog-sw-more {
+ width: 28px;
+ height: 28px;
+ border-radius: var(--radius-full);
+ background: var(--c-surface-2);
+ border: 2px solid var(--c-surface);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 9px;
+ font-weight: var(--weight-bold);
+ color: var(--c-text-secondary);
+ margin-left: -9px;
+ position: relative;
+ z-index: 0;
+}
+
+/* Quickpicker-Dropdown */
+.dog-quickpick {
+ position: absolute;
+ top: calc(100% + 10px);
+ right: 0;
+ background: var(--c-surface);
+ border: 1px solid var(--c-border-light);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-lg);
+ padding: var(--space-2);
+ min-width: 170px;
+ z-index: 600;
+}
+.dog-quickpick.hidden { display: none; }
+
+.dog-qp-item {
+ display: flex;
+ align-items: center;
+ gap: var(--space-3);
+ padding: var(--space-2) var(--space-3);
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ font-size: var(--text-sm);
+ font-weight: var(--weight-medium);
+ color: var(--c-text);
+ transition: background var(--transition-fast);
+ -webkit-tap-highlight-color: transparent;
+}
+.dog-qp-item:hover { background: var(--c-bg); }
+
+.dog-qp-av {
+ width: 32px;
+ height: 32px;
+ border-radius: var(--radius-full);
+ overflow: hidden;
+ background: var(--c-surface-2);
+ flex-shrink: 0;
+}
+.dog-qp-av img { width:100%; height:100%; object-fit:cover; display:block; }
+.dog-qp-av span {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ font-size: 16px;
+}
+
+/* Sidebar: größerer aktiver Avatar */
+#sidebar-dog-switcher .dog-sw-active {
+ width: 36px;
+ height: 36px;
+}
+
+/* ------------------------------------------------------------
+ DIARY — Multi-Dog (Hunde-Auswahl im Formular + Karten-Anzeige)
+ ------------------------------------------------------------ */
+
+/* Avatar-Reihe in der Tagebuch-Karte */
+.diary-dog-row {
+ display: flex;
+ align-items: center;
+ gap: -4px; /* überlappend via margin */
+ margin-top: var(--space-2);
+ flex-wrap: wrap;
+ gap: var(--space-1);
+}
+
+.diary-dog-av {
+ width: 22px;
+ height: 22px;
+ border-radius: var(--radius-full);
+ overflow: hidden;
+ background: var(--c-surface-2);
+ border: 1.5px solid var(--c-surface);
+ flex-shrink: 0;
+}
+.diary-dog-av img { width:100%; height:100%; object-fit:cover; display:block; }
+.diary-dog-av span {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ font-size: 12px;
+}
+
+/* Hunde-Chip in der Detail-Ansicht */
+.diary-detail-dogs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-2);
+ margin-bottom: var(--space-3);
+}
+
+.diary-dog-chip {
+ display: flex;
+ align-items: center;
+ gap: var(--space-1);
+ padding: 3px 8px 3px 4px;
+ background: var(--c-surface-2);
+ border-radius: var(--radius-full);
+ font-size: var(--text-xs);
+ font-weight: var(--weight-medium);
+ color: var(--c-text-secondary);
+}
+.diary-dog-chip .diary-dog-av {
+ width: 20px;
+ height: 20px;
+}
+
+/* Hunde-Picker im Formular */
+.diary-dog-picker {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-2);
+}
+
+.diary-dog-pick-item {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ padding: var(--space-2) var(--space-3);
+ border: 1.5px solid var(--c-border-light);
+ border-radius: var(--radius-full);
+ cursor: pointer;
+ font-size: var(--text-sm);
+ font-weight: var(--weight-medium);
+ color: var(--c-text-secondary);
+ transition: border-color var(--transition-fast),
+ background var(--transition-fast),
+ color var(--transition-fast);
+ -webkit-tap-highlight-color: transparent;
+ user-select: none;
+}
+.diary-dog-pick-item input { display: none; }
+
+.diary-dog-pick-item .diary-dog-av {
+ width: 26px;
+ height: 26px;
+}
+
+.diary-dog-pick-item:hover {
+ border-color: var(--c-primary);
+ color: var(--c-text);
+}
+
+.diary-dog-pick-item.checked {
+ border-color: var(--c-primary);
+ background: var(--c-primary-subtle);
+ color: var(--c-primary-dark);
+ font-weight: var(--weight-semibold);
+}
diff --git a/backend/static/css/layout.css b/backend/static/css/layout.css
index 88fe171..2682530 100644
--- a/backend/static/css/layout.css
+++ b/backend/static/css/layout.css
@@ -58,6 +58,16 @@
flex: 1;
}
+/* Dog Switcher Container im Header */
+#header-dog-switcher {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ min-width: 0;
+ overflow: visible;
+}
+
.header-back {
display: flex;
align-items: center;
@@ -201,7 +211,7 @@
background: var(--c-surface);
border-right: 1px solid var(--c-border-light);
flex-direction: column;
- overflow-y: auto;
+ overflow: hidden; /* Sidebar selbst scrollt nicht */
box-shadow: var(--shadow-sm);
}
@@ -229,14 +239,31 @@
color: var(--c-text);
}
-.sidebar-nav {
- flex: 1;
- padding: var(--space-4) var(--space-2);
- display: flex;
- flex-direction: column;
- gap: var(--space-1);
+.sidebar-add {
+ padding: var(--space-4) var(--space-4) var(--space-2);
+ flex-shrink: 0;
}
+.sidebar-nav {
+ flex: 1;
+ padding: var(--space-2) var(--space-2) var(--space-4);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-1);
+ overflow-y: auto;
+ min-height: 0; /* wichtig: flex-child darf kleiner werden als Inhalt */
+ /* Firefox */
+ scrollbar-width: thin;
+ scrollbar-color: var(--c-primary) var(--c-surface);
+}
+.sidebar-nav::-webkit-scrollbar { width: 6px; }
+.sidebar-nav::-webkit-scrollbar-track { background: var(--c-surface); }
+.sidebar-nav::-webkit-scrollbar-thumb {
+ background: var(--c-primary);
+ border-radius: 3px;
+}
+.sidebar-nav::-webkit-scrollbar-thumb:hover { background: var(--c-primary-dark); }
+
.sidebar-section-label {
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
@@ -270,6 +297,12 @@
color: var(--c-primary-dark);
font-weight: var(--weight-semibold);
}
+/* User-Eintrag bekommt nie den Active-Stil */
+.sidebar-item--user.active {
+ background: transparent;
+ color: var(--c-text-secondary);
+ font-weight: var(--weight-medium);
+}
.sidebar-item-icon {
font-size: 18px;
width: 24px;
@@ -291,11 +324,7 @@
padding: 0 var(--space-1);
}
-.sidebar-footer {
- padding: var(--space-4) var(--space-2);
- border-top: 1px solid var(--c-border-light);
- flex-shrink: 0;
-}
+/* sidebar-footer entfernt — Einstellungen/Konto sind jetzt Teil der scrollbaren Nav */
/* ------------------------------------------------------------
5. PAGE WRAPPER (inneres Layout der Seiten)
diff --git a/backend/static/icons/favicon-16.png b/backend/static/icons/favicon-16.png
new file mode 100644
index 0000000..40b9c1f
Binary files /dev/null and b/backend/static/icons/favicon-16.png differ
diff --git a/backend/static/icons/favicon-32.png b/backend/static/icons/favicon-32.png
new file mode 100644
index 0000000..7667efc
Binary files /dev/null and b/backend/static/icons/favicon-32.png differ
diff --git a/backend/static/icons/favicon.ico b/backend/static/icons/favicon.ico
new file mode 100644
index 0000000..9c22a1c
Binary files /dev/null and b/backend/static/icons/favicon.ico differ
diff --git a/backend/static/icons/icon-180.png b/backend/static/icons/icon-180.png
new file mode 100644
index 0000000..57a5fa6
Binary files /dev/null and b/backend/static/icons/icon-180.png differ
diff --git a/backend/static/icons/icon-192.png b/backend/static/icons/icon-192.png
new file mode 100644
index 0000000..2554fff
Binary files /dev/null and b/backend/static/icons/icon-192.png differ
diff --git a/backend/static/icons/icon-512.png b/backend/static/icons/icon-512.png
new file mode 100644
index 0000000..58dc5fe
Binary files /dev/null and b/backend/static/icons/icon-512.png differ
diff --git a/backend/static/index.html b/backend/static/index.html
index d5c5e22..f0fd842 100644
--- a/backend/static/index.html
+++ b/backend/static/index.html
@@ -6,9 +6,14 @@
+
+
+
+
+
-
+
@@ -30,17 +35,23 @@