diff --git a/drohnenfuehrer/frontend/index.html b/drohnenfuehrer/frontend/index.html
index 76ad2b5..d2fa19d 100644
--- a/drohnenfuehrer/frontend/index.html
+++ b/drohnenfuehrer/frontend/index.html
@@ -5,7 +5,7 @@
-
+
diff --git a/drohnenfuehrer/frontend/public/logo-fallingbostel.png b/drohnenfuehrer/frontend/public/logo-fallingbostel.png
deleted file mode 100644
index bf3e426..0000000
Binary files a/drohnenfuehrer/frontend/public/logo-fallingbostel.png and /dev/null differ
diff --git a/drohnenfuehrer/frontend/public/logo-ljn.png b/drohnenfuehrer/frontend/public/logo-ljn.png
deleted file mode 100644
index a1a6ce9..0000000
Binary files a/drohnenfuehrer/frontend/public/logo-ljn.png and /dev/null differ
diff --git a/drohnenfuehrer/frontend/public/manifest.json b/drohnenfuehrer/frontend/public/manifest.json
index 3ea9347..3cf8f09 100644
--- a/drohnenfuehrer/frontend/public/manifest.json
+++ b/drohnenfuehrer/frontend/public/manifest.json
@@ -19,7 +19,7 @@
"scope": "/drohnenfuehrer/",
"display": "standalone",
"orientation": "portrait",
- "theme_color": "#2d6a2d",
- "background_color": "#ffffff",
+ "theme_color": "#1a3d1a",
+ "background_color": "#e8e8e2",
"description": "Drohnenführer Heidekreis – Übersicht der Drohnenführer"
}
diff --git a/drohnenfuehrer/frontend/public/offline.html b/drohnenfuehrer/frontend/public/offline.html
index c069be4..b1c4d55 100644
--- a/drohnenfuehrer/frontend/public/offline.html
+++ b/drohnenfuehrer/frontend/public/offline.html
@@ -1,16 +1,93 @@
-
+
-
-
- Offline - Drohnenführer
-
+
+
+
+ Offline – Jagd Apps Heidekreis
+
- Du bist offline
- Die App ist derzeit nicht verfügbar. Bitte überprüfe deine Internetverbindung.
+
+
📡
+
Keine Verbindung
+
+ Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
+ Sobald wieder Empfang besteht, lädt die Seite normal.
+
+
+
-
\ No newline at end of file
+
diff --git a/drohnenfuehrer/frontend/src/App.css b/drohnenfuehrer/frontend/src/App.css
index b8f3ffe..b3a77b8 100644
--- a/drohnenfuehrer/frontend/src/App.css
+++ b/drohnenfuehrer/frontend/src/App.css
@@ -2,43 +2,203 @@
box-sizing: border-box;
}
+/* ──────────────────────────────────────────────────────────────────────────
+ Design-Tokens — einzige Farbquelle der App.
+ Palette und Formensprache folgen dem Portal (portal/index.html), damit der
+ Wechsel vom Portal in eine App nicht wie ein Produktwechsel wirkt.
+ Schriftmodell wie im Portal: Serif für die Marken-/Überschriftenebene,
+ Sans für funktionale UI-Texte (auf kleinen Displays besser lesbar).
+
+ Alle Textpaare erfüllen WCAG AA (>= 4.5:1), funktionale Rahmen >= 3.0:1 —
+ in beiden Varianten nachgerechnet.
+ ────────────────────────────────────────────────────────────────────────── */
:root {
- --color-primary: #2e8b2e;
- --color-primary-dark: #1e6b1e;
- --color-primary-accent: #8B0D12;
- --color-secondary: #6c757d;
- --color-secondary-dark: #5a6268;
- --color-success: #28a745;
- --color-success-dark: #218838;
- --color-danger: #dc3545;
- --color-danger-dark: #c82333;
- --color-bg: #f5f5f0;
- --color-surface: #ffffff;
+ --font-display: Georgia, 'Times New Roman', serif;
+ --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-mono: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
+
+ /* Flächen */
+ --color-bg: #e8e8e2;
+ --color-surface: #f4f4ee;
+ --color-surface-alt: #dedcd2;
+ --color-muted-bg: #dedcd2;
+
+ /* Text */
--color-text: #1a1a1a;
- --color-text-muted: #555;
- --color-border: #b8d4b8;
- --color-border-strong: #88b888;
- --color-focus: rgba(46, 139, 46, 0.2);
- --color-muted-bg: #f5f5f0;
- --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.1);
- --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.2);
- --radius-sm: 4px;
- --radius-md: 8px;
- --radius-pill: 12px;
+ --color-text-muted: #55554c;
+
+ /* Rahmen: -border ist dekorativ (Trennlinien, Karten),
+ -border-strong begrenzt Bedienelemente und erfüllt die 3:1-Anforderung. */
+ --color-border: #c9c9b8;
+ --color-border-strong: #7d7d68;
+
+ /* Aktionsfarben – jeweils mit der zugehörigen Textfarbe, damit die
+ Dunkelvariante nicht auf weißem Text auf hellem Grund landet. */
+ --color-primary: #2d5a2d;
+ --color-primary-dark: #1a3d1a;
+ --color-on-primary: #ffffff;
+ --color-secondary: #5c5c50;
+ --color-secondary-dark: #46463c;
+ --color-on-secondary: #ffffff;
+ --color-success: #1f6b34;
+ --color-success-dark: #175128;
+ --color-on-success: #ffffff;
+ --color-danger: #a32020;
+ --color-danger-dark: #821919;
+ --color-on-danger: #ffffff;
+ --color-warning: #7a5200;
+ --color-on-warning: #ffffff;
+ --color-accent: #8b0d12;
+ --color-on-accent: #ffffff;
+ /* Altname, wird von RulesDisplay noch benutzt */
+ --color-primary-accent: #8b0d12;
+
+ /* Getönte Status-Flächen (Meldungen, Badges, Zustands-Karten).
+ Der Block wird durch seine Füllung erkannt, der Rahmen ist Zierde. */
+ --color-success-bg: #dfeedd;
+ --color-success-border: #a9cba4;
+ --color-success-text: #1a4a24;
+ --color-danger-bg: #f6e0e0;
+ --color-danger-border: #d9a9a9;
+ --color-danger-text: #7d1a1a;
+ --color-warning-bg: #f7edd4;
+ --color-warning-border: #d9c48a;
+ --color-warning-text: #5c3d00;
+ --color-info: #24608f;
+ --color-info-dark: #1b4a6e;
+ --color-on-info: #ffffff;
+ --color-info-bg: #dde8f1;
+ --color-info-border: #a5bfd4;
+ --color-info-text: #14405f;
+
+ /* Als RGB-Tripel fuer rgba()-Anwendungen (Puls-Animation im Admin-Panel) */
+ --color-primary-rgb: 45, 90, 45;
+
+ --color-focus: rgba(45, 90, 45, 0.35);
+
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.15);
+ --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.2);
+
+ /* Kantige Ecken wie im Portal */
+ --radius-sm: 2px;
+ --radius-md: 2px;
+ --radius-pill: 2px;
+
--space-1: 0.5rem;
--space-2: 1rem;
--space-3: 1.5rem;
--space-4: 2rem;
+
+ /* Mindestgröße für Bedienelemente auf Touchgeräten */
+ --touch-target: 44px;
}
+/* Nachtvariante. Nachsuchen laufen in der Dämmerung und nachts — ein weißes
+ Vollbild blendet dann und kostet die Dunkeladaption der Augen. Warme, sehr
+ dunkle Grüntöne statt reinem Schwarz. */
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-bg: #14180f;
+ --color-surface: #1e241a;
+ --color-surface-alt: #2a3124;
+ --color-muted-bg: #2a3124;
+
+ --color-text: #e9e7dd;
+ --color-text-muted: #a6a698;
+
+ --color-border: #333b28;
+ --color-border-strong: #758566;
+
+ --color-primary: #7fb36f;
+ --color-primary-dark: #9ccb8c;
+ --color-on-primary: #10140c;
+ --color-secondary: #8d8d80;
+ --color-secondary-dark: #a3a396;
+ --color-on-secondary: #10140c;
+ --color-success: #79c48c;
+ --color-success-dark: #93d3a3;
+ --color-on-success: #10140c;
+ --color-danger: #ea8b8b;
+ --color-danger-dark: #f2a5a5;
+ --color-on-danger: #10140c;
+ --color-warning: #d6b25f;
+ --color-on-warning: #10140c;
+ --color-accent: #e88a8f;
+ --color-on-accent: #10140c;
+ --color-primary-accent: #e88a8f;
+
+ --color-success-bg: #1d2c20;
+ --color-success-border: #3d5c43;
+ --color-success-text: #93d3a3;
+ --color-danger-bg: #33201f;
+ --color-danger-border: #6b4040;
+ --color-danger-text: #f2a5a5;
+ --color-warning-bg: #322a15;
+ --color-warning-border: #63552c;
+ --color-warning-text: #e0c37c;
+ --color-info: #7fb0dc;
+ --color-info-dark: #9cc4e8;
+ --color-on-info: #10140c;
+ --color-info-bg: #1a2530;
+ --color-info-border: #3d5468;
+ --color-info-text: #9cc4e8;
+
+ --color-primary-rgb: 127, 179, 111;
+ --color-focus: rgba(127, 179, 111, 0.45);
+
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
+ --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.6);
+ }
+}
+
+body {
+ margin: 0;
+ font-family: var(--font-ui);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background: var(--color-bg);
+ color: var(--color-text);
+ /* Damit auch vom Browser gestellte Bedienelemente (Bildlaufleisten,
+ Datumsauswahl, Autofill) der gewählten Ansicht folgen. */
+ color-scheme: light dark;
+}
+
+/* Formularfelder brauchen ausdrücklich Farben: ohne sie nimmt der Browser
+ seinen Standard (weiß) — in der Nachtansicht leuchtet dann jedes Eingabefeld. */
+input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='file']),
+select,
+textarea {
+ background: var(--color-surface);
+ color: var(--color-text);
+}
+
+input::placeholder,
+textarea::placeholder {
+ color: var(--color-text-muted);
+ opacity: 1;
+}
+
+h1, h2, h3 {
+ font-family: var(--font-display);
+}
+
+code {
+ font-family: var(--font-mono);
+}
+
+/* ── Bedienelemente ─────────────────────────────────────────────────────── */
+
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-1);
+ min-height: var(--touch-target);
padding: 0.5rem 1rem;
border: none;
border-radius: var(--radius-sm);
+ font-family: var(--font-ui);
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
@@ -46,15 +206,24 @@
}
.btn:disabled {
- background: var(--color-border);
+ background: var(--color-surface-alt);
color: var(--color-text-muted);
cursor: not-allowed;
box-shadow: none;
}
+/* Sichtbarer Tastaturfokus. Ohne das war die Tastaturbedienung unsichtbar —
+ Buttons hatten nur einen :hover-Stil. */
+.btn:focus-visible,
+.nav-button:focus-visible,
+a:focus-visible {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
+
.btn-primary {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.btn-primary:hover:not(:disabled) {
@@ -64,7 +233,7 @@
.btn-secondary {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.btn-secondary:hover:not(:disabled) {
@@ -72,19 +241,9 @@
transform: translateY(-1px);
}
-.btn-success {
- background: var(--color-success);
- color: white;
-}
-
-.btn-success:hover:not(:disabled) {
- background: var(--color-success-dark);
- transform: translateY(-1px);
-}
-
.btn-danger {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.btn-danger:hover:not(:disabled) {
@@ -96,9 +255,13 @@
.select,
.textarea {
width: 100%;
+ min-height: var(--touch-target);
padding: 0.75rem 1rem;
+ background: var(--color-surface);
+ color: var(--color-text);
border: 1px solid var(--color-border-strong);
border-radius: var(--radius-sm);
+ font-family: var(--font-ui);
font-size: 1rem;
box-sizing: border-box;
}
@@ -111,33 +274,19 @@
box-shadow: 0 0 0 3px var(--color-focus);
}
-.panel {
- background: var(--color-surface);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- padding: var(--space-3);
- box-shadow: var(--shadow-sm);
-}
-
.panel-title {
margin: 0 0 var(--space-2);
+ font-family: var(--font-display);
font-size: 1.1rem;
color: var(--color-text);
}
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- background: var(--color-bg);
- color: var(--color-text);
-}
+/* ── Grundgerüst ────────────────────────────────────────────────────────── */
.App {
- min-height: 100vh;
+ /* dvh statt vh: mit ein- und ausblendender Adressleiste auf Mobilgeräten
+ entsteht mit vh sonst Überlauf. */
+ min-height: 100dvh;
display: flex;
flex-direction: column;
}
@@ -151,44 +300,26 @@ body {
display: flex;
justify-content: center;
align-items: center;
- min-height: 100vh;
+ min-height: 100dvh;
font-size: 1.2rem;
color: var(--color-text-muted);
}
-.login-prompt {
- position: fixed;
- bottom: 20px;
- right: 20px;
-}
-
-.login-button-header {
- padding: 0.75rem 1.5rem;
- background: var(--color-primary);
- color: white;
- border: none;
- border-radius: 4px;
- font-size: 1rem;
- font-weight: 600;
- cursor: pointer;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- transition: all 0.2s;
-}
-
-.login-button-header:hover {
- background: var(--color-primary-dark);
- transform: translateY(-2px);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
-}
-
-@media (max-width: 768px) {
- .login-prompt {
- bottom: 10px;
- right: 10px;
+/* Wer Bewegung reduziert haben möchte, bekommt keine Animationen. */
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
}
- .login-button-header {
- padding: 0.6rem 1.2rem;
- font-size: 0.9rem;
+ .btn:hover:not(:disabled),
+ .btn-primary:hover:not(:disabled),
+ .btn-secondary:hover:not(:disabled),
+ .btn-danger:hover:not(:disabled) {
+ transform: none;
}
}
diff --git a/drohnenfuehrer/frontend/src/components/admin/AdminPanel.css b/drohnenfuehrer/frontend/src/components/admin/AdminPanel.css
index 12ce644..16e6fa0 100644
--- a/drohnenfuehrer/frontend/src/components/admin/AdminPanel.css
+++ b/drohnenfuehrer/frontend/src/components/admin/AdminPanel.css
@@ -25,7 +25,7 @@
.tab-button.active {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.settings-panel {
@@ -59,9 +59,9 @@
.unsaved-badge {
display: inline-block;
- background: #fff3cd;
- color: #856404;
- border: 1px solid #ffc107;
+ background: var(--color-warning-bg);
+ color: var(--color-warning-text);
+ border: 1px solid var(--color-warning);
border-radius: var(--radius-sm);
padding: 0.2rem 0.6rem;
font-size: 0.8rem;
@@ -102,7 +102,7 @@
display: flex;
align-items: center;
gap: 0.5rem;
- background: var(--color-muted-bg, #f5f5f0);
+ background: var(--color-muted-bg, var(--color-surface-alt));
border: none;
padding: 0.75rem var(--space-2);
cursor: pointer;
@@ -111,7 +111,7 @@
}
.settings-section-header:hover {
- background: var(--color-focus, #eef2e6);
+ background: var(--color-focus, var(--color-success-bg));
}
.settings-section-header .settings-heading {
@@ -193,7 +193,7 @@
.skeleton-line {
height: 1rem;
border-radius: var(--radius-sm);
- background: linear-gradient(90deg, #e8e8e4 25%, #f0f0ec 50%, #e8e8e4 75%);
+ background: linear-gradient(90deg, var(--color-surface-alt) 25%, var(--color-surface-alt) 50%, var(--color-surface-alt) 75%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.4s infinite;
margin-bottom: 0.75rem;
@@ -323,17 +323,17 @@
.notification.success {
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
}
.notification.error {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.notification.warning {
- background: #e67e00;
- color: white;
+ background: var(--color-warning);
+ color: var(--color-on-warning);
}
@keyframes slideIn {
diff --git a/drohnenfuehrer/frontend/src/components/admin/AuditLogs.css b/drohnenfuehrer/frontend/src/components/admin/AuditLogs.css
index 433cfc4..0f2d27a 100644
--- a/drohnenfuehrer/frontend/src/components/admin/AuditLogs.css
+++ b/drohnenfuehrer/frontend/src/components/admin/AuditLogs.css
@@ -13,8 +13,8 @@
gap: 12px;
flex-wrap: wrap;
}
-.audit-header h2 { margin: 0 0 4px 0; color: #333; font-size: 26px; }
-.audit-description { margin: 0; color: #666; font-size: 13px; }
+.audit-header h2 { margin: 0 0 4px 0; color: var(--color-text); font-size: 26px; }
+.audit-description { margin: 0; color: var(--color-text-muted); font-size: 13px; }
.audit-header-actions {
display: flex;
@@ -32,24 +32,24 @@
}
.btn-stats-toggle {
padding: 6px 14px;
- background: #f0f4f8;
- border: 1px solid #d0d7de;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
font-size: 13px;
- color: #444;
+ color: var(--color-text-muted);
}
-.btn-stats-toggle:hover { background: #e2e8f0; }
+.btn-stats-toggle:hover { background: var(--color-surface-alt); }
.stats-days-select { font-size: 13px; }
.audit-stats {
- background: #f8fafc;
- border: 1px solid #e2e8f0;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
border-radius: 10px;
padding: 16px;
margin-bottom: 16px;
}
-.stats-loading { color: #888; font-size: 13px; padding: 8px 0; }
+.stats-loading { color: var(--color-text-muted); font-size: 13px; padding: 8px 0; }
.stats-row {
display: flex;
@@ -60,18 +60,18 @@
.stat-card {
flex: 1;
min-width: 100px;
- background: white;
+ background: var(--color-surface);
border-radius: 8px;
padding: 12px 16px;
text-align: center;
- border: 1px solid #e2e8f0;
+ border: 1px solid var(--color-border);
}
.stat-number { font-size: 28px; font-weight: 700; line-height: 1; }
-.stat-label { font-size: 11px; color: #666; margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
-.stat-total .stat-number { color: #1976d2; }
-.stat-failed .stat-number { color: #c62828; }
-.stat-success .stat-number { color: #2e7d32; }
-.stat-period .stat-number { color: #555; font-size: 20px; }
+.stat-label { font-size: 11px; color: var(--color-text-muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
+.stat-total .stat-number { color: var(--color-info-text); }
+.stat-failed .stat-number { color: var(--color-danger-text); }
+.stat-success .stat-number { color: var(--color-success-text); }
+.stat-period .stat-number { color: var(--color-text-muted); font-size: 20px; }
.stats-details {
display: flex;
@@ -79,7 +79,7 @@
flex-wrap: wrap;
}
.stats-col { flex: 1; min-width: 180px; }
-.stats-col h4 { margin: 0 0 8px 0; font-size: 12px; text-transform: uppercase; color: #888; letter-spacing: 0.5px; }
+.stats-col h4 { margin: 0 0 8px 0; font-size: 12px; text-transform: uppercase; color: var(--color-text-muted); letter-spacing: 0.5px; }
.stat-bar-row {
display: flex;
@@ -88,8 +88,8 @@
gap: 8px;
margin-bottom: 5px;
}
-.stat-bar-label { font-size: 13px; color: #444; }
-.stat-bar-count { font-size: 13px; font-weight: 600; color: #333; flex-shrink: 0; }
+.stat-bar-label { font-size: 13px; color: var(--color-text-muted); }
+.stat-bar-count { font-size: 13px; font-weight: 600; color: var(--color-text); flex-shrink: 0; }
/* Mini bar chart */
.stats-chart-col { flex: 2; min-width: 220px; }
@@ -98,7 +98,7 @@
align-items: flex-end;
gap: 3px;
height: 80px;
- background: #f0f4f8;
+ background: var(--color-surface-alt);
border-radius: 6px;
padding: 6px 6px 0;
}
@@ -110,7 +110,7 @@
}
.chart-bar {
width: 100%;
- background: #1976d2;
+ background: var(--color-info);
border-radius: 2px 2px 0 0;
position: relative;
min-height: 4px;
@@ -121,7 +121,7 @@
bottom: 0;
left: 0;
width: 100%;
- background: #e53935;
+ background: var(--color-danger);
}
/* ── Filters ─────────────────────────────────────────────────────── */
@@ -134,52 +134,52 @@
}
.filter-select {
padding: 8px 12px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
font-size: 13px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
}
-.filter-select:focus { outline: none; border-color: #1976d2; }
+.filter-select:focus { outline: none; border-color: var(--color-primary); }
.filter-input {
padding: 8px 12px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
font-size: 13px;
- background: white;
+ background: var(--color-surface);
min-width: 140px;
}
-.filter-input:focus { outline: none; border-color: #1976d2; }
+.filter-input:focus { outline: none; border-color: var(--color-primary); }
.filter-date { min-width: 130px; }
.btn-refresh {
padding: 8px 14px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
}
-.btn-refresh:hover:not(:disabled) { background: #1565c0; }
-.btn-refresh:disabled { background: #bdbdbd; cursor: not-allowed; }
+.btn-refresh:hover:not(:disabled) { background: var(--color-info-dark); }
+.btn-refresh:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); cursor: not-allowed; }
.btn-reset {
padding: 8px 12px;
- background: white;
- color: #666;
- border: 1.5px solid #d0d7de;
+ background: var(--color-surface);
+ color: var(--color-text-muted);
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
font-size: 13px;
}
-.btn-reset:hover { background: #f5f5f5; }
+.btn-reset:hover { background: var(--color-surface-alt); }
.btn-export {
padding: 8px 16px;
- background: #2e7d32;
- color: white;
+ background: var(--color-success);
+ color: var(--color-on-success);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -187,15 +187,15 @@
font-weight: 500;
white-space: nowrap;
}
-.btn-export:hover:not(:disabled) { background: #1b5e20; }
-.btn-export:disabled { background: #bdbdbd; cursor: not-allowed; }
+.btn-export:hover:not(:disabled) { background: var(--color-success-dark); }
+.btn-export:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); cursor: not-allowed; }
.auto-refresh-toggle {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
- color: #555;
+ color: var(--color-text-muted);
cursor: pointer;
white-space: nowrap;
}
@@ -206,7 +206,7 @@
justify-content: space-between;
align-items: center;
font-size: 13px;
- color: #666;
+ color: var(--color-text-muted);
margin-bottom: 10px;
}
.limit-select { padding: 4px 8px; font-size: 13px; }
@@ -224,16 +224,16 @@
}
.badge-create { background: #e8f5e9; color: #2e7d32; }
.badge-update { background: #e3f2fd; color: #1565c0; }
-.badge-delete { background: #ffebee; color: #c62828; }
-.badge-restore { background: #fff3e0; color: #e65100; }
+.badge-delete { background: #ffebee; color: var(--color-danger-text); }
+.badge-restore { background: #fff3e0; color: #a83a00; }
.badge-login { background: #f3e5f5; color: #6a1b9a; }
.badge-logout { background: #fce4ec; color: #880e4f; }
.badge-login-failed { background: #ffcdd2; color: #b71c1c; font-weight: 700; }
.badge-import { background: #e0f7fa; color: #00695c; }
.badge-export { background: #e8f5e9; color: #1b5e20; }
-.badge-bulk-update { background: #e8eaf6; color: #283593; }
+.badge-bulk-update { background: var(--color-surface-alt); color: #283593; }
.badge-bulk-delete { background: #fbe9e7; color: #bf360c; }
-.badge-password { background: #fff8e1; color: #f57f17; }
+.badge-password { background: #fff8e1; color: #9c4e00; }
.badge-default { background: #f5f5f5; color: #616161; }
.status-code {
@@ -244,16 +244,16 @@
font-family: monospace;
}
.status-ok { background: #e8f5e9; color: #2e7d32; }
-.status-redirect { background: #fff3e0; color: #e65100; }
-.status-error { background: #ffebee; color: #c62828; }
+.status-redirect { background: #fff3e0; color: #a83a00; }
+.status-error { background: #ffebee; color: var(--color-danger-text); }
.status-server-error { background: #f3e5f5; color: #6a1b9a; }
.duration-badge {
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
- background: #f5f5f5;
- color: #777;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
font-family: monospace;
}
@@ -261,24 +261,24 @@
.audit-empty {
text-align: center;
padding: 40px;
- background: #f9f9f9;
+ background: var(--color-surface-alt);
border-radius: 8px;
- color: #888;
+ color: var(--color-text-muted);
}
.audit-error { text-align: center; padding: 20px; }
-.audit-error p { color: #d32f2f; margin: 0; }
+.audit-error p { color: var(--color-danger-text); margin: 0; }
.audit-list { display: flex; flex-direction: column; gap: 8px; }
.audit-item {
- background: white;
- border: 1px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
overflow: hidden;
transition: box-shadow 0.15s;
}
.audit-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
-.audit-item-failed { border-left: 4px solid #e53935; }
+.audit-item-failed { border-left: 4px solid var(--color-danger); }
.audit-item-header {
display: flex;
@@ -286,18 +286,18 @@
gap: 8px;
padding: 10px 14px;
flex-wrap: wrap;
- background: #fafafa;
- border-bottom: 1px solid #f0f0f0;
+ background: var(--color-surface-alt);
+ border-bottom: 1px solid var(--color-border);
}
-.audit-time { margin-left: auto; color: #999; font-size: 12px; white-space: nowrap; }
-.expand-toggle { color: #aaa; font-size: 11px; cursor: pointer; padding: 0 4px; }
+.audit-time { margin-left: auto; color: var(--color-text-muted); font-size: 12px; white-space: nowrap; }
+.expand-toggle { color: var(--color-text-muted); font-size: 11px; cursor: pointer; padding: 0 4px; }
.audit-resource {
padding: 3px 8px;
- background: #f0f0f0;
+ background: var(--color-surface-alt);
border-radius: 4px;
font-size: 12px;
- color: #555;
+ color: var(--color-text-muted);
}
.audit-item-body {
@@ -308,16 +308,16 @@
font-size: 13px;
align-items: center;
}
-.audit-admin { color: #333; }
-.audit-resource-name { color: #555; }
-.audit-ip { color: #999; font-family: monospace; font-size: 12px; }
-.audit-failed-badge { color: #c62828; font-weight: 600; font-size: 12px; }
+.audit-admin { color: var(--color-text); }
+.audit-resource-name { color: var(--color-text-muted); }
+.audit-ip { color: var(--color-text-muted); font-family: monospace; font-size: 12px; }
+.audit-failed-badge { color: var(--color-danger-text); font-weight: 600; font-size: 12px; }
/* ── Expanded detail ─────────────────────────────────────────────── */
.audit-item-detail {
padding: 10px 14px 14px;
- border-top: 1px dashed #e0e0e0;
- background: #fefefe;
+ border-top: 1px dashed var(--color-border);
+ background: var(--color-surface);
display: flex;
flex-direction: column;
gap: 8px;
@@ -330,7 +330,7 @@
}
.detail-label {
font-weight: 600;
- color: #888;
+ color: var(--color-text-muted);
font-size: 11px;
text-transform: uppercase;
min-width: 70px;
@@ -338,23 +338,23 @@
}
.detail-row code {
font-family: monospace;
- background: #f0f0f0;
+ background: var(--color-surface-alt);
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
}
.detail-ua-full {
- color: #aaa;
+ color: var(--color-text-muted);
cursor: help;
font-size: 12px;
}
-.detail-error { color: #c62828; }
-.detail-error .detail-label { color: #c62828; }
+.detail-error { color: var(--color-danger-text); }
+.detail-error .detail-label { color: var(--color-danger-text); }
.meta-tag {
display: inline-block;
- background: #e8eaf6;
- color: #283593;
+ background: var(--color-surface-alt);
+ color: var(--color-info-text);
border-radius: 4px;
padding: 2px 8px;
font-size: 12px;
@@ -370,17 +370,17 @@
margin-top: 6px;
}
.diff-table th {
- background: #f0f0f0;
+ background: var(--color-surface-alt);
padding: 5px 10px;
text-align: left;
font-size: 11px;
text-transform: uppercase;
- color: #666;
- border: 1px solid #e0e0e0;
+ color: var(--color-text-muted);
+ border: 1px solid var(--color-border);
}
-.diff-table td { padding: 5px 10px; border: 1px solid #e8e8e8; vertical-align: top; }
-.diff-field { font-weight: 600; color: #444; font-family: monospace; white-space: nowrap; background: #fafafa; }
-.diff-before { color: #c62828; background: #fff5f5; font-family: monospace; word-break: break-all; }
+.diff-table td { padding: 5px 10px; border: 1px solid var(--color-border); vertical-align: top; }
+.diff-field { font-weight: 600; color: var(--color-text-muted); font-family: monospace; white-space: nowrap; background: var(--color-surface-alt); }
+.diff-before { color: var(--color-danger-text); background: #fff5f5; font-family: monospace; word-break: break-all; }
.diff-after { color: #2e7d32; background: #f5fff5; font-family: monospace; word-break: break-all; }
/* ── Pagination ──────────────────────────────────────────────────── */
@@ -393,16 +393,16 @@
}
.btn-page {
padding: 7px 14px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
font-size: 13px;
- color: #333;
+ color: var(--color-text);
}
-.btn-page:hover:not(:disabled) { background: #f0f4f8; border-color: #1976d2; }
-.btn-page:disabled { color: #bbb; cursor: not-allowed; border-color: #eee; }
-.page-info { font-size: 13px; color: #666; padding: 0 8px; }
+.btn-page:hover:not(:disabled) { background: var(--color-surface-alt); border-color: var(--color-primary); }
+.btn-page:disabled { color: var(--color-text-muted); cursor: not-allowed; border-color: var(--color-border); }
+.page-info { font-size: 13px; color: var(--color-text-muted); padding: 0 8px; }
.audit-header {
@@ -411,13 +411,13 @@
.audit-header h2 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
}
.audit-description {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -428,7 +428,7 @@
}
.audit-error p {
- color: #d32f2f;
+ color: var(--color-danger-text);
margin: 0;
}
@@ -441,23 +441,23 @@
.filter-select {
padding: 10px 14px;
- border: 2px solid #e0e0e0;
+ border: 2px solid var(--color-border);
border-radius: 6px;
font-size: 14px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
transition: border-color 0.2s;
}
.filter-select:focus {
outline: none;
- border-color: #1976d2;
+ border-color: var(--color-primary);
}
.btn-refresh {
padding: 10px 16px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -467,20 +467,21 @@
}
.btn-refresh:hover:not(:disabled) {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.btn-refresh:disabled {
- background: #bdbdbd;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
cursor: not-allowed;
}
.audit-empty {
text-align: center;
padding: 40px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 8px;
- color: #666;
+ color: var(--color-text-muted);
}
.audit-list {
@@ -490,8 +491,8 @@
}
.audit-item {
- background: white;
- border: 1px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 16px;
transition: box-shadow 0.2s;
@@ -519,58 +520,18 @@
gap: 4px;
}
-.badge-create {
- background: #e8f5e9;
- color: #2e7d32;
-}
-
-.badge-update {
- background: #e3f2fd;
- color: #1565c0;
-}
-
-.badge-delete {
- background: #ffebee;
- color: #c62828;
-}
-
-.badge-restore {
- background: #fff3e0;
- color: #e65100;
-}
-
-.badge-login {
- background: #f3e5f5;
- color: #6a1b9a;
-}
-
-.badge-logout {
- background: #fce4ec;
- color: #880e4f;
-}
-
-.badge-login-failed {
- background: #ffcdd2;
- color: #b71c1c;
- font-weight: 700;
-}
-
-.badge-default {
- background: #f5f5f5;
- color: #616161;
-}
.audit-resource {
padding: 4px 10px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 4px;
font-size: 13px;
- color: #666;
+ color: var(--color-text-muted);
}
.audit-time {
margin-left: auto;
- color: #999;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -582,23 +543,19 @@
}
.audit-admin {
- color: #333;
+ color: var(--color-text);
}
.audit-resource-name {
- color: #666;
+ color: var(--color-text-muted);
}
.audit-ip {
- color: #888;
+ color: var(--color-text-muted);
font-family: monospace;
font-size: 13px;
}
-.audit-error-message {
- color: #d32f2f;
- font-weight: 500;
-}
.audit-pagination {
display: flex;
@@ -607,15 +564,15 @@
gap: 16px;
margin-top: 24px;
padding: 16px;
- background: white;
+ background: var(--color-surface);
border-radius: 8px;
- border: 1px solid #e0e0e0;
+ border: 1px solid var(--color-border);
}
.btn-page {
padding: 8px 16px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -624,16 +581,17 @@
}
.btn-page:hover:not(:disabled) {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.btn-page:disabled {
- background: #bdbdbd;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
cursor: not-allowed;
}
.page-info {
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -656,3 +614,33 @@
width: 100%;
}
}
+
+/* ── Nachtvariante ───────────────────────────────────────────────────────
+ Die Badges kodieren die Aktionsart über den Farbton – der bleibt erhalten,
+ nur Helligkeit und Sättigung drehen sich um. Alle Paare >= 6.4:1. */
+@media (prefers-color-scheme: dark) {
+ .badge-create { background: #162d17; color: #97d99a; }
+ .badge-update { background: #16202d; color: #89b5e6; }
+ .badge-delete { background: #2d1616; color: #e68989; }
+ .badge-restore { background: #2d1e16; color: #e6aa89; }
+ .badge-login { background: #24162d; color: #c389e6; }
+ .badge-logout { background: #2d1622; color: #e689bb; }
+ .badge-login-failed { background: #2d1616; color: #e68989; }
+ .badge-import { background: #162d2a; color: #89e6db; }
+ .badge-export { background: #162d17; color: #90df96; }
+ .badge-bulk-update { background: #16182d; color: #8f99e0; }
+ .badge-bulk-delete { background: #2d1b16; color: #e69f89; }
+ .badge-password { background: #2d2016; color: #e6b589; }
+ .badge-default { background: var(--color-surface-alt); color: var(--color-text-muted); }
+
+ .status-ok { background: #162d17; color: #97d99a; }
+ .status-redirect { background: #2d1e16; color: #e6aa89; }
+ .status-error { background: #2d1616; color: #e68989; }
+ .status-server-error { background: #24162d; color: #c389e6; }
+
+ /* Diff-Tabelle: die roten/gruenen Vorher-Nachher-Felder */
+ .diff-table th { background: var(--color-surface-alt); }
+ .diff-before { color: #e68989; background: #2d1616; }
+ .diff-after { color: #97d99a; background: #162d17; }
+ .diff-field { background: var(--color-surface-alt); color: var(--color-text); }
+}
diff --git a/drohnenfuehrer/frontend/src/components/admin/ExportButton.css b/drohnenfuehrer/frontend/src/components/admin/ExportButton.css
index 83981da..c231346 100644
--- a/drohnenfuehrer/frontend/src/components/admin/ExportButton.css
+++ b/drohnenfuehrer/frontend/src/components/admin/ExportButton.css
@@ -14,7 +14,7 @@
.export-button {
padding: 0.5rem 1rem;
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -41,8 +41,8 @@
.import-button {
padding: 0.5rem 1rem;
- background: var(--color-primary, #2563eb);
- color: white;
+ background: var(--color-primary, var(--color-info));
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -52,7 +52,7 @@
}
.import-button:hover:not(:disabled) {
- background: var(--color-primary-dark, #1d4ed8);
+ background: var(--color-primary-dark, var(--color-info-dark));
}
.import-button:disabled {
@@ -65,7 +65,7 @@
align-items: center;
gap: 0.4rem;
font-size: 0.85rem;
- color: var(--color-text-muted, #6b7280);
+ color: var(--color-text-muted);
cursor: pointer;
white-space: nowrap;
}
diff --git a/drohnenfuehrer/frontend/src/components/admin/Trash.css b/drohnenfuehrer/frontend/src/components/admin/Trash.css
index 200c68a..e70ac72 100644
--- a/drohnenfuehrer/frontend/src/components/admin/Trash.css
+++ b/drohnenfuehrer/frontend/src/components/admin/Trash.css
@@ -10,13 +10,13 @@
.trash-header h2 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
}
.trash-description {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -27,14 +27,14 @@
}
.trash-error h3 {
- color: #d32f2f;
+ color: var(--color-danger-text);
margin-bottom: 12px;
}
.btn-retry {
padding: 10px 20px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -43,13 +43,13 @@
}
.btn-retry:hover {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.trash-empty {
text-align: center;
padding: 60px 20px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 12px;
}
@@ -60,7 +60,7 @@
}
.trash-empty p {
- color: #666;
+ color: var(--color-text-muted);
font-size: 16px;
margin: 0;
}
@@ -72,8 +72,8 @@
}
.trash-item {
- background: #fff;
- border: 2px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 2px solid var(--color-border);
border-radius: 8px;
padding: 16px 20px;
display: flex;
@@ -84,7 +84,7 @@
.trash-item:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- border-color: #bdbdbd;
+ border-color: var(--color-border);
}
.trash-item-info {
@@ -93,7 +93,7 @@
.trash-item-info h3 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 18px;
font-weight: 600;
}
@@ -106,8 +106,8 @@
}
.trash-item-type {
- background: #e3f2fd;
- color: #1976d2;
+ background: var(--color-info-bg);
+ color: var(--color-info-text);
padding: 4px 10px;
border-radius: 4px;
font-size: 13px;
@@ -116,12 +116,12 @@
.trash-item-address,
.trash-item-phone {
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
.trash-item-meta {
- color: #999;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -140,8 +140,8 @@
align-items: center;
gap: 6px;
padding: 10px 16px;
- background: #4caf50;
- color: white;
+ background: var(--color-success);
+ color: var(--color-on-success);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -151,7 +151,7 @@
}
.btn-restore:hover:not(:disabled) {
- background: #45a049;
+ background: var(--color-success-dark);
transform: translateY(-1px);
}
@@ -160,7 +160,7 @@
}
.btn-restore:disabled {
- background: #bdbdbd;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
diff --git a/drohnenfuehrer/frontend/src/components/auth/LoginForm.css b/drohnenfuehrer/frontend/src/components/auth/LoginForm.css
index 1a38755..56024ab 100644
--- a/drohnenfuehrer/frontend/src/components/auth/LoginForm.css
+++ b/drohnenfuehrer/frontend/src/components/auth/LoginForm.css
@@ -56,7 +56,7 @@
width: 100%;
padding: 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
font-size: 1rem;
@@ -76,8 +76,8 @@
.login-error {
padding: 0.75rem;
- background: #ffebee;
- border: 1px solid #ffcdd2;
+ background: var(--color-danger-bg);
+ border: 1px solid var(--color-danger-border);
border-radius: var(--radius-sm);
color: var(--color-danger);
margin-bottom: 1rem;
diff --git a/drohnenfuehrer/frontend/src/components/auth/PasswordReset.css b/drohnenfuehrer/frontend/src/components/auth/PasswordReset.css
index cd3c067..4ee08d1 100644
--- a/drohnenfuehrer/frontend/src/components/auth/PasswordReset.css
+++ b/drohnenfuehrer/frontend/src/components/auth/PasswordReset.css
@@ -1,5 +1,6 @@
.password-reset-container {
- min-height: 100vh;
+ /* dvh: mit ein- und ausblendender Adressleiste entsteht mit vh Überlauf. */
+ min-height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
@@ -8,7 +9,7 @@
}
.password-reset-card {
- background: white;
+ background: var(--color-surface);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
padding: 40px;
@@ -18,7 +19,7 @@
.password-reset-card h2 {
margin: 0 0 24px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
text-align: center;
}
@@ -32,15 +33,15 @@
}
.message.success {
- background-color: #d4edda;
- color: #155724;
- border: 1px solid #c3e6cb;
+ background-color: var(--color-success-bg);
+ color: var(--color-success-text);
+ border: 1px solid var(--color-success-border);
}
.message.error {
- background-color: #f8d7da;
- color: #721c24;
- border: 1px solid #f5c6cb;
+ background-color: var(--color-danger-bg);
+ color: var(--color-danger-text);
+ border: 1px solid var(--color-danger-border);
}
.form-group {
@@ -50,7 +51,7 @@
.form-group label {
display: block;
margin-bottom: 8px;
- color: #555;
+ color: var(--color-text-muted);
font-weight: 500;
font-size: 14px;
}
@@ -58,7 +59,7 @@
.form-group input {
width: 100%;
padding: 12px 16px;
- border: 2px solid #e0e0e0;
+ border: 2px solid var(--color-border);
border-radius: 8px;
font-size: 15px;
transition: border-color 0.3s;
@@ -71,14 +72,14 @@
}
.form-group input:disabled {
- background-color: #f5f5f5;
+ background-color: var(--color-surface-alt);
cursor: not-allowed;
}
.form-group small {
display: block;
margin-top: 6px;
- color: #888;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -86,7 +87,7 @@
width: 100%;
padding: 14px;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 8px;
font-size: 16px;
diff --git a/drohnenfuehrer/frontend/src/components/common/ErrorMessage.css b/drohnenfuehrer/frontend/src/components/common/ErrorMessage.css
index 38733d8..efba2ba 100644
--- a/drohnenfuehrer/frontend/src/components/common/ErrorMessage.css
+++ b/drohnenfuehrer/frontend/src/components/common/ErrorMessage.css
@@ -4,10 +4,10 @@
gap: 0.5rem;
padding: 1rem;
margin: 1rem 0;
- background-color: #fee;
- border: 1px solid #fcc;
+ background-color: var(--color-danger-bg);
+ border: 1px solid var(--color-danger-border);
border-radius: 4px;
- color: #c33;
+ color: var(--color-danger-text);
}
.error-icon {
@@ -22,7 +22,7 @@
background: none;
border: none;
font-size: 1.5rem;
- color: #c33;
+ color: var(--color-danger-text);
cursor: pointer;
padding: 0;
width: 24px;
@@ -34,5 +34,5 @@
}
.error-close:hover {
- color: #a22;
+ color: var(--color-danger-text);
}
diff --git a/drohnenfuehrer/frontend/src/components/common/Header.css b/drohnenfuehrer/frontend/src/components/common/Header.css
index 69a023f..dd3e83d 100644
--- a/drohnenfuehrer/frontend/src/components/common/Header.css
+++ b/drohnenfuehrer/frontend/src/components/common/Header.css
@@ -1,6 +1,6 @@
.app-header {
- background: #ffffff;
- border-bottom: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border-bottom: 1px solid var(--color-border);
padding: 0.75rem 2rem;
display: flex;
align-items: center;
@@ -27,7 +27,7 @@
.portal-back-link:hover {
background: var(--color-primary);
- color: #fff;
+ color: var(--color-on-primary);
}
.app-brand {
@@ -40,18 +40,18 @@
height: 52px;
width: auto;
object-fit: contain;
-}
-
-.app-logo-ljn {
- height: 44px;
+ flex-shrink: 0;
}
.app-title {
margin: 0;
+ font-family: var(--font-display);
font-size: 1.05rem;
font-weight: 700;
color: var(--color-text);
- white-space: nowrap;
+ /* Kein nowrap: lange App-Namen haben die Kopfzeile sonst über die
+ Bildschirmbreite hinaus geschoben. */
+ overflow-wrap: anywhere;
}
.app-nav {
@@ -61,11 +61,14 @@
}
.nav-button {
+ display: inline-flex;
+ align-items: center;
+ min-height: var(--touch-target);
padding: 0.5rem 0.875rem;
background: none;
border: none;
border-radius: var(--radius-sm);
- color: #333;
+ color: var(--color-text);
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
@@ -97,12 +100,19 @@
.app-header {
flex-direction: column;
align-items: flex-start;
- padding: 0.75rem 1rem;
- gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ gap: 0.4rem;
+ /* Auf schmalen Geräten nimmt die umgebrochene Kopfzeile viel Höhe ein.
+ Klebrig bleibt sie nur dort, wo genug Platz ist. */
+ position: static;
}
.app-title {
- font-size: 0.9rem;
+ font-size: 0.95rem;
+ }
+
+ .app-logo {
+ height: 36px;
}
.app-nav {
@@ -111,7 +121,31 @@
}
.nav-button {
- font-size: 0.85rem;
+ font-size: 0.9rem;
padding: 0.4rem 0.7rem;
}
}
+
+@media (max-width: 480px) {
+ .app-header {
+ padding: 0.5rem 0.75rem;
+ }
+
+ .app-brand {
+ gap: 0.5rem;
+ }
+
+ .app-logo {
+ height: 30px;
+ }
+
+ .app-nav {
+ width: 100%;
+ }
+
+ .nav-button {
+ flex: 1 1 45%;
+ justify-content: center;
+ padding: 0.4rem 0.5rem;
+ }
+}
diff --git a/drohnenfuehrer/frontend/src/components/common/InstallBanner.css b/drohnenfuehrer/frontend/src/components/common/InstallBanner.css
index f5b248d..0ab554a 100644
--- a/drohnenfuehrer/frontend/src/components/common/InstallBanner.css
+++ b/drohnenfuehrer/frontend/src/components/common/InstallBanner.css
@@ -2,8 +2,8 @@
position: sticky;
top: 0;
z-index: 1000;
- background-color: #2d6a2d;
- color: #fff;
+ background-color: var(--color-primary);
+ color: var(--color-on-primary);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
@@ -22,8 +22,8 @@
}
.install-banner__btn {
- background: #fff;
- color: #2d6a2d;
+ background: var(--color-surface);
+ color: var(--color-primary);
border: none;
border-radius: 4px;
padding: 0.35rem 0.85rem;
@@ -34,7 +34,7 @@
}
.install-banner__btn:hover {
- background: #e8f5e9;
+ background: var(--color-success-bg);
}
.install-banner__close {
@@ -49,7 +49,7 @@
}
.install-banner__close:hover {
- color: #fff;
+ color: var(--color-on-primary);
}
.install-banner__share-icon {
diff --git a/drohnenfuehrer/frontend/src/components/common/Loading.css b/drohnenfuehrer/frontend/src/components/common/Loading.css
index ec8df60..e1dbe74 100644
--- a/drohnenfuehrer/frontend/src/components/common/Loading.css
+++ b/drohnenfuehrer/frontend/src/components/common/Loading.css
@@ -8,8 +8,8 @@
}
.spinner {
- border: 4px solid #f3f3f3;
- border-top: 4px solid #3498db;
+ border: 4px solid var(--color-border);
+ border-top: 4px solid var(--color-primary);
border-radius: 50%;
width: 50px;
height: 50px;
@@ -23,6 +23,6 @@
.loading-message {
margin-top: 1rem;
- color: #666;
+ color: var(--color-text-muted);
font-size: 0.9rem;
}
diff --git a/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerDashboard.css b/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerDashboard.css
index 5a312bb..3109209 100644
--- a/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerDashboard.css
+++ b/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerDashboard.css
@@ -5,7 +5,7 @@
}
.drohnenfuehrer-dashboard-card {
- background: white;
+ background: var(--color-surface);
border-radius: 10px;
padding: 2rem;
width: 100%;
@@ -46,7 +46,7 @@
.btn-drohnenfuehrer-logout:hover {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.drohnenfuehrer-message {
@@ -56,8 +56,8 @@
font-size: 0.9rem;
}
-.drohnenfuehrer-message-success { background: #dcfce7; color: #166534; }
-.drohnenfuehrer-message-error { background: #fee2e2; color: #b91c1c; }
+.drohnenfuehrer-message-success { background: var(--color-success-bg); color: var(--color-success-text); }
+.drohnenfuehrer-message-error { background: var(--color-danger-bg); color: var(--color-danger-text); }
.drohnenfuehrer-availability-section {
background: var(--color-muted-bg);
@@ -92,15 +92,15 @@
.availability-big-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-green {
- background: #dcfce7;
- color: #15803d;
- border-color: #86efac;
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
+ border-color: var(--color-success-border);
}
.btn-red {
- background: #fee2e2;
- color: #b91c1c;
- border-color: #fca5a5;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
+ border-color: var(--color-danger-border);
}
.status-dot-lg {
@@ -110,8 +110,8 @@
flex-shrink: 0;
}
-.dot-green { background: #22c55e; }
-.dot-red { background: #ef4444; }
+.dot-green { background: var(--color-success); }
+.dot-red { background: var(--color-danger); }
.availability-hint {
font-size: 0.82rem;
@@ -147,7 +147,7 @@
font-size: 0.9rem;
}
-.btn-drohnenfuehrer-edit:hover { background: var(--color-primary); color: white; }
+.btn-drohnenfuehrer-edit:hover { background: var(--color-primary); color: var(--color-on-primary); }
.drohnenfuehrer-info-list { display: flex; flex-direction: column; gap: 0.6rem; }
@@ -206,7 +206,7 @@
flex: 1;
padding: 0.65rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 6px;
font-size: 0.95rem;
diff --git a/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerLogin.css b/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerLogin.css
index abca037..f7e71b9 100644
--- a/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerLogin.css
+++ b/drohnenfuehrer/frontend/src/components/drohnenfuehrer/DrohnenfuehrerLogin.css
@@ -6,7 +6,7 @@
}
.drohnenfuehrer-login-card {
- background: white;
+ background: var(--color-surface);
border-radius: 10px;
padding: 2rem;
width: 100%;
@@ -48,7 +48,7 @@
.drohnenfuehrer-mode-toggle button.active {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
font-weight: 600;
}
@@ -82,7 +82,7 @@
width: 100%;
padding: 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 6px;
font-size: 1rem;
@@ -102,8 +102,8 @@
}
.drohnenfuehrer-error {
- background: #fee2e2;
- color: #b91c1c;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
border-radius: 4px;
padding: 0.6rem 0.9rem;
margin-bottom: 1rem;
@@ -111,8 +111,8 @@
}
.drohnenfuehrer-success {
- background: #dcfce7;
- color: #166534;
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
border-radius: 4px;
padding: 0.6rem 0.9rem;
margin-bottom: 1rem;
diff --git a/drohnenfuehrer/frontend/src/components/map/MapView.css b/drohnenfuehrer/frontend/src/components/map/MapView.css
index bfb9cff..6e82ee3 100644
--- a/drohnenfuehrer/frontend/src/components/map/MapView.css
+++ b/drohnenfuehrer/frontend/src/components/map/MapView.css
@@ -13,32 +13,32 @@
left: 12px;
z-index: 500;
background: rgba(255, 255, 255, 0.95);
- color: #444;
+ color: var(--color-text-muted);
padding: 0.45rem 0.7rem;
border-radius: 6px;
font-size: 0.85rem;
- border: 1px solid #dcdcdc;
+ border: 1px solid var(--color-border);
}
.map-no-data {
padding: 3rem;
text-align: center;
- color: #666;
- background: white;
+ color: var(--color-text-muted);
+ background: var(--color-surface);
border-radius: 8px;
margin: 1rem 0;
}
.map-popup h3 {
margin: 0 0 0.5rem 0;
- color: #333;
+ color: var(--color-text);
font-size: 1rem;
}
.map-popup p {
margin: 0.25rem 0;
font-size: 0.85rem;
- color: #666;
+ color: var(--color-text-muted);
}
.map-popup a {
@@ -54,8 +54,40 @@
display: inline-block;
padding: 0.2rem 0.5rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border-radius: 4px;
font-size: 0.75rem;
margin-top: 0.5rem;
}
+
+/* ── Nachtansicht ────────────────────────────────────────────────────────
+ Die OSM-Kacheln sind immer taghell. In der Dämmerung ist die Karte damit
+ die mit Abstand hellste Fläche der App und blendet — genau die Situation,
+ in der Nachsuchen stattfinden. Die Kacheln werden deshalb abgedunkelt;
+ Marker und Bedienelemente bleiben unangetastet, damit sie lesbar sind. */
+@media (prefers-color-scheme: dark) {
+ .leaflet-tile-pane {
+ filter: brightness(0.62) saturate(0.75) contrast(1.05);
+ }
+
+ .leaflet-container {
+ background: var(--color-surface-alt);
+ }
+
+ /* Hoehere Spezifitaet als Leaflets eigene Regeln, die spaeter geladen werden */
+ .leaflet-container .leaflet-control-zoom a,
+ .leaflet-container .leaflet-control-attribution {
+ background: var(--color-surface);
+ color: var(--color-text);
+ }
+
+ .leaflet-container .leaflet-control-attribution a {
+ color: var(--color-primary);
+ }
+
+ .leaflet-popup-content-wrapper,
+ .leaflet-popup-tip {
+ background: var(--color-surface);
+ color: var(--color-text);
+ }
+}
diff --git a/drohnenfuehrer/frontend/src/components/public/PublicUserList.css b/drohnenfuehrer/frontend/src/components/public/PublicUserList.css
index c24d538..eb2084f 100644
--- a/drohnenfuehrer/frontend/src/components/public/PublicUserList.css
+++ b/drohnenfuehrer/frontend/src/components/public/PublicUserList.css
@@ -14,7 +14,7 @@
}
.public-user-list h2 {
- color: #1a1a1a;
+ color: var(--color-text);
margin: 0;
font-size: 1.5rem;
font-weight: 700;
@@ -23,7 +23,7 @@
.toggle-map-button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -44,8 +44,8 @@
.filter-toggle-button {
padding: 0.5rem 1rem;
- background: #6c757d;
- color: white;
+ background: var(--color-secondary);
+ color: var(--color-on-secondary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -55,12 +55,12 @@
}
.filter-toggle-button:hover {
- background: #5a6268;
+ background: var(--color-secondary-dark);
}
.location-panel {
- background: white;
- border: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1rem 1.5rem;
margin-bottom: 1.5rem;
@@ -78,7 +78,7 @@
.location-button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -92,7 +92,7 @@
}
.location-button:disabled {
- background: #b6b6b6;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
@@ -103,13 +103,13 @@
}
.location-status.success {
- background: #e8f5e9;
- color: var(--color-primary-dark);
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
}
.location-status.error {
- background: #ffebee;
- color: #c62828;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
}
.postal-search {
@@ -120,21 +120,21 @@
.postal-search input[type="text"] {
padding: 0.5rem;
- border: 1px solid #ddd;
+ border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 0.9rem;
width: 150px;
}
.postal-search input[type="text"]:disabled {
- background: #f5f5f5;
+ background: var(--color-surface-alt);
cursor: not-allowed;
}
.postal-search button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -148,14 +148,14 @@
}
.postal-search button:disabled {
- background: #b6b6b6;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
.radius-filter label {
display: block;
font-size: 0.9rem;
- color: #555;
+ color: var(--color-text-muted);
margin-bottom: 0.5rem;
font-weight: 500;
}
@@ -174,26 +174,26 @@
.radius-inputs input[type="number"] {
width: 80px;
padding: 0.4rem 0.5rem;
- border: 1px solid #ddd;
+ border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 0.9rem;
}
.radius-inputs input:disabled {
- background: #f5f5f5;
+ background: var(--color-surface-alt);
cursor: not-allowed;
}
.radius-hint {
font-size: 0.85rem;
- color: #777;
+ color: var(--color-text-muted);
margin-top: 0.5rem;
}
.gps-hint {
margin-top: 0.5rem;
font-size: 0.85rem;
- color: #777;
+ color: var(--color-text-muted);
}
.user-grid {
@@ -205,8 +205,8 @@
/* Jägerschaft-style card */
.user-card {
- background: white;
- border: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
@@ -232,9 +232,9 @@
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
}
-.user-name {
+.public-user-list .user-name {
margin: 0 0 0.2rem;
- color: #1a1a1a;
+ color: var(--color-text);
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
@@ -250,15 +250,15 @@
color: var(--color-primary);
}
-.user-info {
+.public-user-list .user-info {
display: flex;
flex-direction: column;
gap: 0.375rem;
}
-.user-address {
+.public-user-list .user-address {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 0.9rem;
}
@@ -266,72 +266,80 @@
margin: 0.5rem 0 0;
}
-.type-badge {
+.public-user-list .type-badge {
display: inline-block;
padding: 0.2rem 0.6rem;
- background: #f0f0f0;
- color: #444;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
border-radius: 4px;
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.03em;
}
+/* Der Anruf beim Drohnenführer ist der Zweck dieser Liste und wird fast
+ immer mit dem Daumen auf dem Handy ausgelöst. Vorher war das ein 14 px hoher
+ Textlink; jetzt ein vollwertiges Ziel mit der empfohlenen Mindesthöhe. */
.user-phone {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ min-height: var(--touch-target);
+ margin: 0.15rem 0;
+ padding: 0.35rem 0.6rem;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-sm);
color: var(--color-primary);
text-decoration: none;
- font-weight: 500;
- font-size: 0.9rem;
+ font-weight: 600;
+ font-size: 1rem;
}
-.user-phone:hover {
+.public-user-list .user-phone:hover,
+.public-user-list .user-phone:focus-visible {
+ background: var(--color-surface);
+ border-color: var(--color-border-strong);
text-decoration: underline;
}
-.user-gps {
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid #e5e5e5;
- font-size: 0.85rem;
- color: #888;
-}
.user-distance {
margin-top: 0.75rem;
padding-top: 0.75rem;
- border-top: 1px solid #e5e5e5;
+ border-top: 1px solid var(--color-border);
font-size: 0.85rem;
- color: #555;
+ color: var(--color-text-muted);
font-weight: 500;
}
.no-users {
text-align: center;
padding: 3rem;
- color: #666;
+ color: var(--color-text-muted);
}
.loading {
text-align: center;
padding: 3rem;
- color: #666;
+ color: var(--color-text-muted);
}
@media (max-width: 768px) {
- .user-grid {
+.user-grid {
grid-template-columns: 1fr;
}
- .public-user-list {
+.public-user-list {
padding: 1rem;
}
- .radius-inputs {
+.radius-inputs {
flex-direction: column;
align-items: stretch;
}
- .radius-inputs input[type="number"] {
+.radius-inputs input[type="number"] {
width: 100%;
}
}
diff --git a/drohnenfuehrer/frontend/src/components/public/RulesDisplay.css b/drohnenfuehrer/frontend/src/components/public/RulesDisplay.css
index 32be9b6..4ec7a73 100644
--- a/drohnenfuehrer/frontend/src/components/public/RulesDisplay.css
+++ b/drohnenfuehrer/frontend/src/components/public/RulesDisplay.css
@@ -33,7 +33,7 @@
}
.allgemeines-tab-btn.active {
- background: white;
+ background: var(--color-surface);
color: var(--color-primary);
font-weight: 700;
border-color: var(--color-primary);
@@ -41,7 +41,7 @@
}
.allgemeines-content {
- background: white;
+ background: var(--color-surface);
border: 1px solid var(--color-primary);
border-top: none;
border-radius: 0 0 8px 8px;
diff --git a/drohnenfuehrer/frontend/src/components/users/UserCard.css b/drohnenfuehrer/frontend/src/components/users/UserCard.css
index a6f6bb7..2c62fa9 100644
--- a/drohnenfuehrer/frontend/src/components/users/UserCard.css
+++ b/drohnenfuehrer/frontend/src/components/users/UserCard.css
@@ -25,7 +25,7 @@
border-bottom: 1px solid var(--color-border);
}
-.user-name-row {
+.user-card-admin .user-name-row {
display: flex;
align-items: center;
gap: 0.5rem;
@@ -39,10 +39,10 @@
box-shadow: 0 0 4px rgba(0,0,0,0.2);
}
-.dot-green { background: #22c55e; }
-.dot-red { background: #ef4444; }
+.dot-green { background: var(--color-success); }
+.dot-red { background: var(--color-danger); }
-.user-name {
+.user-card-admin .user-name {
margin: 0;
color: var(--color-text);
font-size: 1.2rem;
@@ -67,40 +67,40 @@
font-weight: 600;
}
-.label-green { color: #16a34a; }
-.label-red { color: var(--color-danger); }
+.label-green { color: var(--color-success); }
+.label-red { color: var(--color-danger); }
-.user-info {
+.user-card-admin .user-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
-.user-address {
+.user-card-admin .user-address {
margin: 0;
color: var(--color-text-muted);
font-size: 0.9rem;
}
-.type-badge {
+.user-card-admin .type-badge {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border-radius: var(--radius-pill);
font-size: 0.85rem;
font-weight: 500;
}
-.user-phone {
+.user-card-admin .user-phone {
color: var(--color-primary);
text-decoration: none;
font-weight: 500;
font-size: 1rem;
}
-.user-phone:hover {
+.user-card-admin .user-phone:hover {
text-decoration: underline;
}
@@ -183,7 +183,7 @@
.edit-gps-button {
padding: 0.25rem 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -229,7 +229,7 @@
.save-gps-button {
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
}
.save-gps-button:hover:not(:disabled) {
@@ -243,7 +243,7 @@
.cancel-gps-button {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.cancel-gps-button:hover {
@@ -272,7 +272,7 @@
.edit-button {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.edit-button:hover {
@@ -281,7 +281,7 @@
.delete-button {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.delete-button:hover {
@@ -289,17 +289,17 @@
}
@media (max-width: 768px) {
- .user-header {
+.user-header {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}
- .gps-inputs {
+.gps-inputs {
flex-direction: column;
}
- .card-actions {
+.card-actions {
flex-direction: column;
}
}
@@ -322,7 +322,7 @@
display: block;
margin-top: 0.35rem;
padding: 0.4rem 0.5rem;
- background: var(--color-bg-muted, #f2f2ec);
+ background: var(--color-surface-alt);
border: 1px solid var(--color-border);
border-radius: 2px;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
diff --git a/drohnenfuehrer/frontend/src/components/users/UserForm.css b/drohnenfuehrer/frontend/src/components/users/UserForm.css
index 474c2a3..e3e62df 100644
--- a/drohnenfuehrer/frontend/src/components/users/UserForm.css
+++ b/drohnenfuehrer/frontend/src/components/users/UserForm.css
@@ -91,7 +91,7 @@
top: 100%;
left: 0;
right: 0;
- background: white;
+ background: var(--color-surface);
border: 1px solid var(--color-border-strong);
border-top: none;
border-radius: 0 0 var(--radius-sm) var(--radius-sm);
@@ -163,7 +163,7 @@
.btn-primary {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.btn-primary:hover {
@@ -172,7 +172,7 @@
.btn-secondary {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.btn-secondary:hover {
diff --git a/drohnenfuehrer/frontend/src/components/users/UserList.css b/drohnenfuehrer/frontend/src/components/users/UserList.css
index 4dd50f4..03ceb1a 100644
--- a/drohnenfuehrer/frontend/src/components/users/UserList.css
+++ b/drohnenfuehrer/frontend/src/components/users/UserList.css
@@ -34,7 +34,7 @@
.create-button {
padding: 0.5rem 1rem;
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
diff --git a/drohnenfuehrer/frontend/src/index.css b/drohnenfuehrer/frontend/src/index.css
index ec2585e..a76866f 100644
--- a/drohnenfuehrer/frontend/src/index.css
+++ b/drohnenfuehrer/frontend/src/index.css
@@ -1,13 +1,8 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
+/* Basisstile stehen in App.css, wo auch die Design-Tokens definiert sind.
+ Hier stand vorher eine zweite body-Regel, die von App.css vollständig
+ überschrieben wurde. */
+html {
+ /* Verhindert, dass iOS beim Drehen die Schrift eigenmächtig vergrößert. */
+ -webkit-text-size-adjust: 100%;
+ text-size-adjust: 100%;
}
diff --git a/nachsuche/frontend/index.html b/nachsuche/frontend/index.html
index 4920ad1..ff0013d 100644
--- a/nachsuche/frontend/index.html
+++ b/nachsuche/frontend/index.html
@@ -5,7 +5,7 @@
-
+
diff --git a/nachsuche/frontend/public/logo-fallingbostel.png b/nachsuche/frontend/public/logo-fallingbostel.png
deleted file mode 100644
index bf3e426..0000000
Binary files a/nachsuche/frontend/public/logo-fallingbostel.png and /dev/null differ
diff --git a/nachsuche/frontend/public/logo-ljn.png b/nachsuche/frontend/public/logo-ljn.png
deleted file mode 100644
index a1a6ce9..0000000
Binary files a/nachsuche/frontend/public/logo-ljn.png and /dev/null differ
diff --git a/nachsuche/frontend/public/manifest.json b/nachsuche/frontend/public/manifest.json
index 310f74e..2ab89a8 100644
--- a/nachsuche/frontend/public/manifest.json
+++ b/nachsuche/frontend/public/manifest.json
@@ -19,7 +19,7 @@
"scope": "/nachsuche/",
"display": "standalone",
"orientation": "portrait",
- "theme_color": "#2d6a2d",
- "background_color": "#ffffff",
+ "theme_color": "#1a3d1a",
+ "background_color": "#e8e8e2",
"description": "Nachsuchenstation Heidekreis – Übersicht der Nachsuchenführer"
}
diff --git a/nachsuche/frontend/public/offline.html b/nachsuche/frontend/public/offline.html
index 13728bd..b1c4d55 100644
--- a/nachsuche/frontend/public/offline.html
+++ b/nachsuche/frontend/public/offline.html
@@ -1,16 +1,93 @@
-
+
-
-
- Offline - Nachsuchenführer
-
+
+
+
+ Offline – Jagd Apps Heidekreis
+
- Du bist offline
- Die App ist derzeit nicht verfügbar. Bitte überprüfe deine Internetverbindung.
+
+
📡
+
Keine Verbindung
+
+ Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
+ Sobald wieder Empfang besteht, lädt die Seite normal.
+
+
+
-
\ No newline at end of file
+
diff --git a/nachsuche/frontend/src/App.css b/nachsuche/frontend/src/App.css
index b8f3ffe..b3a77b8 100644
--- a/nachsuche/frontend/src/App.css
+++ b/nachsuche/frontend/src/App.css
@@ -2,43 +2,203 @@
box-sizing: border-box;
}
+/* ──────────────────────────────────────────────────────────────────────────
+ Design-Tokens — einzige Farbquelle der App.
+ Palette und Formensprache folgen dem Portal (portal/index.html), damit der
+ Wechsel vom Portal in eine App nicht wie ein Produktwechsel wirkt.
+ Schriftmodell wie im Portal: Serif für die Marken-/Überschriftenebene,
+ Sans für funktionale UI-Texte (auf kleinen Displays besser lesbar).
+
+ Alle Textpaare erfüllen WCAG AA (>= 4.5:1), funktionale Rahmen >= 3.0:1 —
+ in beiden Varianten nachgerechnet.
+ ────────────────────────────────────────────────────────────────────────── */
:root {
- --color-primary: #2e8b2e;
- --color-primary-dark: #1e6b1e;
- --color-primary-accent: #8B0D12;
- --color-secondary: #6c757d;
- --color-secondary-dark: #5a6268;
- --color-success: #28a745;
- --color-success-dark: #218838;
- --color-danger: #dc3545;
- --color-danger-dark: #c82333;
- --color-bg: #f5f5f0;
- --color-surface: #ffffff;
+ --font-display: Georgia, 'Times New Roman', serif;
+ --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-mono: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
+
+ /* Flächen */
+ --color-bg: #e8e8e2;
+ --color-surface: #f4f4ee;
+ --color-surface-alt: #dedcd2;
+ --color-muted-bg: #dedcd2;
+
+ /* Text */
--color-text: #1a1a1a;
- --color-text-muted: #555;
- --color-border: #b8d4b8;
- --color-border-strong: #88b888;
- --color-focus: rgba(46, 139, 46, 0.2);
- --color-muted-bg: #f5f5f0;
- --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.1);
- --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.2);
- --radius-sm: 4px;
- --radius-md: 8px;
- --radius-pill: 12px;
+ --color-text-muted: #55554c;
+
+ /* Rahmen: -border ist dekorativ (Trennlinien, Karten),
+ -border-strong begrenzt Bedienelemente und erfüllt die 3:1-Anforderung. */
+ --color-border: #c9c9b8;
+ --color-border-strong: #7d7d68;
+
+ /* Aktionsfarben – jeweils mit der zugehörigen Textfarbe, damit die
+ Dunkelvariante nicht auf weißem Text auf hellem Grund landet. */
+ --color-primary: #2d5a2d;
+ --color-primary-dark: #1a3d1a;
+ --color-on-primary: #ffffff;
+ --color-secondary: #5c5c50;
+ --color-secondary-dark: #46463c;
+ --color-on-secondary: #ffffff;
+ --color-success: #1f6b34;
+ --color-success-dark: #175128;
+ --color-on-success: #ffffff;
+ --color-danger: #a32020;
+ --color-danger-dark: #821919;
+ --color-on-danger: #ffffff;
+ --color-warning: #7a5200;
+ --color-on-warning: #ffffff;
+ --color-accent: #8b0d12;
+ --color-on-accent: #ffffff;
+ /* Altname, wird von RulesDisplay noch benutzt */
+ --color-primary-accent: #8b0d12;
+
+ /* Getönte Status-Flächen (Meldungen, Badges, Zustands-Karten).
+ Der Block wird durch seine Füllung erkannt, der Rahmen ist Zierde. */
+ --color-success-bg: #dfeedd;
+ --color-success-border: #a9cba4;
+ --color-success-text: #1a4a24;
+ --color-danger-bg: #f6e0e0;
+ --color-danger-border: #d9a9a9;
+ --color-danger-text: #7d1a1a;
+ --color-warning-bg: #f7edd4;
+ --color-warning-border: #d9c48a;
+ --color-warning-text: #5c3d00;
+ --color-info: #24608f;
+ --color-info-dark: #1b4a6e;
+ --color-on-info: #ffffff;
+ --color-info-bg: #dde8f1;
+ --color-info-border: #a5bfd4;
+ --color-info-text: #14405f;
+
+ /* Als RGB-Tripel fuer rgba()-Anwendungen (Puls-Animation im Admin-Panel) */
+ --color-primary-rgb: 45, 90, 45;
+
+ --color-focus: rgba(45, 90, 45, 0.35);
+
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.15);
+ --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.2);
+
+ /* Kantige Ecken wie im Portal */
+ --radius-sm: 2px;
+ --radius-md: 2px;
+ --radius-pill: 2px;
+
--space-1: 0.5rem;
--space-2: 1rem;
--space-3: 1.5rem;
--space-4: 2rem;
+
+ /* Mindestgröße für Bedienelemente auf Touchgeräten */
+ --touch-target: 44px;
}
+/* Nachtvariante. Nachsuchen laufen in der Dämmerung und nachts — ein weißes
+ Vollbild blendet dann und kostet die Dunkeladaption der Augen. Warme, sehr
+ dunkle Grüntöne statt reinem Schwarz. */
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-bg: #14180f;
+ --color-surface: #1e241a;
+ --color-surface-alt: #2a3124;
+ --color-muted-bg: #2a3124;
+
+ --color-text: #e9e7dd;
+ --color-text-muted: #a6a698;
+
+ --color-border: #333b28;
+ --color-border-strong: #758566;
+
+ --color-primary: #7fb36f;
+ --color-primary-dark: #9ccb8c;
+ --color-on-primary: #10140c;
+ --color-secondary: #8d8d80;
+ --color-secondary-dark: #a3a396;
+ --color-on-secondary: #10140c;
+ --color-success: #79c48c;
+ --color-success-dark: #93d3a3;
+ --color-on-success: #10140c;
+ --color-danger: #ea8b8b;
+ --color-danger-dark: #f2a5a5;
+ --color-on-danger: #10140c;
+ --color-warning: #d6b25f;
+ --color-on-warning: #10140c;
+ --color-accent: #e88a8f;
+ --color-on-accent: #10140c;
+ --color-primary-accent: #e88a8f;
+
+ --color-success-bg: #1d2c20;
+ --color-success-border: #3d5c43;
+ --color-success-text: #93d3a3;
+ --color-danger-bg: #33201f;
+ --color-danger-border: #6b4040;
+ --color-danger-text: #f2a5a5;
+ --color-warning-bg: #322a15;
+ --color-warning-border: #63552c;
+ --color-warning-text: #e0c37c;
+ --color-info: #7fb0dc;
+ --color-info-dark: #9cc4e8;
+ --color-on-info: #10140c;
+ --color-info-bg: #1a2530;
+ --color-info-border: #3d5468;
+ --color-info-text: #9cc4e8;
+
+ --color-primary-rgb: 127, 179, 111;
+ --color-focus: rgba(127, 179, 111, 0.45);
+
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
+ --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.6);
+ }
+}
+
+body {
+ margin: 0;
+ font-family: var(--font-ui);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background: var(--color-bg);
+ color: var(--color-text);
+ /* Damit auch vom Browser gestellte Bedienelemente (Bildlaufleisten,
+ Datumsauswahl, Autofill) der gewählten Ansicht folgen. */
+ color-scheme: light dark;
+}
+
+/* Formularfelder brauchen ausdrücklich Farben: ohne sie nimmt der Browser
+ seinen Standard (weiß) — in der Nachtansicht leuchtet dann jedes Eingabefeld. */
+input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='file']),
+select,
+textarea {
+ background: var(--color-surface);
+ color: var(--color-text);
+}
+
+input::placeholder,
+textarea::placeholder {
+ color: var(--color-text-muted);
+ opacity: 1;
+}
+
+h1, h2, h3 {
+ font-family: var(--font-display);
+}
+
+code {
+ font-family: var(--font-mono);
+}
+
+/* ── Bedienelemente ─────────────────────────────────────────────────────── */
+
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-1);
+ min-height: var(--touch-target);
padding: 0.5rem 1rem;
border: none;
border-radius: var(--radius-sm);
+ font-family: var(--font-ui);
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
@@ -46,15 +206,24 @@
}
.btn:disabled {
- background: var(--color-border);
+ background: var(--color-surface-alt);
color: var(--color-text-muted);
cursor: not-allowed;
box-shadow: none;
}
+/* Sichtbarer Tastaturfokus. Ohne das war die Tastaturbedienung unsichtbar —
+ Buttons hatten nur einen :hover-Stil. */
+.btn:focus-visible,
+.nav-button:focus-visible,
+a:focus-visible {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
+
.btn-primary {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.btn-primary:hover:not(:disabled) {
@@ -64,7 +233,7 @@
.btn-secondary {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.btn-secondary:hover:not(:disabled) {
@@ -72,19 +241,9 @@
transform: translateY(-1px);
}
-.btn-success {
- background: var(--color-success);
- color: white;
-}
-
-.btn-success:hover:not(:disabled) {
- background: var(--color-success-dark);
- transform: translateY(-1px);
-}
-
.btn-danger {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.btn-danger:hover:not(:disabled) {
@@ -96,9 +255,13 @@
.select,
.textarea {
width: 100%;
+ min-height: var(--touch-target);
padding: 0.75rem 1rem;
+ background: var(--color-surface);
+ color: var(--color-text);
border: 1px solid var(--color-border-strong);
border-radius: var(--radius-sm);
+ font-family: var(--font-ui);
font-size: 1rem;
box-sizing: border-box;
}
@@ -111,33 +274,19 @@
box-shadow: 0 0 0 3px var(--color-focus);
}
-.panel {
- background: var(--color-surface);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- padding: var(--space-3);
- box-shadow: var(--shadow-sm);
-}
-
.panel-title {
margin: 0 0 var(--space-2);
+ font-family: var(--font-display);
font-size: 1.1rem;
color: var(--color-text);
}
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- background: var(--color-bg);
- color: var(--color-text);
-}
+/* ── Grundgerüst ────────────────────────────────────────────────────────── */
.App {
- min-height: 100vh;
+ /* dvh statt vh: mit ein- und ausblendender Adressleiste auf Mobilgeräten
+ entsteht mit vh sonst Überlauf. */
+ min-height: 100dvh;
display: flex;
flex-direction: column;
}
@@ -151,44 +300,26 @@ body {
display: flex;
justify-content: center;
align-items: center;
- min-height: 100vh;
+ min-height: 100dvh;
font-size: 1.2rem;
color: var(--color-text-muted);
}
-.login-prompt {
- position: fixed;
- bottom: 20px;
- right: 20px;
-}
-
-.login-button-header {
- padding: 0.75rem 1.5rem;
- background: var(--color-primary);
- color: white;
- border: none;
- border-radius: 4px;
- font-size: 1rem;
- font-weight: 600;
- cursor: pointer;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- transition: all 0.2s;
-}
-
-.login-button-header:hover {
- background: var(--color-primary-dark);
- transform: translateY(-2px);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
-}
-
-@media (max-width: 768px) {
- .login-prompt {
- bottom: 10px;
- right: 10px;
+/* Wer Bewegung reduziert haben möchte, bekommt keine Animationen. */
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
}
- .login-button-header {
- padding: 0.6rem 1.2rem;
- font-size: 0.9rem;
+ .btn:hover:not(:disabled),
+ .btn-primary:hover:not(:disabled),
+ .btn-secondary:hover:not(:disabled),
+ .btn-danger:hover:not(:disabled) {
+ transform: none;
}
}
diff --git a/nachsuche/frontend/src/components/admin/AdminPanel.css b/nachsuche/frontend/src/components/admin/AdminPanel.css
index 12ce644..16e6fa0 100644
--- a/nachsuche/frontend/src/components/admin/AdminPanel.css
+++ b/nachsuche/frontend/src/components/admin/AdminPanel.css
@@ -25,7 +25,7 @@
.tab-button.active {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.settings-panel {
@@ -59,9 +59,9 @@
.unsaved-badge {
display: inline-block;
- background: #fff3cd;
- color: #856404;
- border: 1px solid #ffc107;
+ background: var(--color-warning-bg);
+ color: var(--color-warning-text);
+ border: 1px solid var(--color-warning);
border-radius: var(--radius-sm);
padding: 0.2rem 0.6rem;
font-size: 0.8rem;
@@ -102,7 +102,7 @@
display: flex;
align-items: center;
gap: 0.5rem;
- background: var(--color-muted-bg, #f5f5f0);
+ background: var(--color-muted-bg, var(--color-surface-alt));
border: none;
padding: 0.75rem var(--space-2);
cursor: pointer;
@@ -111,7 +111,7 @@
}
.settings-section-header:hover {
- background: var(--color-focus, #eef2e6);
+ background: var(--color-focus, var(--color-success-bg));
}
.settings-section-header .settings-heading {
@@ -193,7 +193,7 @@
.skeleton-line {
height: 1rem;
border-radius: var(--radius-sm);
- background: linear-gradient(90deg, #e8e8e4 25%, #f0f0ec 50%, #e8e8e4 75%);
+ background: linear-gradient(90deg, var(--color-surface-alt) 25%, var(--color-surface-alt) 50%, var(--color-surface-alt) 75%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.4s infinite;
margin-bottom: 0.75rem;
@@ -323,17 +323,17 @@
.notification.success {
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
}
.notification.error {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.notification.warning {
- background: #e67e00;
- color: white;
+ background: var(--color-warning);
+ color: var(--color-on-warning);
}
@keyframes slideIn {
diff --git a/nachsuche/frontend/src/components/admin/AuditLogs.css b/nachsuche/frontend/src/components/admin/AuditLogs.css
index 433cfc4..0f2d27a 100644
--- a/nachsuche/frontend/src/components/admin/AuditLogs.css
+++ b/nachsuche/frontend/src/components/admin/AuditLogs.css
@@ -13,8 +13,8 @@
gap: 12px;
flex-wrap: wrap;
}
-.audit-header h2 { margin: 0 0 4px 0; color: #333; font-size: 26px; }
-.audit-description { margin: 0; color: #666; font-size: 13px; }
+.audit-header h2 { margin: 0 0 4px 0; color: var(--color-text); font-size: 26px; }
+.audit-description { margin: 0; color: var(--color-text-muted); font-size: 13px; }
.audit-header-actions {
display: flex;
@@ -32,24 +32,24 @@
}
.btn-stats-toggle {
padding: 6px 14px;
- background: #f0f4f8;
- border: 1px solid #d0d7de;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
font-size: 13px;
- color: #444;
+ color: var(--color-text-muted);
}
-.btn-stats-toggle:hover { background: #e2e8f0; }
+.btn-stats-toggle:hover { background: var(--color-surface-alt); }
.stats-days-select { font-size: 13px; }
.audit-stats {
- background: #f8fafc;
- border: 1px solid #e2e8f0;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
border-radius: 10px;
padding: 16px;
margin-bottom: 16px;
}
-.stats-loading { color: #888; font-size: 13px; padding: 8px 0; }
+.stats-loading { color: var(--color-text-muted); font-size: 13px; padding: 8px 0; }
.stats-row {
display: flex;
@@ -60,18 +60,18 @@
.stat-card {
flex: 1;
min-width: 100px;
- background: white;
+ background: var(--color-surface);
border-radius: 8px;
padding: 12px 16px;
text-align: center;
- border: 1px solid #e2e8f0;
+ border: 1px solid var(--color-border);
}
.stat-number { font-size: 28px; font-weight: 700; line-height: 1; }
-.stat-label { font-size: 11px; color: #666; margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
-.stat-total .stat-number { color: #1976d2; }
-.stat-failed .stat-number { color: #c62828; }
-.stat-success .stat-number { color: #2e7d32; }
-.stat-period .stat-number { color: #555; font-size: 20px; }
+.stat-label { font-size: 11px; color: var(--color-text-muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
+.stat-total .stat-number { color: var(--color-info-text); }
+.stat-failed .stat-number { color: var(--color-danger-text); }
+.stat-success .stat-number { color: var(--color-success-text); }
+.stat-period .stat-number { color: var(--color-text-muted); font-size: 20px; }
.stats-details {
display: flex;
@@ -79,7 +79,7 @@
flex-wrap: wrap;
}
.stats-col { flex: 1; min-width: 180px; }
-.stats-col h4 { margin: 0 0 8px 0; font-size: 12px; text-transform: uppercase; color: #888; letter-spacing: 0.5px; }
+.stats-col h4 { margin: 0 0 8px 0; font-size: 12px; text-transform: uppercase; color: var(--color-text-muted); letter-spacing: 0.5px; }
.stat-bar-row {
display: flex;
@@ -88,8 +88,8 @@
gap: 8px;
margin-bottom: 5px;
}
-.stat-bar-label { font-size: 13px; color: #444; }
-.stat-bar-count { font-size: 13px; font-weight: 600; color: #333; flex-shrink: 0; }
+.stat-bar-label { font-size: 13px; color: var(--color-text-muted); }
+.stat-bar-count { font-size: 13px; font-weight: 600; color: var(--color-text); flex-shrink: 0; }
/* Mini bar chart */
.stats-chart-col { flex: 2; min-width: 220px; }
@@ -98,7 +98,7 @@
align-items: flex-end;
gap: 3px;
height: 80px;
- background: #f0f4f8;
+ background: var(--color-surface-alt);
border-radius: 6px;
padding: 6px 6px 0;
}
@@ -110,7 +110,7 @@
}
.chart-bar {
width: 100%;
- background: #1976d2;
+ background: var(--color-info);
border-radius: 2px 2px 0 0;
position: relative;
min-height: 4px;
@@ -121,7 +121,7 @@
bottom: 0;
left: 0;
width: 100%;
- background: #e53935;
+ background: var(--color-danger);
}
/* ── Filters ─────────────────────────────────────────────────────── */
@@ -134,52 +134,52 @@
}
.filter-select {
padding: 8px 12px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
font-size: 13px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
}
-.filter-select:focus { outline: none; border-color: #1976d2; }
+.filter-select:focus { outline: none; border-color: var(--color-primary); }
.filter-input {
padding: 8px 12px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
font-size: 13px;
- background: white;
+ background: var(--color-surface);
min-width: 140px;
}
-.filter-input:focus { outline: none; border-color: #1976d2; }
+.filter-input:focus { outline: none; border-color: var(--color-primary); }
.filter-date { min-width: 130px; }
.btn-refresh {
padding: 8px 14px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
}
-.btn-refresh:hover:not(:disabled) { background: #1565c0; }
-.btn-refresh:disabled { background: #bdbdbd; cursor: not-allowed; }
+.btn-refresh:hover:not(:disabled) { background: var(--color-info-dark); }
+.btn-refresh:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); cursor: not-allowed; }
.btn-reset {
padding: 8px 12px;
- background: white;
- color: #666;
- border: 1.5px solid #d0d7de;
+ background: var(--color-surface);
+ color: var(--color-text-muted);
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
font-size: 13px;
}
-.btn-reset:hover { background: #f5f5f5; }
+.btn-reset:hover { background: var(--color-surface-alt); }
.btn-export {
padding: 8px 16px;
- background: #2e7d32;
- color: white;
+ background: var(--color-success);
+ color: var(--color-on-success);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -187,15 +187,15 @@
font-weight: 500;
white-space: nowrap;
}
-.btn-export:hover:not(:disabled) { background: #1b5e20; }
-.btn-export:disabled { background: #bdbdbd; cursor: not-allowed; }
+.btn-export:hover:not(:disabled) { background: var(--color-success-dark); }
+.btn-export:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); cursor: not-allowed; }
.auto-refresh-toggle {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
- color: #555;
+ color: var(--color-text-muted);
cursor: pointer;
white-space: nowrap;
}
@@ -206,7 +206,7 @@
justify-content: space-between;
align-items: center;
font-size: 13px;
- color: #666;
+ color: var(--color-text-muted);
margin-bottom: 10px;
}
.limit-select { padding: 4px 8px; font-size: 13px; }
@@ -224,16 +224,16 @@
}
.badge-create { background: #e8f5e9; color: #2e7d32; }
.badge-update { background: #e3f2fd; color: #1565c0; }
-.badge-delete { background: #ffebee; color: #c62828; }
-.badge-restore { background: #fff3e0; color: #e65100; }
+.badge-delete { background: #ffebee; color: var(--color-danger-text); }
+.badge-restore { background: #fff3e0; color: #a83a00; }
.badge-login { background: #f3e5f5; color: #6a1b9a; }
.badge-logout { background: #fce4ec; color: #880e4f; }
.badge-login-failed { background: #ffcdd2; color: #b71c1c; font-weight: 700; }
.badge-import { background: #e0f7fa; color: #00695c; }
.badge-export { background: #e8f5e9; color: #1b5e20; }
-.badge-bulk-update { background: #e8eaf6; color: #283593; }
+.badge-bulk-update { background: var(--color-surface-alt); color: #283593; }
.badge-bulk-delete { background: #fbe9e7; color: #bf360c; }
-.badge-password { background: #fff8e1; color: #f57f17; }
+.badge-password { background: #fff8e1; color: #9c4e00; }
.badge-default { background: #f5f5f5; color: #616161; }
.status-code {
@@ -244,16 +244,16 @@
font-family: monospace;
}
.status-ok { background: #e8f5e9; color: #2e7d32; }
-.status-redirect { background: #fff3e0; color: #e65100; }
-.status-error { background: #ffebee; color: #c62828; }
+.status-redirect { background: #fff3e0; color: #a83a00; }
+.status-error { background: #ffebee; color: var(--color-danger-text); }
.status-server-error { background: #f3e5f5; color: #6a1b9a; }
.duration-badge {
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
- background: #f5f5f5;
- color: #777;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
font-family: monospace;
}
@@ -261,24 +261,24 @@
.audit-empty {
text-align: center;
padding: 40px;
- background: #f9f9f9;
+ background: var(--color-surface-alt);
border-radius: 8px;
- color: #888;
+ color: var(--color-text-muted);
}
.audit-error { text-align: center; padding: 20px; }
-.audit-error p { color: #d32f2f; margin: 0; }
+.audit-error p { color: var(--color-danger-text); margin: 0; }
.audit-list { display: flex; flex-direction: column; gap: 8px; }
.audit-item {
- background: white;
- border: 1px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
overflow: hidden;
transition: box-shadow 0.15s;
}
.audit-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
-.audit-item-failed { border-left: 4px solid #e53935; }
+.audit-item-failed { border-left: 4px solid var(--color-danger); }
.audit-item-header {
display: flex;
@@ -286,18 +286,18 @@
gap: 8px;
padding: 10px 14px;
flex-wrap: wrap;
- background: #fafafa;
- border-bottom: 1px solid #f0f0f0;
+ background: var(--color-surface-alt);
+ border-bottom: 1px solid var(--color-border);
}
-.audit-time { margin-left: auto; color: #999; font-size: 12px; white-space: nowrap; }
-.expand-toggle { color: #aaa; font-size: 11px; cursor: pointer; padding: 0 4px; }
+.audit-time { margin-left: auto; color: var(--color-text-muted); font-size: 12px; white-space: nowrap; }
+.expand-toggle { color: var(--color-text-muted); font-size: 11px; cursor: pointer; padding: 0 4px; }
.audit-resource {
padding: 3px 8px;
- background: #f0f0f0;
+ background: var(--color-surface-alt);
border-radius: 4px;
font-size: 12px;
- color: #555;
+ color: var(--color-text-muted);
}
.audit-item-body {
@@ -308,16 +308,16 @@
font-size: 13px;
align-items: center;
}
-.audit-admin { color: #333; }
-.audit-resource-name { color: #555; }
-.audit-ip { color: #999; font-family: monospace; font-size: 12px; }
-.audit-failed-badge { color: #c62828; font-weight: 600; font-size: 12px; }
+.audit-admin { color: var(--color-text); }
+.audit-resource-name { color: var(--color-text-muted); }
+.audit-ip { color: var(--color-text-muted); font-family: monospace; font-size: 12px; }
+.audit-failed-badge { color: var(--color-danger-text); font-weight: 600; font-size: 12px; }
/* ── Expanded detail ─────────────────────────────────────────────── */
.audit-item-detail {
padding: 10px 14px 14px;
- border-top: 1px dashed #e0e0e0;
- background: #fefefe;
+ border-top: 1px dashed var(--color-border);
+ background: var(--color-surface);
display: flex;
flex-direction: column;
gap: 8px;
@@ -330,7 +330,7 @@
}
.detail-label {
font-weight: 600;
- color: #888;
+ color: var(--color-text-muted);
font-size: 11px;
text-transform: uppercase;
min-width: 70px;
@@ -338,23 +338,23 @@
}
.detail-row code {
font-family: monospace;
- background: #f0f0f0;
+ background: var(--color-surface-alt);
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
}
.detail-ua-full {
- color: #aaa;
+ color: var(--color-text-muted);
cursor: help;
font-size: 12px;
}
-.detail-error { color: #c62828; }
-.detail-error .detail-label { color: #c62828; }
+.detail-error { color: var(--color-danger-text); }
+.detail-error .detail-label { color: var(--color-danger-text); }
.meta-tag {
display: inline-block;
- background: #e8eaf6;
- color: #283593;
+ background: var(--color-surface-alt);
+ color: var(--color-info-text);
border-radius: 4px;
padding: 2px 8px;
font-size: 12px;
@@ -370,17 +370,17 @@
margin-top: 6px;
}
.diff-table th {
- background: #f0f0f0;
+ background: var(--color-surface-alt);
padding: 5px 10px;
text-align: left;
font-size: 11px;
text-transform: uppercase;
- color: #666;
- border: 1px solid #e0e0e0;
+ color: var(--color-text-muted);
+ border: 1px solid var(--color-border);
}
-.diff-table td { padding: 5px 10px; border: 1px solid #e8e8e8; vertical-align: top; }
-.diff-field { font-weight: 600; color: #444; font-family: monospace; white-space: nowrap; background: #fafafa; }
-.diff-before { color: #c62828; background: #fff5f5; font-family: monospace; word-break: break-all; }
+.diff-table td { padding: 5px 10px; border: 1px solid var(--color-border); vertical-align: top; }
+.diff-field { font-weight: 600; color: var(--color-text-muted); font-family: monospace; white-space: nowrap; background: var(--color-surface-alt); }
+.diff-before { color: var(--color-danger-text); background: #fff5f5; font-family: monospace; word-break: break-all; }
.diff-after { color: #2e7d32; background: #f5fff5; font-family: monospace; word-break: break-all; }
/* ── Pagination ──────────────────────────────────────────────────── */
@@ -393,16 +393,16 @@
}
.btn-page {
padding: 7px 14px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
font-size: 13px;
- color: #333;
+ color: var(--color-text);
}
-.btn-page:hover:not(:disabled) { background: #f0f4f8; border-color: #1976d2; }
-.btn-page:disabled { color: #bbb; cursor: not-allowed; border-color: #eee; }
-.page-info { font-size: 13px; color: #666; padding: 0 8px; }
+.btn-page:hover:not(:disabled) { background: var(--color-surface-alt); border-color: var(--color-primary); }
+.btn-page:disabled { color: var(--color-text-muted); cursor: not-allowed; border-color: var(--color-border); }
+.page-info { font-size: 13px; color: var(--color-text-muted); padding: 0 8px; }
.audit-header {
@@ -411,13 +411,13 @@
.audit-header h2 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
}
.audit-description {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -428,7 +428,7 @@
}
.audit-error p {
- color: #d32f2f;
+ color: var(--color-danger-text);
margin: 0;
}
@@ -441,23 +441,23 @@
.filter-select {
padding: 10px 14px;
- border: 2px solid #e0e0e0;
+ border: 2px solid var(--color-border);
border-radius: 6px;
font-size: 14px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
transition: border-color 0.2s;
}
.filter-select:focus {
outline: none;
- border-color: #1976d2;
+ border-color: var(--color-primary);
}
.btn-refresh {
padding: 10px 16px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -467,20 +467,21 @@
}
.btn-refresh:hover:not(:disabled) {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.btn-refresh:disabled {
- background: #bdbdbd;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
cursor: not-allowed;
}
.audit-empty {
text-align: center;
padding: 40px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 8px;
- color: #666;
+ color: var(--color-text-muted);
}
.audit-list {
@@ -490,8 +491,8 @@
}
.audit-item {
- background: white;
- border: 1px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 16px;
transition: box-shadow 0.2s;
@@ -519,58 +520,18 @@
gap: 4px;
}
-.badge-create {
- background: #e8f5e9;
- color: #2e7d32;
-}
-
-.badge-update {
- background: #e3f2fd;
- color: #1565c0;
-}
-
-.badge-delete {
- background: #ffebee;
- color: #c62828;
-}
-
-.badge-restore {
- background: #fff3e0;
- color: #e65100;
-}
-
-.badge-login {
- background: #f3e5f5;
- color: #6a1b9a;
-}
-
-.badge-logout {
- background: #fce4ec;
- color: #880e4f;
-}
-
-.badge-login-failed {
- background: #ffcdd2;
- color: #b71c1c;
- font-weight: 700;
-}
-
-.badge-default {
- background: #f5f5f5;
- color: #616161;
-}
.audit-resource {
padding: 4px 10px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 4px;
font-size: 13px;
- color: #666;
+ color: var(--color-text-muted);
}
.audit-time {
margin-left: auto;
- color: #999;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -582,23 +543,19 @@
}
.audit-admin {
- color: #333;
+ color: var(--color-text);
}
.audit-resource-name {
- color: #666;
+ color: var(--color-text-muted);
}
.audit-ip {
- color: #888;
+ color: var(--color-text-muted);
font-family: monospace;
font-size: 13px;
}
-.audit-error-message {
- color: #d32f2f;
- font-weight: 500;
-}
.audit-pagination {
display: flex;
@@ -607,15 +564,15 @@
gap: 16px;
margin-top: 24px;
padding: 16px;
- background: white;
+ background: var(--color-surface);
border-radius: 8px;
- border: 1px solid #e0e0e0;
+ border: 1px solid var(--color-border);
}
.btn-page {
padding: 8px 16px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -624,16 +581,17 @@
}
.btn-page:hover:not(:disabled) {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.btn-page:disabled {
- background: #bdbdbd;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
cursor: not-allowed;
}
.page-info {
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -656,3 +614,33 @@
width: 100%;
}
}
+
+/* ── Nachtvariante ───────────────────────────────────────────────────────
+ Die Badges kodieren die Aktionsart über den Farbton – der bleibt erhalten,
+ nur Helligkeit und Sättigung drehen sich um. Alle Paare >= 6.4:1. */
+@media (prefers-color-scheme: dark) {
+ .badge-create { background: #162d17; color: #97d99a; }
+ .badge-update { background: #16202d; color: #89b5e6; }
+ .badge-delete { background: #2d1616; color: #e68989; }
+ .badge-restore { background: #2d1e16; color: #e6aa89; }
+ .badge-login { background: #24162d; color: #c389e6; }
+ .badge-logout { background: #2d1622; color: #e689bb; }
+ .badge-login-failed { background: #2d1616; color: #e68989; }
+ .badge-import { background: #162d2a; color: #89e6db; }
+ .badge-export { background: #162d17; color: #90df96; }
+ .badge-bulk-update { background: #16182d; color: #8f99e0; }
+ .badge-bulk-delete { background: #2d1b16; color: #e69f89; }
+ .badge-password { background: #2d2016; color: #e6b589; }
+ .badge-default { background: var(--color-surface-alt); color: var(--color-text-muted); }
+
+ .status-ok { background: #162d17; color: #97d99a; }
+ .status-redirect { background: #2d1e16; color: #e6aa89; }
+ .status-error { background: #2d1616; color: #e68989; }
+ .status-server-error { background: #24162d; color: #c389e6; }
+
+ /* Diff-Tabelle: die roten/gruenen Vorher-Nachher-Felder */
+ .diff-table th { background: var(--color-surface-alt); }
+ .diff-before { color: #e68989; background: #2d1616; }
+ .diff-after { color: #97d99a; background: #162d17; }
+ .diff-field { background: var(--color-surface-alt); color: var(--color-text); }
+}
diff --git a/nachsuche/frontend/src/components/admin/ExportButton.css b/nachsuche/frontend/src/components/admin/ExportButton.css
index 83981da..c231346 100644
--- a/nachsuche/frontend/src/components/admin/ExportButton.css
+++ b/nachsuche/frontend/src/components/admin/ExportButton.css
@@ -14,7 +14,7 @@
.export-button {
padding: 0.5rem 1rem;
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -41,8 +41,8 @@
.import-button {
padding: 0.5rem 1rem;
- background: var(--color-primary, #2563eb);
- color: white;
+ background: var(--color-primary, var(--color-info));
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -52,7 +52,7 @@
}
.import-button:hover:not(:disabled) {
- background: var(--color-primary-dark, #1d4ed8);
+ background: var(--color-primary-dark, var(--color-info-dark));
}
.import-button:disabled {
@@ -65,7 +65,7 @@
align-items: center;
gap: 0.4rem;
font-size: 0.85rem;
- color: var(--color-text-muted, #6b7280);
+ color: var(--color-text-muted);
cursor: pointer;
white-space: nowrap;
}
diff --git a/nachsuche/frontend/src/components/admin/Trash.css b/nachsuche/frontend/src/components/admin/Trash.css
index 200c68a..e70ac72 100644
--- a/nachsuche/frontend/src/components/admin/Trash.css
+++ b/nachsuche/frontend/src/components/admin/Trash.css
@@ -10,13 +10,13 @@
.trash-header h2 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
}
.trash-description {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -27,14 +27,14 @@
}
.trash-error h3 {
- color: #d32f2f;
+ color: var(--color-danger-text);
margin-bottom: 12px;
}
.btn-retry {
padding: 10px 20px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -43,13 +43,13 @@
}
.btn-retry:hover {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.trash-empty {
text-align: center;
padding: 60px 20px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 12px;
}
@@ -60,7 +60,7 @@
}
.trash-empty p {
- color: #666;
+ color: var(--color-text-muted);
font-size: 16px;
margin: 0;
}
@@ -72,8 +72,8 @@
}
.trash-item {
- background: #fff;
- border: 2px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 2px solid var(--color-border);
border-radius: 8px;
padding: 16px 20px;
display: flex;
@@ -84,7 +84,7 @@
.trash-item:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- border-color: #bdbdbd;
+ border-color: var(--color-border);
}
.trash-item-info {
@@ -93,7 +93,7 @@
.trash-item-info h3 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 18px;
font-weight: 600;
}
@@ -106,8 +106,8 @@
}
.trash-item-type {
- background: #e3f2fd;
- color: #1976d2;
+ background: var(--color-info-bg);
+ color: var(--color-info-text);
padding: 4px 10px;
border-radius: 4px;
font-size: 13px;
@@ -116,12 +116,12 @@
.trash-item-address,
.trash-item-phone {
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
.trash-item-meta {
- color: #999;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -140,8 +140,8 @@
align-items: center;
gap: 6px;
padding: 10px 16px;
- background: #4caf50;
- color: white;
+ background: var(--color-success);
+ color: var(--color-on-success);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -151,7 +151,7 @@
}
.btn-restore:hover:not(:disabled) {
- background: #45a049;
+ background: var(--color-success-dark);
transform: translateY(-1px);
}
@@ -160,7 +160,7 @@
}
.btn-restore:disabled {
- background: #bdbdbd;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
diff --git a/nachsuche/frontend/src/components/auth/LoginForm.css b/nachsuche/frontend/src/components/auth/LoginForm.css
index 1a38755..56024ab 100644
--- a/nachsuche/frontend/src/components/auth/LoginForm.css
+++ b/nachsuche/frontend/src/components/auth/LoginForm.css
@@ -56,7 +56,7 @@
width: 100%;
padding: 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
font-size: 1rem;
@@ -76,8 +76,8 @@
.login-error {
padding: 0.75rem;
- background: #ffebee;
- border: 1px solid #ffcdd2;
+ background: var(--color-danger-bg);
+ border: 1px solid var(--color-danger-border);
border-radius: var(--radius-sm);
color: var(--color-danger);
margin-bottom: 1rem;
diff --git a/nachsuche/frontend/src/components/auth/PasswordReset.css b/nachsuche/frontend/src/components/auth/PasswordReset.css
index cd3c067..4ee08d1 100644
--- a/nachsuche/frontend/src/components/auth/PasswordReset.css
+++ b/nachsuche/frontend/src/components/auth/PasswordReset.css
@@ -1,5 +1,6 @@
.password-reset-container {
- min-height: 100vh;
+ /* dvh: mit ein- und ausblendender Adressleiste entsteht mit vh Überlauf. */
+ min-height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
@@ -8,7 +9,7 @@
}
.password-reset-card {
- background: white;
+ background: var(--color-surface);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
padding: 40px;
@@ -18,7 +19,7 @@
.password-reset-card h2 {
margin: 0 0 24px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
text-align: center;
}
@@ -32,15 +33,15 @@
}
.message.success {
- background-color: #d4edda;
- color: #155724;
- border: 1px solid #c3e6cb;
+ background-color: var(--color-success-bg);
+ color: var(--color-success-text);
+ border: 1px solid var(--color-success-border);
}
.message.error {
- background-color: #f8d7da;
- color: #721c24;
- border: 1px solid #f5c6cb;
+ background-color: var(--color-danger-bg);
+ color: var(--color-danger-text);
+ border: 1px solid var(--color-danger-border);
}
.form-group {
@@ -50,7 +51,7 @@
.form-group label {
display: block;
margin-bottom: 8px;
- color: #555;
+ color: var(--color-text-muted);
font-weight: 500;
font-size: 14px;
}
@@ -58,7 +59,7 @@
.form-group input {
width: 100%;
padding: 12px 16px;
- border: 2px solid #e0e0e0;
+ border: 2px solid var(--color-border);
border-radius: 8px;
font-size: 15px;
transition: border-color 0.3s;
@@ -71,14 +72,14 @@
}
.form-group input:disabled {
- background-color: #f5f5f5;
+ background-color: var(--color-surface-alt);
cursor: not-allowed;
}
.form-group small {
display: block;
margin-top: 6px;
- color: #888;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -86,7 +87,7 @@
width: 100%;
padding: 14px;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 8px;
font-size: 16px;
diff --git a/nachsuche/frontend/src/components/common/ErrorMessage.css b/nachsuche/frontend/src/components/common/ErrorMessage.css
index 38733d8..efba2ba 100644
--- a/nachsuche/frontend/src/components/common/ErrorMessage.css
+++ b/nachsuche/frontend/src/components/common/ErrorMessage.css
@@ -4,10 +4,10 @@
gap: 0.5rem;
padding: 1rem;
margin: 1rem 0;
- background-color: #fee;
- border: 1px solid #fcc;
+ background-color: var(--color-danger-bg);
+ border: 1px solid var(--color-danger-border);
border-radius: 4px;
- color: #c33;
+ color: var(--color-danger-text);
}
.error-icon {
@@ -22,7 +22,7 @@
background: none;
border: none;
font-size: 1.5rem;
- color: #c33;
+ color: var(--color-danger-text);
cursor: pointer;
padding: 0;
width: 24px;
@@ -34,5 +34,5 @@
}
.error-close:hover {
- color: #a22;
+ color: var(--color-danger-text);
}
diff --git a/nachsuche/frontend/src/components/common/Header.css b/nachsuche/frontend/src/components/common/Header.css
index 69a023f..dd3e83d 100644
--- a/nachsuche/frontend/src/components/common/Header.css
+++ b/nachsuche/frontend/src/components/common/Header.css
@@ -1,6 +1,6 @@
.app-header {
- background: #ffffff;
- border-bottom: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border-bottom: 1px solid var(--color-border);
padding: 0.75rem 2rem;
display: flex;
align-items: center;
@@ -27,7 +27,7 @@
.portal-back-link:hover {
background: var(--color-primary);
- color: #fff;
+ color: var(--color-on-primary);
}
.app-brand {
@@ -40,18 +40,18 @@
height: 52px;
width: auto;
object-fit: contain;
-}
-
-.app-logo-ljn {
- height: 44px;
+ flex-shrink: 0;
}
.app-title {
margin: 0;
+ font-family: var(--font-display);
font-size: 1.05rem;
font-weight: 700;
color: var(--color-text);
- white-space: nowrap;
+ /* Kein nowrap: lange App-Namen haben die Kopfzeile sonst über die
+ Bildschirmbreite hinaus geschoben. */
+ overflow-wrap: anywhere;
}
.app-nav {
@@ -61,11 +61,14 @@
}
.nav-button {
+ display: inline-flex;
+ align-items: center;
+ min-height: var(--touch-target);
padding: 0.5rem 0.875rem;
background: none;
border: none;
border-radius: var(--radius-sm);
- color: #333;
+ color: var(--color-text);
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
@@ -97,12 +100,19 @@
.app-header {
flex-direction: column;
align-items: flex-start;
- padding: 0.75rem 1rem;
- gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ gap: 0.4rem;
+ /* Auf schmalen Geräten nimmt die umgebrochene Kopfzeile viel Höhe ein.
+ Klebrig bleibt sie nur dort, wo genug Platz ist. */
+ position: static;
}
.app-title {
- font-size: 0.9rem;
+ font-size: 0.95rem;
+ }
+
+ .app-logo {
+ height: 36px;
}
.app-nav {
@@ -111,7 +121,31 @@
}
.nav-button {
- font-size: 0.85rem;
+ font-size: 0.9rem;
padding: 0.4rem 0.7rem;
}
}
+
+@media (max-width: 480px) {
+ .app-header {
+ padding: 0.5rem 0.75rem;
+ }
+
+ .app-brand {
+ gap: 0.5rem;
+ }
+
+ .app-logo {
+ height: 30px;
+ }
+
+ .app-nav {
+ width: 100%;
+ }
+
+ .nav-button {
+ flex: 1 1 45%;
+ justify-content: center;
+ padding: 0.4rem 0.5rem;
+ }
+}
diff --git a/nachsuche/frontend/src/components/common/InstallBanner.css b/nachsuche/frontend/src/components/common/InstallBanner.css
index f5b248d..0ab554a 100644
--- a/nachsuche/frontend/src/components/common/InstallBanner.css
+++ b/nachsuche/frontend/src/components/common/InstallBanner.css
@@ -2,8 +2,8 @@
position: sticky;
top: 0;
z-index: 1000;
- background-color: #2d6a2d;
- color: #fff;
+ background-color: var(--color-primary);
+ color: var(--color-on-primary);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
@@ -22,8 +22,8 @@
}
.install-banner__btn {
- background: #fff;
- color: #2d6a2d;
+ background: var(--color-surface);
+ color: var(--color-primary);
border: none;
border-radius: 4px;
padding: 0.35rem 0.85rem;
@@ -34,7 +34,7 @@
}
.install-banner__btn:hover {
- background: #e8f5e9;
+ background: var(--color-success-bg);
}
.install-banner__close {
@@ -49,7 +49,7 @@
}
.install-banner__close:hover {
- color: #fff;
+ color: var(--color-on-primary);
}
.install-banner__share-icon {
diff --git a/nachsuche/frontend/src/components/common/Loading.css b/nachsuche/frontend/src/components/common/Loading.css
index ec8df60..e1dbe74 100644
--- a/nachsuche/frontend/src/components/common/Loading.css
+++ b/nachsuche/frontend/src/components/common/Loading.css
@@ -8,8 +8,8 @@
}
.spinner {
- border: 4px solid #f3f3f3;
- border-top: 4px solid #3498db;
+ border: 4px solid var(--color-border);
+ border-top: 4px solid var(--color-primary);
border-radius: 50%;
width: 50px;
height: 50px;
@@ -23,6 +23,6 @@
.loading-message {
margin-top: 1rem;
- color: #666;
+ color: var(--color-text-muted);
font-size: 0.9rem;
}
diff --git a/nachsuche/frontend/src/components/handler/HandlerDashboard.css b/nachsuche/frontend/src/components/handler/HandlerDashboard.css
index 5078c48..7ebe76d 100644
--- a/nachsuche/frontend/src/components/handler/HandlerDashboard.css
+++ b/nachsuche/frontend/src/components/handler/HandlerDashboard.css
@@ -5,7 +5,7 @@
}
.handler-dashboard-card {
- background: white;
+ background: var(--color-surface);
border-radius: 10px;
padding: 2rem;
width: 100%;
@@ -46,7 +46,7 @@
.btn-handler-logout:hover {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.handler-message {
@@ -56,8 +56,8 @@
font-size: 0.9rem;
}
-.handler-message-success { background: #dcfce7; color: #166534; }
-.handler-message-error { background: #fee2e2; color: #b91c1c; }
+.handler-message-success { background: var(--color-success-bg); color: var(--color-success-text); }
+.handler-message-error { background: var(--color-danger-bg); color: var(--color-danger-text); }
.handler-availability-section {
background: var(--color-muted-bg);
@@ -92,15 +92,15 @@
.availability-big-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-green {
- background: #dcfce7;
- color: #15803d;
- border-color: #86efac;
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
+ border-color: var(--color-success-border);
}
.btn-red {
- background: #fee2e2;
- color: #b91c1c;
- border-color: #fca5a5;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
+ border-color: var(--color-danger-border);
}
.status-dot-lg {
@@ -110,8 +110,8 @@
flex-shrink: 0;
}
-.dot-green { background: #22c55e; }
-.dot-red { background: #ef4444; }
+.dot-green { background: var(--color-success); }
+.dot-red { background: var(--color-danger); }
.availability-hint {
font-size: 0.82rem;
@@ -147,7 +147,7 @@
font-size: 0.9rem;
}
-.btn-handler-edit:hover { background: var(--color-primary); color: white; }
+.btn-handler-edit:hover { background: var(--color-primary); color: var(--color-on-primary); }
.handler-info-list { display: flex; flex-direction: column; gap: 0.6rem; }
@@ -206,7 +206,7 @@
flex: 1;
padding: 0.65rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 6px;
font-size: 0.95rem;
diff --git a/nachsuche/frontend/src/components/handler/HandlerLogin.css b/nachsuche/frontend/src/components/handler/HandlerLogin.css
index 6715730..65680ad 100644
--- a/nachsuche/frontend/src/components/handler/HandlerLogin.css
+++ b/nachsuche/frontend/src/components/handler/HandlerLogin.css
@@ -6,7 +6,7 @@
}
.handler-login-card {
- background: white;
+ background: var(--color-surface);
border-radius: 10px;
padding: 2rem;
width: 100%;
@@ -48,7 +48,7 @@
.handler-mode-toggle button.active {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
font-weight: 600;
}
@@ -82,7 +82,7 @@
width: 100%;
padding: 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 6px;
font-size: 1rem;
@@ -102,8 +102,8 @@
}
.handler-error {
- background: #fee2e2;
- color: #b91c1c;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
border-radius: 4px;
padding: 0.6rem 0.9rem;
margin-bottom: 1rem;
@@ -111,8 +111,8 @@
}
.handler-success {
- background: #dcfce7;
- color: #166534;
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
border-radius: 4px;
padding: 0.6rem 0.9rem;
margin-bottom: 1rem;
diff --git a/nachsuche/frontend/src/components/map/MapView.css b/nachsuche/frontend/src/components/map/MapView.css
index bfb9cff..6e82ee3 100644
--- a/nachsuche/frontend/src/components/map/MapView.css
+++ b/nachsuche/frontend/src/components/map/MapView.css
@@ -13,32 +13,32 @@
left: 12px;
z-index: 500;
background: rgba(255, 255, 255, 0.95);
- color: #444;
+ color: var(--color-text-muted);
padding: 0.45rem 0.7rem;
border-radius: 6px;
font-size: 0.85rem;
- border: 1px solid #dcdcdc;
+ border: 1px solid var(--color-border);
}
.map-no-data {
padding: 3rem;
text-align: center;
- color: #666;
- background: white;
+ color: var(--color-text-muted);
+ background: var(--color-surface);
border-radius: 8px;
margin: 1rem 0;
}
.map-popup h3 {
margin: 0 0 0.5rem 0;
- color: #333;
+ color: var(--color-text);
font-size: 1rem;
}
.map-popup p {
margin: 0.25rem 0;
font-size: 0.85rem;
- color: #666;
+ color: var(--color-text-muted);
}
.map-popup a {
@@ -54,8 +54,40 @@
display: inline-block;
padding: 0.2rem 0.5rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border-radius: 4px;
font-size: 0.75rem;
margin-top: 0.5rem;
}
+
+/* ── Nachtansicht ────────────────────────────────────────────────────────
+ Die OSM-Kacheln sind immer taghell. In der Dämmerung ist die Karte damit
+ die mit Abstand hellste Fläche der App und blendet — genau die Situation,
+ in der Nachsuchen stattfinden. Die Kacheln werden deshalb abgedunkelt;
+ Marker und Bedienelemente bleiben unangetastet, damit sie lesbar sind. */
+@media (prefers-color-scheme: dark) {
+ .leaflet-tile-pane {
+ filter: brightness(0.62) saturate(0.75) contrast(1.05);
+ }
+
+ .leaflet-container {
+ background: var(--color-surface-alt);
+ }
+
+ /* Hoehere Spezifitaet als Leaflets eigene Regeln, die spaeter geladen werden */
+ .leaflet-container .leaflet-control-zoom a,
+ .leaflet-container .leaflet-control-attribution {
+ background: var(--color-surface);
+ color: var(--color-text);
+ }
+
+ .leaflet-container .leaflet-control-attribution a {
+ color: var(--color-primary);
+ }
+
+ .leaflet-popup-content-wrapper,
+ .leaflet-popup-tip {
+ background: var(--color-surface);
+ color: var(--color-text);
+ }
+}
diff --git a/nachsuche/frontend/src/components/public/PublicUserList.css b/nachsuche/frontend/src/components/public/PublicUserList.css
index c24d538..1eb3efd 100644
--- a/nachsuche/frontend/src/components/public/PublicUserList.css
+++ b/nachsuche/frontend/src/components/public/PublicUserList.css
@@ -14,7 +14,7 @@
}
.public-user-list h2 {
- color: #1a1a1a;
+ color: var(--color-text);
margin: 0;
font-size: 1.5rem;
font-weight: 700;
@@ -23,7 +23,7 @@
.toggle-map-button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -44,8 +44,8 @@
.filter-toggle-button {
padding: 0.5rem 1rem;
- background: #6c757d;
- color: white;
+ background: var(--color-secondary);
+ color: var(--color-on-secondary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -55,12 +55,12 @@
}
.filter-toggle-button:hover {
- background: #5a6268;
+ background: var(--color-secondary-dark);
}
.location-panel {
- background: white;
- border: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1rem 1.5rem;
margin-bottom: 1.5rem;
@@ -78,7 +78,7 @@
.location-button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -92,7 +92,7 @@
}
.location-button:disabled {
- background: #b6b6b6;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
@@ -103,13 +103,13 @@
}
.location-status.success {
- background: #e8f5e9;
- color: var(--color-primary-dark);
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
}
.location-status.error {
- background: #ffebee;
- color: #c62828;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
}
.postal-search {
@@ -120,21 +120,21 @@
.postal-search input[type="text"] {
padding: 0.5rem;
- border: 1px solid #ddd;
+ border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 0.9rem;
width: 150px;
}
.postal-search input[type="text"]:disabled {
- background: #f5f5f5;
+ background: var(--color-surface-alt);
cursor: not-allowed;
}
.postal-search button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -148,14 +148,14 @@
}
.postal-search button:disabled {
- background: #b6b6b6;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
.radius-filter label {
display: block;
font-size: 0.9rem;
- color: #555;
+ color: var(--color-text-muted);
margin-bottom: 0.5rem;
font-weight: 500;
}
@@ -174,26 +174,26 @@
.radius-inputs input[type="number"] {
width: 80px;
padding: 0.4rem 0.5rem;
- border: 1px solid #ddd;
+ border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 0.9rem;
}
.radius-inputs input:disabled {
- background: #f5f5f5;
+ background: var(--color-surface-alt);
cursor: not-allowed;
}
.radius-hint {
font-size: 0.85rem;
- color: #777;
+ color: var(--color-text-muted);
margin-top: 0.5rem;
}
.gps-hint {
margin-top: 0.5rem;
font-size: 0.85rem;
- color: #777;
+ color: var(--color-text-muted);
}
.user-grid {
@@ -205,8 +205,8 @@
/* Jägerschaft-style card */
.user-card {
- background: white;
- border: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
@@ -232,9 +232,9 @@
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
}
-.user-name {
+.public-user-list .user-name {
margin: 0 0 0.2rem;
- color: #1a1a1a;
+ color: var(--color-text);
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
@@ -250,15 +250,15 @@
color: var(--color-primary);
}
-.user-info {
+.public-user-list .user-info {
display: flex;
flex-direction: column;
gap: 0.375rem;
}
-.user-address {
+.public-user-list .user-address {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 0.9rem;
}
@@ -266,72 +266,80 @@
margin: 0.5rem 0 0;
}
-.type-badge {
+.public-user-list .type-badge {
display: inline-block;
padding: 0.2rem 0.6rem;
- background: #f0f0f0;
- color: #444;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
border-radius: 4px;
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.03em;
}
+/* Der Anruf beim Nachsuchenführer ist der Zweck dieser Liste und wird fast
+ immer mit dem Daumen auf dem Handy ausgelöst. Vorher war das ein 14 px hoher
+ Textlink; jetzt ein vollwertiges Ziel mit der empfohlenen Mindesthöhe. */
.user-phone {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ min-height: var(--touch-target);
+ margin: 0.15rem 0;
+ padding: 0.35rem 0.6rem;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-sm);
color: var(--color-primary);
text-decoration: none;
- font-weight: 500;
- font-size: 0.9rem;
+ font-weight: 600;
+ font-size: 1rem;
}
-.user-phone:hover {
+.public-user-list .user-phone:hover,
+.public-user-list .user-phone:focus-visible {
+ background: var(--color-surface);
+ border-color: var(--color-border-strong);
text-decoration: underline;
}
-.user-gps {
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid #e5e5e5;
- font-size: 0.85rem;
- color: #888;
-}
.user-distance {
margin-top: 0.75rem;
padding-top: 0.75rem;
- border-top: 1px solid #e5e5e5;
+ border-top: 1px solid var(--color-border);
font-size: 0.85rem;
- color: #555;
+ color: var(--color-text-muted);
font-weight: 500;
}
.no-users {
text-align: center;
padding: 3rem;
- color: #666;
+ color: var(--color-text-muted);
}
.loading {
text-align: center;
padding: 3rem;
- color: #666;
+ color: var(--color-text-muted);
}
@media (max-width: 768px) {
- .user-grid {
+.user-grid {
grid-template-columns: 1fr;
}
- .public-user-list {
+.public-user-list {
padding: 1rem;
}
- .radius-inputs {
+.radius-inputs {
flex-direction: column;
align-items: stretch;
}
- .radius-inputs input[type="number"] {
+.radius-inputs input[type="number"] {
width: 100%;
}
}
diff --git a/nachsuche/frontend/src/components/public/RulesDisplay.css b/nachsuche/frontend/src/components/public/RulesDisplay.css
index 32be9b6..4ec7a73 100644
--- a/nachsuche/frontend/src/components/public/RulesDisplay.css
+++ b/nachsuche/frontend/src/components/public/RulesDisplay.css
@@ -33,7 +33,7 @@
}
.allgemeines-tab-btn.active {
- background: white;
+ background: var(--color-surface);
color: var(--color-primary);
font-weight: 700;
border-color: var(--color-primary);
@@ -41,7 +41,7 @@
}
.allgemeines-content {
- background: white;
+ background: var(--color-surface);
border: 1px solid var(--color-primary);
border-top: none;
border-radius: 0 0 8px 8px;
diff --git a/nachsuche/frontend/src/components/users/UserCard.css b/nachsuche/frontend/src/components/users/UserCard.css
index a6f6bb7..2c62fa9 100644
--- a/nachsuche/frontend/src/components/users/UserCard.css
+++ b/nachsuche/frontend/src/components/users/UserCard.css
@@ -25,7 +25,7 @@
border-bottom: 1px solid var(--color-border);
}
-.user-name-row {
+.user-card-admin .user-name-row {
display: flex;
align-items: center;
gap: 0.5rem;
@@ -39,10 +39,10 @@
box-shadow: 0 0 4px rgba(0,0,0,0.2);
}
-.dot-green { background: #22c55e; }
-.dot-red { background: #ef4444; }
+.dot-green { background: var(--color-success); }
+.dot-red { background: var(--color-danger); }
-.user-name {
+.user-card-admin .user-name {
margin: 0;
color: var(--color-text);
font-size: 1.2rem;
@@ -67,40 +67,40 @@
font-weight: 600;
}
-.label-green { color: #16a34a; }
-.label-red { color: var(--color-danger); }
+.label-green { color: var(--color-success); }
+.label-red { color: var(--color-danger); }
-.user-info {
+.user-card-admin .user-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
-.user-address {
+.user-card-admin .user-address {
margin: 0;
color: var(--color-text-muted);
font-size: 0.9rem;
}
-.type-badge {
+.user-card-admin .type-badge {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border-radius: var(--radius-pill);
font-size: 0.85rem;
font-weight: 500;
}
-.user-phone {
+.user-card-admin .user-phone {
color: var(--color-primary);
text-decoration: none;
font-weight: 500;
font-size: 1rem;
}
-.user-phone:hover {
+.user-card-admin .user-phone:hover {
text-decoration: underline;
}
@@ -183,7 +183,7 @@
.edit-gps-button {
padding: 0.25rem 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -229,7 +229,7 @@
.save-gps-button {
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
}
.save-gps-button:hover:not(:disabled) {
@@ -243,7 +243,7 @@
.cancel-gps-button {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.cancel-gps-button:hover {
@@ -272,7 +272,7 @@
.edit-button {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.edit-button:hover {
@@ -281,7 +281,7 @@
.delete-button {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.delete-button:hover {
@@ -289,17 +289,17 @@
}
@media (max-width: 768px) {
- .user-header {
+.user-header {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}
- .gps-inputs {
+.gps-inputs {
flex-direction: column;
}
- .card-actions {
+.card-actions {
flex-direction: column;
}
}
@@ -322,7 +322,7 @@
display: block;
margin-top: 0.35rem;
padding: 0.4rem 0.5rem;
- background: var(--color-bg-muted, #f2f2ec);
+ background: var(--color-surface-alt);
border: 1px solid var(--color-border);
border-radius: 2px;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
diff --git a/nachsuche/frontend/src/components/users/UserForm.css b/nachsuche/frontend/src/components/users/UserForm.css
index 474c2a3..e3e62df 100644
--- a/nachsuche/frontend/src/components/users/UserForm.css
+++ b/nachsuche/frontend/src/components/users/UserForm.css
@@ -91,7 +91,7 @@
top: 100%;
left: 0;
right: 0;
- background: white;
+ background: var(--color-surface);
border: 1px solid var(--color-border-strong);
border-top: none;
border-radius: 0 0 var(--radius-sm) var(--radius-sm);
@@ -163,7 +163,7 @@
.btn-primary {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.btn-primary:hover {
@@ -172,7 +172,7 @@
.btn-secondary {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.btn-secondary:hover {
diff --git a/nachsuche/frontend/src/components/users/UserList.css b/nachsuche/frontend/src/components/users/UserList.css
index 4dd50f4..03ceb1a 100644
--- a/nachsuche/frontend/src/components/users/UserList.css
+++ b/nachsuche/frontend/src/components/users/UserList.css
@@ -34,7 +34,7 @@
.create-button {
padding: 0.5rem 1rem;
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
diff --git a/nachsuche/frontend/src/index.css b/nachsuche/frontend/src/index.css
index ec2585e..a76866f 100644
--- a/nachsuche/frontend/src/index.css
+++ b/nachsuche/frontend/src/index.css
@@ -1,13 +1,8 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
+/* Basisstile stehen in App.css, wo auch die Design-Tokens definiert sind.
+ Hier stand vorher eine zweite body-Regel, die von App.css vollständig
+ überschrieben wurde. */
+html {
+ /* Verhindert, dass iOS beim Drehen die Schrift eigenmächtig vergrößert. */
+ -webkit-text-size-adjust: 100%;
+ text-size-adjust: 100%;
}
diff --git a/portal/index.html b/portal/index.html
index aca5737..ccf4f6d 100644
--- a/portal/index.html
+++ b/portal/index.html
@@ -3,7 +3,7 @@
-
+
diff --git a/portal/manifest.json b/portal/manifest.json
index 883c36c..9f6c7a2 100644
--- a/portal/manifest.json
+++ b/portal/manifest.json
@@ -31,7 +31,7 @@
"scope": "/",
"display": "standalone",
"orientation": "portrait",
- "theme_color": "#2d6a2d",
- "background_color": "#ffffff",
+ "theme_color": "#1a3d1a",
+ "background_color": "#e8e8e2",
"description": "Jagd Apps Heidekreis – Übersicht aller Apps"
}
diff --git a/portal/offline.html b/portal/offline.html
index 6e27ceb..b1c4d55 100644
--- a/portal/offline.html
+++ b/portal/offline.html
@@ -3,29 +3,91 @@
- Offline – Jagd Apps
+
+ Offline – Jagd Apps Heidekreis
- 📡
- Keine Verbindung
- Bitte prüfen Sie Ihre Internetverbindung und laden Sie die Seite neu.
+
+
📡
+
Keine Verbindung
+
+ Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
+ Sobald wieder Empfang besteht, lädt die Seite normal.
+
+
+
diff --git a/stoeberhunde/frontend/index.html b/stoeberhunde/frontend/index.html
index 2171d6b..808a918 100644
--- a/stoeberhunde/frontend/index.html
+++ b/stoeberhunde/frontend/index.html
@@ -5,7 +5,7 @@
-
+
diff --git a/stoeberhunde/frontend/public/logo-fallingbostel.png b/stoeberhunde/frontend/public/logo-fallingbostel.png
deleted file mode 100644
index bf3e426..0000000
Binary files a/stoeberhunde/frontend/public/logo-fallingbostel.png and /dev/null differ
diff --git a/stoeberhunde/frontend/public/logo-ljn.png b/stoeberhunde/frontend/public/logo-ljn.png
deleted file mode 100644
index a1a6ce9..0000000
Binary files a/stoeberhunde/frontend/public/logo-ljn.png and /dev/null differ
diff --git a/stoeberhunde/frontend/public/manifest.json b/stoeberhunde/frontend/public/manifest.json
index e993e21..cdfd13f 100644
--- a/stoeberhunde/frontend/public/manifest.json
+++ b/stoeberhunde/frontend/public/manifest.json
@@ -19,7 +19,7 @@
"scope": "/stoeberhunde/",
"display": "standalone",
"orientation": "portrait",
- "theme_color": "#2d6a2d",
- "background_color": "#ffffff",
+ "theme_color": "#1a3d1a",
+ "background_color": "#e8e8e2",
"description": "Stöberhunde Heidekreis – Übersicht der Stöberhundleiter"
}
diff --git a/stoeberhunde/frontend/public/offline.html b/stoeberhunde/frontend/public/offline.html
index 6e5c44b..b1c4d55 100644
--- a/stoeberhunde/frontend/public/offline.html
+++ b/stoeberhunde/frontend/public/offline.html
@@ -1,16 +1,93 @@
-
+
-
-
- Offline - Stöberhundeführer
-
+
+
+
+ Offline – Jagd Apps Heidekreis
+
- Du bist offline
- Die App ist derzeit nicht verfügbar. Bitte überprüfe deine Internetverbindung.
+
+
📡
+
Keine Verbindung
+
+ Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
+ Sobald wieder Empfang besteht, lädt die Seite normal.
+
+
+
-
\ No newline at end of file
+
diff --git a/stoeberhunde/frontend/src/App.css b/stoeberhunde/frontend/src/App.css
index b8f3ffe..b3a77b8 100644
--- a/stoeberhunde/frontend/src/App.css
+++ b/stoeberhunde/frontend/src/App.css
@@ -2,43 +2,203 @@
box-sizing: border-box;
}
+/* ──────────────────────────────────────────────────────────────────────────
+ Design-Tokens — einzige Farbquelle der App.
+ Palette und Formensprache folgen dem Portal (portal/index.html), damit der
+ Wechsel vom Portal in eine App nicht wie ein Produktwechsel wirkt.
+ Schriftmodell wie im Portal: Serif für die Marken-/Überschriftenebene,
+ Sans für funktionale UI-Texte (auf kleinen Displays besser lesbar).
+
+ Alle Textpaare erfüllen WCAG AA (>= 4.5:1), funktionale Rahmen >= 3.0:1 —
+ in beiden Varianten nachgerechnet.
+ ────────────────────────────────────────────────────────────────────────── */
:root {
- --color-primary: #2e8b2e;
- --color-primary-dark: #1e6b1e;
- --color-primary-accent: #8B0D12;
- --color-secondary: #6c757d;
- --color-secondary-dark: #5a6268;
- --color-success: #28a745;
- --color-success-dark: #218838;
- --color-danger: #dc3545;
- --color-danger-dark: #c82333;
- --color-bg: #f5f5f0;
- --color-surface: #ffffff;
+ --font-display: Georgia, 'Times New Roman', serif;
+ --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-mono: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
+
+ /* Flächen */
+ --color-bg: #e8e8e2;
+ --color-surface: #f4f4ee;
+ --color-surface-alt: #dedcd2;
+ --color-muted-bg: #dedcd2;
+
+ /* Text */
--color-text: #1a1a1a;
- --color-text-muted: #555;
- --color-border: #b8d4b8;
- --color-border-strong: #88b888;
- --color-focus: rgba(46, 139, 46, 0.2);
- --color-muted-bg: #f5f5f0;
- --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.1);
- --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.2);
- --radius-sm: 4px;
- --radius-md: 8px;
- --radius-pill: 12px;
+ --color-text-muted: #55554c;
+
+ /* Rahmen: -border ist dekorativ (Trennlinien, Karten),
+ -border-strong begrenzt Bedienelemente und erfüllt die 3:1-Anforderung. */
+ --color-border: #c9c9b8;
+ --color-border-strong: #7d7d68;
+
+ /* Aktionsfarben – jeweils mit der zugehörigen Textfarbe, damit die
+ Dunkelvariante nicht auf weißem Text auf hellem Grund landet. */
+ --color-primary: #2d5a2d;
+ --color-primary-dark: #1a3d1a;
+ --color-on-primary: #ffffff;
+ --color-secondary: #5c5c50;
+ --color-secondary-dark: #46463c;
+ --color-on-secondary: #ffffff;
+ --color-success: #1f6b34;
+ --color-success-dark: #175128;
+ --color-on-success: #ffffff;
+ --color-danger: #a32020;
+ --color-danger-dark: #821919;
+ --color-on-danger: #ffffff;
+ --color-warning: #7a5200;
+ --color-on-warning: #ffffff;
+ --color-accent: #8b0d12;
+ --color-on-accent: #ffffff;
+ /* Altname, wird von RulesDisplay noch benutzt */
+ --color-primary-accent: #8b0d12;
+
+ /* Getönte Status-Flächen (Meldungen, Badges, Zustands-Karten).
+ Der Block wird durch seine Füllung erkannt, der Rahmen ist Zierde. */
+ --color-success-bg: #dfeedd;
+ --color-success-border: #a9cba4;
+ --color-success-text: #1a4a24;
+ --color-danger-bg: #f6e0e0;
+ --color-danger-border: #d9a9a9;
+ --color-danger-text: #7d1a1a;
+ --color-warning-bg: #f7edd4;
+ --color-warning-border: #d9c48a;
+ --color-warning-text: #5c3d00;
+ --color-info: #24608f;
+ --color-info-dark: #1b4a6e;
+ --color-on-info: #ffffff;
+ --color-info-bg: #dde8f1;
+ --color-info-border: #a5bfd4;
+ --color-info-text: #14405f;
+
+ /* Als RGB-Tripel fuer rgba()-Anwendungen (Puls-Animation im Admin-Panel) */
+ --color-primary-rgb: 45, 90, 45;
+
+ --color-focus: rgba(45, 90, 45, 0.35);
+
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.15);
+ --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.2);
+
+ /* Kantige Ecken wie im Portal */
+ --radius-sm: 2px;
+ --radius-md: 2px;
+ --radius-pill: 2px;
+
--space-1: 0.5rem;
--space-2: 1rem;
--space-3: 1.5rem;
--space-4: 2rem;
+
+ /* Mindestgröße für Bedienelemente auf Touchgeräten */
+ --touch-target: 44px;
}
+/* Nachtvariante. Nachsuchen laufen in der Dämmerung und nachts — ein weißes
+ Vollbild blendet dann und kostet die Dunkeladaption der Augen. Warme, sehr
+ dunkle Grüntöne statt reinem Schwarz. */
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-bg: #14180f;
+ --color-surface: #1e241a;
+ --color-surface-alt: #2a3124;
+ --color-muted-bg: #2a3124;
+
+ --color-text: #e9e7dd;
+ --color-text-muted: #a6a698;
+
+ --color-border: #333b28;
+ --color-border-strong: #758566;
+
+ --color-primary: #7fb36f;
+ --color-primary-dark: #9ccb8c;
+ --color-on-primary: #10140c;
+ --color-secondary: #8d8d80;
+ --color-secondary-dark: #a3a396;
+ --color-on-secondary: #10140c;
+ --color-success: #79c48c;
+ --color-success-dark: #93d3a3;
+ --color-on-success: #10140c;
+ --color-danger: #ea8b8b;
+ --color-danger-dark: #f2a5a5;
+ --color-on-danger: #10140c;
+ --color-warning: #d6b25f;
+ --color-on-warning: #10140c;
+ --color-accent: #e88a8f;
+ --color-on-accent: #10140c;
+ --color-primary-accent: #e88a8f;
+
+ --color-success-bg: #1d2c20;
+ --color-success-border: #3d5c43;
+ --color-success-text: #93d3a3;
+ --color-danger-bg: #33201f;
+ --color-danger-border: #6b4040;
+ --color-danger-text: #f2a5a5;
+ --color-warning-bg: #322a15;
+ --color-warning-border: #63552c;
+ --color-warning-text: #e0c37c;
+ --color-info: #7fb0dc;
+ --color-info-dark: #9cc4e8;
+ --color-on-info: #10140c;
+ --color-info-bg: #1a2530;
+ --color-info-border: #3d5468;
+ --color-info-text: #9cc4e8;
+
+ --color-primary-rgb: 127, 179, 111;
+ --color-focus: rgba(127, 179, 111, 0.45);
+
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
+ --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.6);
+ }
+}
+
+body {
+ margin: 0;
+ font-family: var(--font-ui);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background: var(--color-bg);
+ color: var(--color-text);
+ /* Damit auch vom Browser gestellte Bedienelemente (Bildlaufleisten,
+ Datumsauswahl, Autofill) der gewählten Ansicht folgen. */
+ color-scheme: light dark;
+}
+
+/* Formularfelder brauchen ausdrücklich Farben: ohne sie nimmt der Browser
+ seinen Standard (weiß) — in der Nachtansicht leuchtet dann jedes Eingabefeld. */
+input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='file']),
+select,
+textarea {
+ background: var(--color-surface);
+ color: var(--color-text);
+}
+
+input::placeholder,
+textarea::placeholder {
+ color: var(--color-text-muted);
+ opacity: 1;
+}
+
+h1, h2, h3 {
+ font-family: var(--font-display);
+}
+
+code {
+ font-family: var(--font-mono);
+}
+
+/* ── Bedienelemente ─────────────────────────────────────────────────────── */
+
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-1);
+ min-height: var(--touch-target);
padding: 0.5rem 1rem;
border: none;
border-radius: var(--radius-sm);
+ font-family: var(--font-ui);
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
@@ -46,15 +206,24 @@
}
.btn:disabled {
- background: var(--color-border);
+ background: var(--color-surface-alt);
color: var(--color-text-muted);
cursor: not-allowed;
box-shadow: none;
}
+/* Sichtbarer Tastaturfokus. Ohne das war die Tastaturbedienung unsichtbar —
+ Buttons hatten nur einen :hover-Stil. */
+.btn:focus-visible,
+.nav-button:focus-visible,
+a:focus-visible {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
+
.btn-primary {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.btn-primary:hover:not(:disabled) {
@@ -64,7 +233,7 @@
.btn-secondary {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.btn-secondary:hover:not(:disabled) {
@@ -72,19 +241,9 @@
transform: translateY(-1px);
}
-.btn-success {
- background: var(--color-success);
- color: white;
-}
-
-.btn-success:hover:not(:disabled) {
- background: var(--color-success-dark);
- transform: translateY(-1px);
-}
-
.btn-danger {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.btn-danger:hover:not(:disabled) {
@@ -96,9 +255,13 @@
.select,
.textarea {
width: 100%;
+ min-height: var(--touch-target);
padding: 0.75rem 1rem;
+ background: var(--color-surface);
+ color: var(--color-text);
border: 1px solid var(--color-border-strong);
border-radius: var(--radius-sm);
+ font-family: var(--font-ui);
font-size: 1rem;
box-sizing: border-box;
}
@@ -111,33 +274,19 @@
box-shadow: 0 0 0 3px var(--color-focus);
}
-.panel {
- background: var(--color-surface);
- border: 1px solid var(--color-border);
- border-radius: var(--radius-md);
- padding: var(--space-3);
- box-shadow: var(--shadow-sm);
-}
-
.panel-title {
margin: 0 0 var(--space-2);
+ font-family: var(--font-display);
font-size: 1.1rem;
color: var(--color-text);
}
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- background: var(--color-bg);
- color: var(--color-text);
-}
+/* ── Grundgerüst ────────────────────────────────────────────────────────── */
.App {
- min-height: 100vh;
+ /* dvh statt vh: mit ein- und ausblendender Adressleiste auf Mobilgeräten
+ entsteht mit vh sonst Überlauf. */
+ min-height: 100dvh;
display: flex;
flex-direction: column;
}
@@ -151,44 +300,26 @@ body {
display: flex;
justify-content: center;
align-items: center;
- min-height: 100vh;
+ min-height: 100dvh;
font-size: 1.2rem;
color: var(--color-text-muted);
}
-.login-prompt {
- position: fixed;
- bottom: 20px;
- right: 20px;
-}
-
-.login-button-header {
- padding: 0.75rem 1.5rem;
- background: var(--color-primary);
- color: white;
- border: none;
- border-radius: 4px;
- font-size: 1rem;
- font-weight: 600;
- cursor: pointer;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- transition: all 0.2s;
-}
-
-.login-button-header:hover {
- background: var(--color-primary-dark);
- transform: translateY(-2px);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
-}
-
-@media (max-width: 768px) {
- .login-prompt {
- bottom: 10px;
- right: 10px;
+/* Wer Bewegung reduziert haben möchte, bekommt keine Animationen. */
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
}
- .login-button-header {
- padding: 0.6rem 1.2rem;
- font-size: 0.9rem;
+ .btn:hover:not(:disabled),
+ .btn-primary:hover:not(:disabled),
+ .btn-secondary:hover:not(:disabled),
+ .btn-danger:hover:not(:disabled) {
+ transform: none;
}
}
diff --git a/stoeberhunde/frontend/src/components/admin/AdminPanel.css b/stoeberhunde/frontend/src/components/admin/AdminPanel.css
index 12ce644..16e6fa0 100644
--- a/stoeberhunde/frontend/src/components/admin/AdminPanel.css
+++ b/stoeberhunde/frontend/src/components/admin/AdminPanel.css
@@ -25,7 +25,7 @@
.tab-button.active {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.settings-panel {
@@ -59,9 +59,9 @@
.unsaved-badge {
display: inline-block;
- background: #fff3cd;
- color: #856404;
- border: 1px solid #ffc107;
+ background: var(--color-warning-bg);
+ color: var(--color-warning-text);
+ border: 1px solid var(--color-warning);
border-radius: var(--radius-sm);
padding: 0.2rem 0.6rem;
font-size: 0.8rem;
@@ -102,7 +102,7 @@
display: flex;
align-items: center;
gap: 0.5rem;
- background: var(--color-muted-bg, #f5f5f0);
+ background: var(--color-muted-bg, var(--color-surface-alt));
border: none;
padding: 0.75rem var(--space-2);
cursor: pointer;
@@ -111,7 +111,7 @@
}
.settings-section-header:hover {
- background: var(--color-focus, #eef2e6);
+ background: var(--color-focus, var(--color-success-bg));
}
.settings-section-header .settings-heading {
@@ -193,7 +193,7 @@
.skeleton-line {
height: 1rem;
border-radius: var(--radius-sm);
- background: linear-gradient(90deg, #e8e8e4 25%, #f0f0ec 50%, #e8e8e4 75%);
+ background: linear-gradient(90deg, var(--color-surface-alt) 25%, var(--color-surface-alt) 50%, var(--color-surface-alt) 75%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.4s infinite;
margin-bottom: 0.75rem;
@@ -323,17 +323,17 @@
.notification.success {
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
}
.notification.error {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.notification.warning {
- background: #e67e00;
- color: white;
+ background: var(--color-warning);
+ color: var(--color-on-warning);
}
@keyframes slideIn {
diff --git a/stoeberhunde/frontend/src/components/admin/AuditLogs.css b/stoeberhunde/frontend/src/components/admin/AuditLogs.css
index 433cfc4..0f2d27a 100644
--- a/stoeberhunde/frontend/src/components/admin/AuditLogs.css
+++ b/stoeberhunde/frontend/src/components/admin/AuditLogs.css
@@ -13,8 +13,8 @@
gap: 12px;
flex-wrap: wrap;
}
-.audit-header h2 { margin: 0 0 4px 0; color: #333; font-size: 26px; }
-.audit-description { margin: 0; color: #666; font-size: 13px; }
+.audit-header h2 { margin: 0 0 4px 0; color: var(--color-text); font-size: 26px; }
+.audit-description { margin: 0; color: var(--color-text-muted); font-size: 13px; }
.audit-header-actions {
display: flex;
@@ -32,24 +32,24 @@
}
.btn-stats-toggle {
padding: 6px 14px;
- background: #f0f4f8;
- border: 1px solid #d0d7de;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
font-size: 13px;
- color: #444;
+ color: var(--color-text-muted);
}
-.btn-stats-toggle:hover { background: #e2e8f0; }
+.btn-stats-toggle:hover { background: var(--color-surface-alt); }
.stats-days-select { font-size: 13px; }
.audit-stats {
- background: #f8fafc;
- border: 1px solid #e2e8f0;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
border-radius: 10px;
padding: 16px;
margin-bottom: 16px;
}
-.stats-loading { color: #888; font-size: 13px; padding: 8px 0; }
+.stats-loading { color: var(--color-text-muted); font-size: 13px; padding: 8px 0; }
.stats-row {
display: flex;
@@ -60,18 +60,18 @@
.stat-card {
flex: 1;
min-width: 100px;
- background: white;
+ background: var(--color-surface);
border-radius: 8px;
padding: 12px 16px;
text-align: center;
- border: 1px solid #e2e8f0;
+ border: 1px solid var(--color-border);
}
.stat-number { font-size: 28px; font-weight: 700; line-height: 1; }
-.stat-label { font-size: 11px; color: #666; margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
-.stat-total .stat-number { color: #1976d2; }
-.stat-failed .stat-number { color: #c62828; }
-.stat-success .stat-number { color: #2e7d32; }
-.stat-period .stat-number { color: #555; font-size: 20px; }
+.stat-label { font-size: 11px; color: var(--color-text-muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
+.stat-total .stat-number { color: var(--color-info-text); }
+.stat-failed .stat-number { color: var(--color-danger-text); }
+.stat-success .stat-number { color: var(--color-success-text); }
+.stat-period .stat-number { color: var(--color-text-muted); font-size: 20px; }
.stats-details {
display: flex;
@@ -79,7 +79,7 @@
flex-wrap: wrap;
}
.stats-col { flex: 1; min-width: 180px; }
-.stats-col h4 { margin: 0 0 8px 0; font-size: 12px; text-transform: uppercase; color: #888; letter-spacing: 0.5px; }
+.stats-col h4 { margin: 0 0 8px 0; font-size: 12px; text-transform: uppercase; color: var(--color-text-muted); letter-spacing: 0.5px; }
.stat-bar-row {
display: flex;
@@ -88,8 +88,8 @@
gap: 8px;
margin-bottom: 5px;
}
-.stat-bar-label { font-size: 13px; color: #444; }
-.stat-bar-count { font-size: 13px; font-weight: 600; color: #333; flex-shrink: 0; }
+.stat-bar-label { font-size: 13px; color: var(--color-text-muted); }
+.stat-bar-count { font-size: 13px; font-weight: 600; color: var(--color-text); flex-shrink: 0; }
/* Mini bar chart */
.stats-chart-col { flex: 2; min-width: 220px; }
@@ -98,7 +98,7 @@
align-items: flex-end;
gap: 3px;
height: 80px;
- background: #f0f4f8;
+ background: var(--color-surface-alt);
border-radius: 6px;
padding: 6px 6px 0;
}
@@ -110,7 +110,7 @@
}
.chart-bar {
width: 100%;
- background: #1976d2;
+ background: var(--color-info);
border-radius: 2px 2px 0 0;
position: relative;
min-height: 4px;
@@ -121,7 +121,7 @@
bottom: 0;
left: 0;
width: 100%;
- background: #e53935;
+ background: var(--color-danger);
}
/* ── Filters ─────────────────────────────────────────────────────── */
@@ -134,52 +134,52 @@
}
.filter-select {
padding: 8px 12px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
font-size: 13px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
}
-.filter-select:focus { outline: none; border-color: #1976d2; }
+.filter-select:focus { outline: none; border-color: var(--color-primary); }
.filter-input {
padding: 8px 12px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
font-size: 13px;
- background: white;
+ background: var(--color-surface);
min-width: 140px;
}
-.filter-input:focus { outline: none; border-color: #1976d2; }
+.filter-input:focus { outline: none; border-color: var(--color-primary); }
.filter-date { min-width: 130px; }
.btn-refresh {
padding: 8px 14px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
}
-.btn-refresh:hover:not(:disabled) { background: #1565c0; }
-.btn-refresh:disabled { background: #bdbdbd; cursor: not-allowed; }
+.btn-refresh:hover:not(:disabled) { background: var(--color-info-dark); }
+.btn-refresh:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); cursor: not-allowed; }
.btn-reset {
padding: 8px 12px;
- background: white;
- color: #666;
- border: 1.5px solid #d0d7de;
+ background: var(--color-surface);
+ color: var(--color-text-muted);
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
font-size: 13px;
}
-.btn-reset:hover { background: #f5f5f5; }
+.btn-reset:hover { background: var(--color-surface-alt); }
.btn-export {
padding: 8px 16px;
- background: #2e7d32;
- color: white;
+ background: var(--color-success);
+ color: var(--color-on-success);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -187,15 +187,15 @@
font-weight: 500;
white-space: nowrap;
}
-.btn-export:hover:not(:disabled) { background: #1b5e20; }
-.btn-export:disabled { background: #bdbdbd; cursor: not-allowed; }
+.btn-export:hover:not(:disabled) { background: var(--color-success-dark); }
+.btn-export:disabled { background: var(--color-surface-alt); color: var(--color-text-muted); cursor: not-allowed; }
.auto-refresh-toggle {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
- color: #555;
+ color: var(--color-text-muted);
cursor: pointer;
white-space: nowrap;
}
@@ -206,7 +206,7 @@
justify-content: space-between;
align-items: center;
font-size: 13px;
- color: #666;
+ color: var(--color-text-muted);
margin-bottom: 10px;
}
.limit-select { padding: 4px 8px; font-size: 13px; }
@@ -224,16 +224,16 @@
}
.badge-create { background: #e8f5e9; color: #2e7d32; }
.badge-update { background: #e3f2fd; color: #1565c0; }
-.badge-delete { background: #ffebee; color: #c62828; }
-.badge-restore { background: #fff3e0; color: #e65100; }
+.badge-delete { background: #ffebee; color: var(--color-danger-text); }
+.badge-restore { background: #fff3e0; color: #a83a00; }
.badge-login { background: #f3e5f5; color: #6a1b9a; }
.badge-logout { background: #fce4ec; color: #880e4f; }
.badge-login-failed { background: #ffcdd2; color: #b71c1c; font-weight: 700; }
.badge-import { background: #e0f7fa; color: #00695c; }
.badge-export { background: #e8f5e9; color: #1b5e20; }
-.badge-bulk-update { background: #e8eaf6; color: #283593; }
+.badge-bulk-update { background: var(--color-surface-alt); color: #283593; }
.badge-bulk-delete { background: #fbe9e7; color: #bf360c; }
-.badge-password { background: #fff8e1; color: #f57f17; }
+.badge-password { background: #fff8e1; color: #9c4e00; }
.badge-default { background: #f5f5f5; color: #616161; }
.status-code {
@@ -244,16 +244,16 @@
font-family: monospace;
}
.status-ok { background: #e8f5e9; color: #2e7d32; }
-.status-redirect { background: #fff3e0; color: #e65100; }
-.status-error { background: #ffebee; color: #c62828; }
+.status-redirect { background: #fff3e0; color: #a83a00; }
+.status-error { background: #ffebee; color: var(--color-danger-text); }
.status-server-error { background: #f3e5f5; color: #6a1b9a; }
.duration-badge {
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
- background: #f5f5f5;
- color: #777;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
font-family: monospace;
}
@@ -261,24 +261,24 @@
.audit-empty {
text-align: center;
padding: 40px;
- background: #f9f9f9;
+ background: var(--color-surface-alt);
border-radius: 8px;
- color: #888;
+ color: var(--color-text-muted);
}
.audit-error { text-align: center; padding: 20px; }
-.audit-error p { color: #d32f2f; margin: 0; }
+.audit-error p { color: var(--color-danger-text); margin: 0; }
.audit-list { display: flex; flex-direction: column; gap: 8px; }
.audit-item {
- background: white;
- border: 1px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
overflow: hidden;
transition: box-shadow 0.15s;
}
.audit-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
-.audit-item-failed { border-left: 4px solid #e53935; }
+.audit-item-failed { border-left: 4px solid var(--color-danger); }
.audit-item-header {
display: flex;
@@ -286,18 +286,18 @@
gap: 8px;
padding: 10px 14px;
flex-wrap: wrap;
- background: #fafafa;
- border-bottom: 1px solid #f0f0f0;
+ background: var(--color-surface-alt);
+ border-bottom: 1px solid var(--color-border);
}
-.audit-time { margin-left: auto; color: #999; font-size: 12px; white-space: nowrap; }
-.expand-toggle { color: #aaa; font-size: 11px; cursor: pointer; padding: 0 4px; }
+.audit-time { margin-left: auto; color: var(--color-text-muted); font-size: 12px; white-space: nowrap; }
+.expand-toggle { color: var(--color-text-muted); font-size: 11px; cursor: pointer; padding: 0 4px; }
.audit-resource {
padding: 3px 8px;
- background: #f0f0f0;
+ background: var(--color-surface-alt);
border-radius: 4px;
font-size: 12px;
- color: #555;
+ color: var(--color-text-muted);
}
.audit-item-body {
@@ -308,16 +308,16 @@
font-size: 13px;
align-items: center;
}
-.audit-admin { color: #333; }
-.audit-resource-name { color: #555; }
-.audit-ip { color: #999; font-family: monospace; font-size: 12px; }
-.audit-failed-badge { color: #c62828; font-weight: 600; font-size: 12px; }
+.audit-admin { color: var(--color-text); }
+.audit-resource-name { color: var(--color-text-muted); }
+.audit-ip { color: var(--color-text-muted); font-family: monospace; font-size: 12px; }
+.audit-failed-badge { color: var(--color-danger-text); font-weight: 600; font-size: 12px; }
/* ── Expanded detail ─────────────────────────────────────────────── */
.audit-item-detail {
padding: 10px 14px 14px;
- border-top: 1px dashed #e0e0e0;
- background: #fefefe;
+ border-top: 1px dashed var(--color-border);
+ background: var(--color-surface);
display: flex;
flex-direction: column;
gap: 8px;
@@ -330,7 +330,7 @@
}
.detail-label {
font-weight: 600;
- color: #888;
+ color: var(--color-text-muted);
font-size: 11px;
text-transform: uppercase;
min-width: 70px;
@@ -338,23 +338,23 @@
}
.detail-row code {
font-family: monospace;
- background: #f0f0f0;
+ background: var(--color-surface-alt);
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
}
.detail-ua-full {
- color: #aaa;
+ color: var(--color-text-muted);
cursor: help;
font-size: 12px;
}
-.detail-error { color: #c62828; }
-.detail-error .detail-label { color: #c62828; }
+.detail-error { color: var(--color-danger-text); }
+.detail-error .detail-label { color: var(--color-danger-text); }
.meta-tag {
display: inline-block;
- background: #e8eaf6;
- color: #283593;
+ background: var(--color-surface-alt);
+ color: var(--color-info-text);
border-radius: 4px;
padding: 2px 8px;
font-size: 12px;
@@ -370,17 +370,17 @@
margin-top: 6px;
}
.diff-table th {
- background: #f0f0f0;
+ background: var(--color-surface-alt);
padding: 5px 10px;
text-align: left;
font-size: 11px;
text-transform: uppercase;
- color: #666;
- border: 1px solid #e0e0e0;
+ color: var(--color-text-muted);
+ border: 1px solid var(--color-border);
}
-.diff-table td { padding: 5px 10px; border: 1px solid #e8e8e8; vertical-align: top; }
-.diff-field { font-weight: 600; color: #444; font-family: monospace; white-space: nowrap; background: #fafafa; }
-.diff-before { color: #c62828; background: #fff5f5; font-family: monospace; word-break: break-all; }
+.diff-table td { padding: 5px 10px; border: 1px solid var(--color-border); vertical-align: top; }
+.diff-field { font-weight: 600; color: var(--color-text-muted); font-family: monospace; white-space: nowrap; background: var(--color-surface-alt); }
+.diff-before { color: var(--color-danger-text); background: #fff5f5; font-family: monospace; word-break: break-all; }
.diff-after { color: #2e7d32; background: #f5fff5; font-family: monospace; word-break: break-all; }
/* ── Pagination ──────────────────────────────────────────────────── */
@@ -393,16 +393,16 @@
}
.btn-page {
padding: 7px 14px;
- border: 1.5px solid #d0d7de;
+ border: 1.5px solid var(--color-border);
border-radius: 6px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
font-size: 13px;
- color: #333;
+ color: var(--color-text);
}
-.btn-page:hover:not(:disabled) { background: #f0f4f8; border-color: #1976d2; }
-.btn-page:disabled { color: #bbb; cursor: not-allowed; border-color: #eee; }
-.page-info { font-size: 13px; color: #666; padding: 0 8px; }
+.btn-page:hover:not(:disabled) { background: var(--color-surface-alt); border-color: var(--color-primary); }
+.btn-page:disabled { color: var(--color-text-muted); cursor: not-allowed; border-color: var(--color-border); }
+.page-info { font-size: 13px; color: var(--color-text-muted); padding: 0 8px; }
.audit-header {
@@ -411,13 +411,13 @@
.audit-header h2 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
}
.audit-description {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -428,7 +428,7 @@
}
.audit-error p {
- color: #d32f2f;
+ color: var(--color-danger-text);
margin: 0;
}
@@ -441,23 +441,23 @@
.filter-select {
padding: 10px 14px;
- border: 2px solid #e0e0e0;
+ border: 2px solid var(--color-border);
border-radius: 6px;
font-size: 14px;
- background: white;
+ background: var(--color-surface);
cursor: pointer;
transition: border-color 0.2s;
}
.filter-select:focus {
outline: none;
- border-color: #1976d2;
+ border-color: var(--color-primary);
}
.btn-refresh {
padding: 10px 16px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -467,20 +467,21 @@
}
.btn-refresh:hover:not(:disabled) {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.btn-refresh:disabled {
- background: #bdbdbd;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
cursor: not-allowed;
}
.audit-empty {
text-align: center;
padding: 40px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 8px;
- color: #666;
+ color: var(--color-text-muted);
}
.audit-list {
@@ -490,8 +491,8 @@
}
.audit-item {
- background: white;
- border: 1px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 16px;
transition: box-shadow 0.2s;
@@ -519,58 +520,18 @@
gap: 4px;
}
-.badge-create {
- background: #e8f5e9;
- color: #2e7d32;
-}
-
-.badge-update {
- background: #e3f2fd;
- color: #1565c0;
-}
-
-.badge-delete {
- background: #ffebee;
- color: #c62828;
-}
-
-.badge-restore {
- background: #fff3e0;
- color: #e65100;
-}
-
-.badge-login {
- background: #f3e5f5;
- color: #6a1b9a;
-}
-
-.badge-logout {
- background: #fce4ec;
- color: #880e4f;
-}
-
-.badge-login-failed {
- background: #ffcdd2;
- color: #b71c1c;
- font-weight: 700;
-}
-
-.badge-default {
- background: #f5f5f5;
- color: #616161;
-}
.audit-resource {
padding: 4px 10px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 4px;
font-size: 13px;
- color: #666;
+ color: var(--color-text-muted);
}
.audit-time {
margin-left: auto;
- color: #999;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -582,23 +543,19 @@
}
.audit-admin {
- color: #333;
+ color: var(--color-text);
}
.audit-resource-name {
- color: #666;
+ color: var(--color-text-muted);
}
.audit-ip {
- color: #888;
+ color: var(--color-text-muted);
font-family: monospace;
font-size: 13px;
}
-.audit-error-message {
- color: #d32f2f;
- font-weight: 500;
-}
.audit-pagination {
display: flex;
@@ -607,15 +564,15 @@
gap: 16px;
margin-top: 24px;
padding: 16px;
- background: white;
+ background: var(--color-surface);
border-radius: 8px;
- border: 1px solid #e0e0e0;
+ border: 1px solid var(--color-border);
}
.btn-page {
padding: 8px 16px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -624,16 +581,17 @@
}
.btn-page:hover:not(:disabled) {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.btn-page:disabled {
- background: #bdbdbd;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
cursor: not-allowed;
}
.page-info {
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -656,3 +614,33 @@
width: 100%;
}
}
+
+/* ── Nachtvariante ───────────────────────────────────────────────────────
+ Die Badges kodieren die Aktionsart über den Farbton – der bleibt erhalten,
+ nur Helligkeit und Sättigung drehen sich um. Alle Paare >= 6.4:1. */
+@media (prefers-color-scheme: dark) {
+ .badge-create { background: #162d17; color: #97d99a; }
+ .badge-update { background: #16202d; color: #89b5e6; }
+ .badge-delete { background: #2d1616; color: #e68989; }
+ .badge-restore { background: #2d1e16; color: #e6aa89; }
+ .badge-login { background: #24162d; color: #c389e6; }
+ .badge-logout { background: #2d1622; color: #e689bb; }
+ .badge-login-failed { background: #2d1616; color: #e68989; }
+ .badge-import { background: #162d2a; color: #89e6db; }
+ .badge-export { background: #162d17; color: #90df96; }
+ .badge-bulk-update { background: #16182d; color: #8f99e0; }
+ .badge-bulk-delete { background: #2d1b16; color: #e69f89; }
+ .badge-password { background: #2d2016; color: #e6b589; }
+ .badge-default { background: var(--color-surface-alt); color: var(--color-text-muted); }
+
+ .status-ok { background: #162d17; color: #97d99a; }
+ .status-redirect { background: #2d1e16; color: #e6aa89; }
+ .status-error { background: #2d1616; color: #e68989; }
+ .status-server-error { background: #24162d; color: #c389e6; }
+
+ /* Diff-Tabelle: die roten/gruenen Vorher-Nachher-Felder */
+ .diff-table th { background: var(--color-surface-alt); }
+ .diff-before { color: #e68989; background: #2d1616; }
+ .diff-after { color: #97d99a; background: #162d17; }
+ .diff-field { background: var(--color-surface-alt); color: var(--color-text); }
+}
diff --git a/stoeberhunde/frontend/src/components/admin/ExportButton.css b/stoeberhunde/frontend/src/components/admin/ExportButton.css
index 83981da..c231346 100644
--- a/stoeberhunde/frontend/src/components/admin/ExportButton.css
+++ b/stoeberhunde/frontend/src/components/admin/ExportButton.css
@@ -14,7 +14,7 @@
.export-button {
padding: 0.5rem 1rem;
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -41,8 +41,8 @@
.import-button {
padding: 0.5rem 1rem;
- background: var(--color-primary, #2563eb);
- color: white;
+ background: var(--color-primary, var(--color-info));
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -52,7 +52,7 @@
}
.import-button:hover:not(:disabled) {
- background: var(--color-primary-dark, #1d4ed8);
+ background: var(--color-primary-dark, var(--color-info-dark));
}
.import-button:disabled {
@@ -65,7 +65,7 @@
align-items: center;
gap: 0.4rem;
font-size: 0.85rem;
- color: var(--color-text-muted, #6b7280);
+ color: var(--color-text-muted);
cursor: pointer;
white-space: nowrap;
}
diff --git a/stoeberhunde/frontend/src/components/admin/Trash.css b/stoeberhunde/frontend/src/components/admin/Trash.css
index 200c68a..e70ac72 100644
--- a/stoeberhunde/frontend/src/components/admin/Trash.css
+++ b/stoeberhunde/frontend/src/components/admin/Trash.css
@@ -10,13 +10,13 @@
.trash-header h2 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
}
.trash-description {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
@@ -27,14 +27,14 @@
}
.trash-error h3 {
- color: #d32f2f;
+ color: var(--color-danger-text);
margin-bottom: 12px;
}
.btn-retry {
padding: 10px 20px;
- background: #1976d2;
- color: white;
+ background: var(--color-info);
+ color: var(--color-on-info);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -43,13 +43,13 @@
}
.btn-retry:hover {
- background: #1565c0;
+ background: var(--color-info-dark);
}
.trash-empty {
text-align: center;
padding: 60px 20px;
- background: #f5f5f5;
+ background: var(--color-surface-alt);
border-radius: 12px;
}
@@ -60,7 +60,7 @@
}
.trash-empty p {
- color: #666;
+ color: var(--color-text-muted);
font-size: 16px;
margin: 0;
}
@@ -72,8 +72,8 @@
}
.trash-item {
- background: #fff;
- border: 2px solid #e0e0e0;
+ background: var(--color-surface);
+ border: 2px solid var(--color-border);
border-radius: 8px;
padding: 16px 20px;
display: flex;
@@ -84,7 +84,7 @@
.trash-item:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- border-color: #bdbdbd;
+ border-color: var(--color-border);
}
.trash-item-info {
@@ -93,7 +93,7 @@
.trash-item-info h3 {
margin: 0 0 8px 0;
- color: #333;
+ color: var(--color-text);
font-size: 18px;
font-weight: 600;
}
@@ -106,8 +106,8 @@
}
.trash-item-type {
- background: #e3f2fd;
- color: #1976d2;
+ background: var(--color-info-bg);
+ color: var(--color-info-text);
padding: 4px 10px;
border-radius: 4px;
font-size: 13px;
@@ -116,12 +116,12 @@
.trash-item-address,
.trash-item-phone {
- color: #666;
+ color: var(--color-text-muted);
font-size: 14px;
}
.trash-item-meta {
- color: #999;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -140,8 +140,8 @@
align-items: center;
gap: 6px;
padding: 10px 16px;
- background: #4caf50;
- color: white;
+ background: var(--color-success);
+ color: var(--color-on-success);
border: none;
border-radius: 6px;
cursor: pointer;
@@ -151,7 +151,7 @@
}
.btn-restore:hover:not(:disabled) {
- background: #45a049;
+ background: var(--color-success-dark);
transform: translateY(-1px);
}
@@ -160,7 +160,7 @@
}
.btn-restore:disabled {
- background: #bdbdbd;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
diff --git a/stoeberhunde/frontend/src/components/auth/LoginForm.css b/stoeberhunde/frontend/src/components/auth/LoginForm.css
index 1a38755..56024ab 100644
--- a/stoeberhunde/frontend/src/components/auth/LoginForm.css
+++ b/stoeberhunde/frontend/src/components/auth/LoginForm.css
@@ -56,7 +56,7 @@
width: 100%;
padding: 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
font-size: 1rem;
@@ -76,8 +76,8 @@
.login-error {
padding: 0.75rem;
- background: #ffebee;
- border: 1px solid #ffcdd2;
+ background: var(--color-danger-bg);
+ border: 1px solid var(--color-danger-border);
border-radius: var(--radius-sm);
color: var(--color-danger);
margin-bottom: 1rem;
diff --git a/stoeberhunde/frontend/src/components/auth/PasswordReset.css b/stoeberhunde/frontend/src/components/auth/PasswordReset.css
index cd3c067..4ee08d1 100644
--- a/stoeberhunde/frontend/src/components/auth/PasswordReset.css
+++ b/stoeberhunde/frontend/src/components/auth/PasswordReset.css
@@ -1,5 +1,6 @@
.password-reset-container {
- min-height: 100vh;
+ /* dvh: mit ein- und ausblendender Adressleiste entsteht mit vh Überlauf. */
+ min-height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
@@ -8,7 +9,7 @@
}
.password-reset-card {
- background: white;
+ background: var(--color-surface);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
padding: 40px;
@@ -18,7 +19,7 @@
.password-reset-card h2 {
margin: 0 0 24px 0;
- color: #333;
+ color: var(--color-text);
font-size: 28px;
text-align: center;
}
@@ -32,15 +33,15 @@
}
.message.success {
- background-color: #d4edda;
- color: #155724;
- border: 1px solid #c3e6cb;
+ background-color: var(--color-success-bg);
+ color: var(--color-success-text);
+ border: 1px solid var(--color-success-border);
}
.message.error {
- background-color: #f8d7da;
- color: #721c24;
- border: 1px solid #f5c6cb;
+ background-color: var(--color-danger-bg);
+ color: var(--color-danger-text);
+ border: 1px solid var(--color-danger-border);
}
.form-group {
@@ -50,7 +51,7 @@
.form-group label {
display: block;
margin-bottom: 8px;
- color: #555;
+ color: var(--color-text-muted);
font-weight: 500;
font-size: 14px;
}
@@ -58,7 +59,7 @@
.form-group input {
width: 100%;
padding: 12px 16px;
- border: 2px solid #e0e0e0;
+ border: 2px solid var(--color-border);
border-radius: 8px;
font-size: 15px;
transition: border-color 0.3s;
@@ -71,14 +72,14 @@
}
.form-group input:disabled {
- background-color: #f5f5f5;
+ background-color: var(--color-surface-alt);
cursor: not-allowed;
}
.form-group small {
display: block;
margin-top: 6px;
- color: #888;
+ color: var(--color-text-muted);
font-size: 13px;
}
@@ -86,7 +87,7 @@
width: 100%;
padding: 14px;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 8px;
font-size: 16px;
diff --git a/stoeberhunde/frontend/src/components/common/ErrorMessage.css b/stoeberhunde/frontend/src/components/common/ErrorMessage.css
index 38733d8..efba2ba 100644
--- a/stoeberhunde/frontend/src/components/common/ErrorMessage.css
+++ b/stoeberhunde/frontend/src/components/common/ErrorMessage.css
@@ -4,10 +4,10 @@
gap: 0.5rem;
padding: 1rem;
margin: 1rem 0;
- background-color: #fee;
- border: 1px solid #fcc;
+ background-color: var(--color-danger-bg);
+ border: 1px solid var(--color-danger-border);
border-radius: 4px;
- color: #c33;
+ color: var(--color-danger-text);
}
.error-icon {
@@ -22,7 +22,7 @@
background: none;
border: none;
font-size: 1.5rem;
- color: #c33;
+ color: var(--color-danger-text);
cursor: pointer;
padding: 0;
width: 24px;
@@ -34,5 +34,5 @@
}
.error-close:hover {
- color: #a22;
+ color: var(--color-danger-text);
}
diff --git a/stoeberhunde/frontend/src/components/common/Header.css b/stoeberhunde/frontend/src/components/common/Header.css
index 69a023f..dd3e83d 100644
--- a/stoeberhunde/frontend/src/components/common/Header.css
+++ b/stoeberhunde/frontend/src/components/common/Header.css
@@ -1,6 +1,6 @@
.app-header {
- background: #ffffff;
- border-bottom: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border-bottom: 1px solid var(--color-border);
padding: 0.75rem 2rem;
display: flex;
align-items: center;
@@ -27,7 +27,7 @@
.portal-back-link:hover {
background: var(--color-primary);
- color: #fff;
+ color: var(--color-on-primary);
}
.app-brand {
@@ -40,18 +40,18 @@
height: 52px;
width: auto;
object-fit: contain;
-}
-
-.app-logo-ljn {
- height: 44px;
+ flex-shrink: 0;
}
.app-title {
margin: 0;
+ font-family: var(--font-display);
font-size: 1.05rem;
font-weight: 700;
color: var(--color-text);
- white-space: nowrap;
+ /* Kein nowrap: lange App-Namen haben die Kopfzeile sonst über die
+ Bildschirmbreite hinaus geschoben. */
+ overflow-wrap: anywhere;
}
.app-nav {
@@ -61,11 +61,14 @@
}
.nav-button {
+ display: inline-flex;
+ align-items: center;
+ min-height: var(--touch-target);
padding: 0.5rem 0.875rem;
background: none;
border: none;
border-radius: var(--radius-sm);
- color: #333;
+ color: var(--color-text);
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
@@ -97,12 +100,19 @@
.app-header {
flex-direction: column;
align-items: flex-start;
- padding: 0.75rem 1rem;
- gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ gap: 0.4rem;
+ /* Auf schmalen Geräten nimmt die umgebrochene Kopfzeile viel Höhe ein.
+ Klebrig bleibt sie nur dort, wo genug Platz ist. */
+ position: static;
}
.app-title {
- font-size: 0.9rem;
+ font-size: 0.95rem;
+ }
+
+ .app-logo {
+ height: 36px;
}
.app-nav {
@@ -111,7 +121,31 @@
}
.nav-button {
- font-size: 0.85rem;
+ font-size: 0.9rem;
padding: 0.4rem 0.7rem;
}
}
+
+@media (max-width: 480px) {
+ .app-header {
+ padding: 0.5rem 0.75rem;
+ }
+
+ .app-brand {
+ gap: 0.5rem;
+ }
+
+ .app-logo {
+ height: 30px;
+ }
+
+ .app-nav {
+ width: 100%;
+ }
+
+ .nav-button {
+ flex: 1 1 45%;
+ justify-content: center;
+ padding: 0.4rem 0.5rem;
+ }
+}
diff --git a/stoeberhunde/frontend/src/components/common/InstallBanner.css b/stoeberhunde/frontend/src/components/common/InstallBanner.css
index f5b248d..0ab554a 100644
--- a/stoeberhunde/frontend/src/components/common/InstallBanner.css
+++ b/stoeberhunde/frontend/src/components/common/InstallBanner.css
@@ -2,8 +2,8 @@
position: sticky;
top: 0;
z-index: 1000;
- background-color: #2d6a2d;
- color: #fff;
+ background-color: var(--color-primary);
+ color: var(--color-on-primary);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
@@ -22,8 +22,8 @@
}
.install-banner__btn {
- background: #fff;
- color: #2d6a2d;
+ background: var(--color-surface);
+ color: var(--color-primary);
border: none;
border-radius: 4px;
padding: 0.35rem 0.85rem;
@@ -34,7 +34,7 @@
}
.install-banner__btn:hover {
- background: #e8f5e9;
+ background: var(--color-success-bg);
}
.install-banner__close {
@@ -49,7 +49,7 @@
}
.install-banner__close:hover {
- color: #fff;
+ color: var(--color-on-primary);
}
.install-banner__share-icon {
diff --git a/stoeberhunde/frontend/src/components/common/Loading.css b/stoeberhunde/frontend/src/components/common/Loading.css
index ec8df60..e1dbe74 100644
--- a/stoeberhunde/frontend/src/components/common/Loading.css
+++ b/stoeberhunde/frontend/src/components/common/Loading.css
@@ -8,8 +8,8 @@
}
.spinner {
- border: 4px solid #f3f3f3;
- border-top: 4px solid #3498db;
+ border: 4px solid var(--color-border);
+ border-top: 4px solid var(--color-primary);
border-radius: 50%;
width: 50px;
height: 50px;
@@ -23,6 +23,6 @@
.loading-message {
margin-top: 1rem;
- color: #666;
+ color: var(--color-text-muted);
font-size: 0.9rem;
}
diff --git a/stoeberhunde/frontend/src/components/map/MapView.css b/stoeberhunde/frontend/src/components/map/MapView.css
index bfb9cff..6e82ee3 100644
--- a/stoeberhunde/frontend/src/components/map/MapView.css
+++ b/stoeberhunde/frontend/src/components/map/MapView.css
@@ -13,32 +13,32 @@
left: 12px;
z-index: 500;
background: rgba(255, 255, 255, 0.95);
- color: #444;
+ color: var(--color-text-muted);
padding: 0.45rem 0.7rem;
border-radius: 6px;
font-size: 0.85rem;
- border: 1px solid #dcdcdc;
+ border: 1px solid var(--color-border);
}
.map-no-data {
padding: 3rem;
text-align: center;
- color: #666;
- background: white;
+ color: var(--color-text-muted);
+ background: var(--color-surface);
border-radius: 8px;
margin: 1rem 0;
}
.map-popup h3 {
margin: 0 0 0.5rem 0;
- color: #333;
+ color: var(--color-text);
font-size: 1rem;
}
.map-popup p {
margin: 0.25rem 0;
font-size: 0.85rem;
- color: #666;
+ color: var(--color-text-muted);
}
.map-popup a {
@@ -54,8 +54,40 @@
display: inline-block;
padding: 0.2rem 0.5rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border-radius: 4px;
font-size: 0.75rem;
margin-top: 0.5rem;
}
+
+/* ── Nachtansicht ────────────────────────────────────────────────────────
+ Die OSM-Kacheln sind immer taghell. In der Dämmerung ist die Karte damit
+ die mit Abstand hellste Fläche der App und blendet — genau die Situation,
+ in der Nachsuchen stattfinden. Die Kacheln werden deshalb abgedunkelt;
+ Marker und Bedienelemente bleiben unangetastet, damit sie lesbar sind. */
+@media (prefers-color-scheme: dark) {
+ .leaflet-tile-pane {
+ filter: brightness(0.62) saturate(0.75) contrast(1.05);
+ }
+
+ .leaflet-container {
+ background: var(--color-surface-alt);
+ }
+
+ /* Hoehere Spezifitaet als Leaflets eigene Regeln, die spaeter geladen werden */
+ .leaflet-container .leaflet-control-zoom a,
+ .leaflet-container .leaflet-control-attribution {
+ background: var(--color-surface);
+ color: var(--color-text);
+ }
+
+ .leaflet-container .leaflet-control-attribution a {
+ color: var(--color-primary);
+ }
+
+ .leaflet-popup-content-wrapper,
+ .leaflet-popup-tip {
+ background: var(--color-surface);
+ color: var(--color-text);
+ }
+}
diff --git a/stoeberhunde/frontend/src/components/public/PublicUserList.css b/stoeberhunde/frontend/src/components/public/PublicUserList.css
index c24d538..55233f6 100644
--- a/stoeberhunde/frontend/src/components/public/PublicUserList.css
+++ b/stoeberhunde/frontend/src/components/public/PublicUserList.css
@@ -14,7 +14,7 @@
}
.public-user-list h2 {
- color: #1a1a1a;
+ color: var(--color-text);
margin: 0;
font-size: 1.5rem;
font-weight: 700;
@@ -23,7 +23,7 @@
.toggle-map-button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -44,8 +44,8 @@
.filter-toggle-button {
padding: 0.5rem 1rem;
- background: #6c757d;
- color: white;
+ background: var(--color-secondary);
+ color: var(--color-on-secondary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -55,12 +55,12 @@
}
.filter-toggle-button:hover {
- background: #5a6268;
+ background: var(--color-secondary-dark);
}
.location-panel {
- background: white;
- border: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1rem 1.5rem;
margin-bottom: 1.5rem;
@@ -78,7 +78,7 @@
.location-button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -92,7 +92,7 @@
}
.location-button:disabled {
- background: #b6b6b6;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
@@ -103,13 +103,13 @@
}
.location-status.success {
- background: #e8f5e9;
- color: var(--color-primary-dark);
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
}
.location-status.error {
- background: #ffebee;
- color: #c62828;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
}
.postal-search {
@@ -120,21 +120,21 @@
.postal-search input[type="text"] {
padding: 0.5rem;
- border: 1px solid #ddd;
+ border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 0.9rem;
width: 150px;
}
.postal-search input[type="text"]:disabled {
- background: #f5f5f5;
+ background: var(--color-surface-alt);
cursor: not-allowed;
}
.postal-search button {
padding: 0.5rem 1rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 4px;
cursor: pointer;
@@ -148,14 +148,14 @@
}
.postal-search button:disabled {
- background: #b6b6b6;
+ background: var(--color-border-strong);
cursor: not-allowed;
}
.radius-filter label {
display: block;
font-size: 0.9rem;
- color: #555;
+ color: var(--color-text-muted);
margin-bottom: 0.5rem;
font-weight: 500;
}
@@ -174,26 +174,26 @@
.radius-inputs input[type="number"] {
width: 80px;
padding: 0.4rem 0.5rem;
- border: 1px solid #ddd;
+ border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 0.9rem;
}
.radius-inputs input:disabled {
- background: #f5f5f5;
+ background: var(--color-surface-alt);
cursor: not-allowed;
}
.radius-hint {
font-size: 0.85rem;
- color: #777;
+ color: var(--color-text-muted);
margin-top: 0.5rem;
}
.gps-hint {
margin-top: 0.5rem;
font-size: 0.85rem;
- color: #777;
+ color: var(--color-text-muted);
}
.user-grid {
@@ -205,8 +205,8 @@
/* Jägerschaft-style card */
.user-card {
- background: white;
- border: 1px solid #e5e5e5;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
@@ -232,9 +232,9 @@
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
}
-.user-name {
+.public-user-list .user-name {
margin: 0 0 0.2rem;
- color: #1a1a1a;
+ color: var(--color-text);
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
@@ -250,15 +250,15 @@
color: var(--color-primary);
}
-.user-info {
+.public-user-list .user-info {
display: flex;
flex-direction: column;
gap: 0.375rem;
}
-.user-address {
+.public-user-list .user-address {
margin: 0;
- color: #666;
+ color: var(--color-text-muted);
font-size: 0.9rem;
}
@@ -266,72 +266,80 @@
margin: 0.5rem 0 0;
}
-.type-badge {
+.public-user-list .type-badge {
display: inline-block;
padding: 0.2rem 0.6rem;
- background: #f0f0f0;
- color: #444;
+ background: var(--color-surface-alt);
+ color: var(--color-text-muted);
border-radius: 4px;
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.03em;
}
+/* Der Anruf beim Stöberhundeführer ist der Zweck dieser Liste und wird fast
+ immer mit dem Daumen auf dem Handy ausgelöst. Vorher war das ein 14 px hoher
+ Textlink; jetzt ein vollwertiges Ziel mit der empfohlenen Mindesthöhe. */
.user-phone {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ min-height: var(--touch-target);
+ margin: 0.15rem 0;
+ padding: 0.35rem 0.6rem;
+ background: var(--color-surface-alt);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-sm);
color: var(--color-primary);
text-decoration: none;
- font-weight: 500;
- font-size: 0.9rem;
+ font-weight: 600;
+ font-size: 1rem;
}
-.user-phone:hover {
+.public-user-list .user-phone:hover,
+.public-user-list .user-phone:focus-visible {
+ background: var(--color-surface);
+ border-color: var(--color-border-strong);
text-decoration: underline;
}
-.user-gps {
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid #e5e5e5;
- font-size: 0.85rem;
- color: #888;
-}
.user-distance {
margin-top: 0.75rem;
padding-top: 0.75rem;
- border-top: 1px solid #e5e5e5;
+ border-top: 1px solid var(--color-border);
font-size: 0.85rem;
- color: #555;
+ color: var(--color-text-muted);
font-weight: 500;
}
.no-users {
text-align: center;
padding: 3rem;
- color: #666;
+ color: var(--color-text-muted);
}
.loading {
text-align: center;
padding: 3rem;
- color: #666;
+ color: var(--color-text-muted);
}
@media (max-width: 768px) {
- .user-grid {
+.user-grid {
grid-template-columns: 1fr;
}
- .public-user-list {
+.public-user-list {
padding: 1rem;
}
- .radius-inputs {
+.radius-inputs {
flex-direction: column;
align-items: stretch;
}
- .radius-inputs input[type="number"] {
+.radius-inputs input[type="number"] {
width: 100%;
}
}
diff --git a/stoeberhunde/frontend/src/components/public/RulesDisplay.css b/stoeberhunde/frontend/src/components/public/RulesDisplay.css
index 32be9b6..4ec7a73 100644
--- a/stoeberhunde/frontend/src/components/public/RulesDisplay.css
+++ b/stoeberhunde/frontend/src/components/public/RulesDisplay.css
@@ -33,7 +33,7 @@
}
.allgemeines-tab-btn.active {
- background: white;
+ background: var(--color-surface);
color: var(--color-primary);
font-weight: 700;
border-color: var(--color-primary);
@@ -41,7 +41,7 @@
}
.allgemeines-content {
- background: white;
+ background: var(--color-surface);
border: 1px solid var(--color-primary);
border-top: none;
border-radius: 0 0 8px 8px;
diff --git a/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerDashboard.css b/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerDashboard.css
index 643a941..fee5347 100644
--- a/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerDashboard.css
+++ b/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerDashboard.css
@@ -5,7 +5,7 @@
}
.stoeberhundefuehrer-dashboard-card {
- background: white;
+ background: var(--color-surface);
border-radius: 10px;
padding: 2rem;
width: 100%;
@@ -46,7 +46,7 @@
.btn-stoeberhundefuehrer-logout:hover {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.stoeberhundefuehrer-message {
@@ -56,8 +56,8 @@
font-size: 0.9rem;
}
-.stoeberhundefuehrer-message-success { background: #dcfce7; color: #166534; }
-.stoeberhundefuehrer-message-error { background: #fee2e2; color: #b91c1c; }
+.stoeberhundefuehrer-message-success { background: var(--color-success-bg); color: var(--color-success-text); }
+.stoeberhundefuehrer-message-error { background: var(--color-danger-bg); color: var(--color-danger-text); }
.stoeberhundefuehrer-availability-section {
background: var(--color-muted-bg);
@@ -92,15 +92,15 @@
.availability-big-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-green {
- background: #dcfce7;
- color: #15803d;
- border-color: #86efac;
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
+ border-color: var(--color-success-border);
}
.btn-red {
- background: #fee2e2;
- color: #b91c1c;
- border-color: #fca5a5;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
+ border-color: var(--color-danger-border);
}
.status-dot-lg {
@@ -110,8 +110,8 @@
flex-shrink: 0;
}
-.dot-green { background: #22c55e; }
-.dot-red { background: #ef4444; }
+.dot-green { background: var(--color-success); }
+.dot-red { background: var(--color-danger); }
.availability-hint {
font-size: 0.82rem;
@@ -147,7 +147,7 @@
font-size: 0.9rem;
}
-.btn-stoeberhundefuehrer-edit:hover { background: var(--color-primary); color: white; }
+.btn-stoeberhundefuehrer-edit:hover { background: var(--color-primary); color: var(--color-on-primary); }
.stoeberhundefuehrer-info-list { display: flex; flex-direction: column; gap: 0.6rem; }
@@ -206,7 +206,7 @@
flex: 1;
padding: 0.65rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 6px;
font-size: 0.95rem;
diff --git a/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerLogin.css b/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerLogin.css
index 3068103..2cb0f68 100644
--- a/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerLogin.css
+++ b/stoeberhunde/frontend/src/components/stoeberhundefuehrer/StoeberhundefuehrerLogin.css
@@ -6,7 +6,7 @@
}
.stoeberhundefuehrer-login-card {
- background: white;
+ background: var(--color-surface);
border-radius: 10px;
padding: 2rem;
width: 100%;
@@ -48,7 +48,7 @@
.stoeberhundefuehrer-mode-toggle button.active {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
font-weight: 600;
}
@@ -82,7 +82,7 @@
width: 100%;
padding: 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: 6px;
font-size: 1rem;
@@ -102,8 +102,8 @@
}
.stoeberhundefuehrer-error {
- background: #fee2e2;
- color: #b91c1c;
+ background: var(--color-danger-bg);
+ color: var(--color-danger-text);
border-radius: 4px;
padding: 0.6rem 0.9rem;
margin-bottom: 1rem;
@@ -111,8 +111,8 @@
}
.stoeberhundefuehrer-success {
- background: #dcfce7;
- color: #166534;
+ background: var(--color-success-bg);
+ color: var(--color-success-text);
border-radius: 4px;
padding: 0.6rem 0.9rem;
margin-bottom: 1rem;
diff --git a/stoeberhunde/frontend/src/components/users/UserCard.css b/stoeberhunde/frontend/src/components/users/UserCard.css
index a6f6bb7..2c62fa9 100644
--- a/stoeberhunde/frontend/src/components/users/UserCard.css
+++ b/stoeberhunde/frontend/src/components/users/UserCard.css
@@ -25,7 +25,7 @@
border-bottom: 1px solid var(--color-border);
}
-.user-name-row {
+.user-card-admin .user-name-row {
display: flex;
align-items: center;
gap: 0.5rem;
@@ -39,10 +39,10 @@
box-shadow: 0 0 4px rgba(0,0,0,0.2);
}
-.dot-green { background: #22c55e; }
-.dot-red { background: #ef4444; }
+.dot-green { background: var(--color-success); }
+.dot-red { background: var(--color-danger); }
-.user-name {
+.user-card-admin .user-name {
margin: 0;
color: var(--color-text);
font-size: 1.2rem;
@@ -67,40 +67,40 @@
font-weight: 600;
}
-.label-green { color: #16a34a; }
-.label-red { color: var(--color-danger); }
+.label-green { color: var(--color-success); }
+.label-red { color: var(--color-danger); }
-.user-info {
+.user-card-admin .user-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
-.user-address {
+.user-card-admin .user-address {
margin: 0;
color: var(--color-text-muted);
font-size: 0.9rem;
}
-.type-badge {
+.user-card-admin .type-badge {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border-radius: var(--radius-pill);
font-size: 0.85rem;
font-weight: 500;
}
-.user-phone {
+.user-card-admin .user-phone {
color: var(--color-primary);
text-decoration: none;
font-weight: 500;
font-size: 1rem;
}
-.user-phone:hover {
+.user-card-admin .user-phone:hover {
text-decoration: underline;
}
@@ -183,7 +183,7 @@
.edit-gps-button {
padding: 0.25rem 0.75rem;
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
@@ -229,7 +229,7 @@
.save-gps-button {
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
}
.save-gps-button:hover:not(:disabled) {
@@ -243,7 +243,7 @@
.cancel-gps-button {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.cancel-gps-button:hover {
@@ -272,7 +272,7 @@
.edit-button {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.edit-button:hover {
@@ -281,7 +281,7 @@
.delete-button {
background: var(--color-danger);
- color: white;
+ color: var(--color-on-danger);
}
.delete-button:hover {
@@ -289,17 +289,17 @@
}
@media (max-width: 768px) {
- .user-header {
+.user-header {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}
- .gps-inputs {
+.gps-inputs {
flex-direction: column;
}
- .card-actions {
+.card-actions {
flex-direction: column;
}
}
@@ -322,7 +322,7 @@
display: block;
margin-top: 0.35rem;
padding: 0.4rem 0.5rem;
- background: var(--color-bg-muted, #f2f2ec);
+ background: var(--color-surface-alt);
border: 1px solid var(--color-border);
border-radius: 2px;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
diff --git a/stoeberhunde/frontend/src/components/users/UserForm.css b/stoeberhunde/frontend/src/components/users/UserForm.css
index 474c2a3..e3e62df 100644
--- a/stoeberhunde/frontend/src/components/users/UserForm.css
+++ b/stoeberhunde/frontend/src/components/users/UserForm.css
@@ -91,7 +91,7 @@
top: 100%;
left: 0;
right: 0;
- background: white;
+ background: var(--color-surface);
border: 1px solid var(--color-border-strong);
border-top: none;
border-radius: 0 0 var(--radius-sm) var(--radius-sm);
@@ -163,7 +163,7 @@
.btn-primary {
background: var(--color-primary);
- color: white;
+ color: var(--color-on-primary);
}
.btn-primary:hover {
@@ -172,7 +172,7 @@
.btn-secondary {
background: var(--color-secondary);
- color: white;
+ color: var(--color-on-secondary);
}
.btn-secondary:hover {
diff --git a/stoeberhunde/frontend/src/components/users/UserList.css b/stoeberhunde/frontend/src/components/users/UserList.css
index 4dd50f4..03ceb1a 100644
--- a/stoeberhunde/frontend/src/components/users/UserList.css
+++ b/stoeberhunde/frontend/src/components/users/UserList.css
@@ -34,7 +34,7 @@
.create-button {
padding: 0.5rem 1rem;
background: var(--color-success);
- color: white;
+ color: var(--color-on-success);
border: none;
border-radius: var(--radius-sm);
cursor: pointer;
diff --git a/stoeberhunde/frontend/src/index.css b/stoeberhunde/frontend/src/index.css
index ec2585e..a76866f 100644
--- a/stoeberhunde/frontend/src/index.css
+++ b/stoeberhunde/frontend/src/index.css
@@ -1,13 +1,8 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
+/* Basisstile stehen in App.css, wo auch die Design-Tokens definiert sind.
+ Hier stand vorher eine zweite body-Regel, die von App.css vollständig
+ überschrieben wurde. */
+html {
+ /* Verhindert, dass iOS beim Drehen die Schrift eigenmächtig vergrößert. */
+ -webkit-text-size-adjust: 100%;
+ text-size-adjust: 100%;
}