feat(design): Bildsprache des Portals übernehmen, Nachtansicht ergänzen

Die visuelle Ebene war bisher nie geprüft. Zwei Entscheidungen lagen dem
zugrunde: die Apps folgen der Bildsprache des Portals, und es gibt eine
Nachtansicht über prefers-color-scheme — Nachsuchen finden in der
Dämmerung und nachts statt, ein weißes Vollbild blendet dann.

Design-Tokens (App.css ist jetzt die einzige Farbquelle):
- Palette, Georgia-Serif für die Überschriftenebene und die kantigen
  2px-Ecken vom Portal übernommen; Sans bleibt für funktionale UI-Texte,
  wie es das Portal ebenfalls handhabt.
- Aktionsfarben haben jetzt eine zugehörige --color-on-*-Textfarbe. Ohne
  das wäre in der Nachtansicht weißer Text auf hellgrünem Grund gelandet.
- 307 fest verdrahtete Farbwerte pro App auf Tokens umgestellt,
  eigenschafts-abhängig (color/background/border getrennt). Das Schlüssel-
  wort "white" war dabei der gefährlichste Fall: als Textfarbe auf einer
  Vollton-Fläche musste es zu --color-on-* werden, als Fläche zu
  --color-surface.
- theme-color war dreifach verschieden (#2d6a2d gehörte zu keiner der
  beiden Paletten); Portal und alle Apps nutzen jetzt einen Wert.

Behobene Kontrastfehler (alle nachgerechnet, nicht geschätzt):
- .btn-success 3,13:1 und .btn-primary 4,33:1 lagen unter AA — der
  Hauptaktionsbutton der gesamten Anwendung.
- Feldrahmen 2,27:1 und Kartenrahmen 1,60:1 (Soll 3,0 für Bedienelemente).
- .badge-restore 3,46:1 und .badge-password 2,49:1 im Audit-Log.
Geprüft: 36 Paare in hell UND dunkel, 0 Verstöße.

Weitere visuelle Befunde:
- .type-badge war in PublicUserList.css und UserCard.css doppelt
  definiert. CSS ist global, die Admin-Variante gewann — die öffentliche
  Liste zeigte die falsche Badge-Optik. Fünf solcher Kollisionen zwischen
  öffentlicher Liste und Admin-Karte sind jetzt auf ihren Container
  eingegrenzt.
- Formularfelder hatten keine Hintergrundfarbe und nahmen den Browser-
  Standard: in der Nachtansicht leuchtete jedes Eingabefeld weiß. Fiel
  erst im Screenshot auf.
- Die Kartenkacheln sind immer taghell und waren nachts die mit Abstand
  hellste Fläche. Sie werden jetzt abgedunkelt, Marker bleiben hell.
- Die Badge-Definitionen im Audit-Log standen doppelt in derselben Datei
  (8 Regeln, identische Werte).

Mobiltauglichkeit:
- .user-phone war ein 14 px hoher Textlink — der tel:-Link ist der Zweck
  der öffentlichen Liste. Jetzt ein Ziel mit 44 px Mindesthöhe.
- Kopfzeile: Logo verkleinert, .app-title umbricht statt nowrap,
  Navigationsschaltflächen auf 44 px, Breakpoint für ≤480px ergänzt,
  auf schmalen Geräten nicht mehr klebend.
- 100vh -> 100dvh (Adressleiste erzeugte sonst Überlauf).
- :focus-visible für Buttons; prefers-reduced-motion respektiert.
- Geprüft mit Screenshots bei 360 px und 768 px, hell und dunkel:
  kein horizontaler Überlauf.

Aufgeräumt:
- logo-fallingbostel.png und logo-ljn.png entfernt: 898 KB pro App, von
  keiner Zeile Code referenziert, 60 % der Buildgröße und fast doppelt so
  groß wie der gesamte Anwendungscode. Build 1,5 MB -> 632 KB.
- Tote Stile (.login-prompt, .btn-success, .panel, .user-gps u. a.),
  doppelte body-Regel in index.css, Variablentippfehler --color-bg-muted.
- Die Offline-Seite der Apps war lang="en" und ungestaltet — genau die
  Seite, die im Funkloch erscheint. Jetzt gestaltet, deutsch, mit
  Nachtansicht, für Portal und Apps identisch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
thomas 2026-08-25 19:43:57 +02:00
parent f4939ef6c5
commit dd39a7aff2
78 changed files with 2242 additions and 1382 deletions

View File

@ -5,7 +5,7 @@
<link rel="icon" href="%BASE_URL%icons/icon-192.png" />
<link rel="apple-touch-icon" href="%BASE_URL%icons/icon-192.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2d6a2d" />
<meta name="theme-color" content="#1a3d1a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="Drohnenführer" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 KiB

View File

@ -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"
}

View File

@ -1,16 +1,93 @@
<!DOCTYPE html>
<html lang="en">
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Offline - Drohnenführer</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
h1 { color: #333; }
</style>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#1a3d1a" />
<title>Offline Jagd Apps Heidekreis</title>
<style>
/* Eigenständige Seite: sie wird vom Service Worker ausgeliefert, wenn das
Netz fehlt, und kann deshalb keine Stylesheets der App nachladen.
Palette und Schriftmodell entsprechen dem Portal, inklusive Nachtansicht. */
* { box-sizing: border-box; }
:root {
--bg: #e8e8e2;
--card: #f4f4ee;
--text: #1a1a1a;
--muted: #55554c;
--border: #c9c9b8;
--green: #2d5a2d;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #14180f;
--card: #1e241a;
--text: #e9e7dd;
--muted: #a6a698;
--border: #333b28;
--green: #7fb36f;
}
}
body {
margin: 0;
min-height: 100dvh;
padding: 2rem 1.25rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
text-align: center;
}
.card {
max-width: 26rem;
padding: 2rem 1.5rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 2px;
}
.icon { font-size: 3rem; line-height: 1; margin-bottom: 1rem; }
h1 {
margin: 0 0 0.5rem;
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.5rem;
color: var(--text);
}
p { margin: 0 0 1.5rem; color: var(--muted); font-size: 1rem; line-height: 1.5; }
button {
min-height: 44px;
padding: 0.6rem 1.4rem;
background: var(--green);
color: var(--bg);
border: none;
border-radius: 2px;
font: inherit;
font-weight: 600;
cursor: pointer;
}
button:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
</style>
</head>
<body>
<h1>Du bist offline</h1>
<p>Die App ist derzeit nicht verfügbar. Bitte überprüfe deine Internetverbindung.</p>
<div class="card">
<div class="icon" role="img" aria-label="Kein Empfang">📡</div>
<h1>Keine Verbindung</h1>
<p>
Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
Sobald wieder Empfang besteht, lädt die Seite normal.
</p>
<button type="button" onclick="location.reload()">Erneut versuchen</button>
</div>
</body>
</html>

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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); }
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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%;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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%;
}

View File

@ -5,7 +5,7 @@
<link rel="icon" href="%BASE_URL%icons/icon-192.png" />
<link rel="apple-touch-icon" href="%BASE_URL%icons/icon-192.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2d6a2d" />
<meta name="theme-color" content="#1a3d1a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="NSS Heidekreis" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 KiB

View File

@ -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"
}

View File

@ -1,16 +1,93 @@
<!DOCTYPE html>
<html lang="en">
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Offline - Nachsuchenführer</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
h1 { color: #333; }
</style>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#1a3d1a" />
<title>Offline Jagd Apps Heidekreis</title>
<style>
/* Eigenständige Seite: sie wird vom Service Worker ausgeliefert, wenn das
Netz fehlt, und kann deshalb keine Stylesheets der App nachladen.
Palette und Schriftmodell entsprechen dem Portal, inklusive Nachtansicht. */
* { box-sizing: border-box; }
:root {
--bg: #e8e8e2;
--card: #f4f4ee;
--text: #1a1a1a;
--muted: #55554c;
--border: #c9c9b8;
--green: #2d5a2d;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #14180f;
--card: #1e241a;
--text: #e9e7dd;
--muted: #a6a698;
--border: #333b28;
--green: #7fb36f;
}
}
body {
margin: 0;
min-height: 100dvh;
padding: 2rem 1.25rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
text-align: center;
}
.card {
max-width: 26rem;
padding: 2rem 1.5rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 2px;
}
.icon { font-size: 3rem; line-height: 1; margin-bottom: 1rem; }
h1 {
margin: 0 0 0.5rem;
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.5rem;
color: var(--text);
}
p { margin: 0 0 1.5rem; color: var(--muted); font-size: 1rem; line-height: 1.5; }
button {
min-height: 44px;
padding: 0.6rem 1.4rem;
background: var(--green);
color: var(--bg);
border: none;
border-radius: 2px;
font: inherit;
font-weight: 600;
cursor: pointer;
}
button:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
</style>
</head>
<body>
<h1>Du bist offline</h1>
<p>Die App ist derzeit nicht verfügbar. Bitte überprüfe deine Internetverbindung.</p>
<div class="card">
<div class="icon" role="img" aria-label="Kein Empfang">📡</div>
<h1>Keine Verbindung</h1>
<p>
Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
Sobald wieder Empfang besteht, lädt die Seite normal.
</p>
<button type="button" onclick="location.reload()">Erneut versuchen</button>
</div>
</body>
</html>

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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); }
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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%;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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%;
}

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2d6a2d" />
<meta name="theme-color" content="#1a3d1a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="Jagd Apps" />

View File

@ -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"
}

View File

@ -3,29 +3,91 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Offline Jagd Apps</title>
<meta name="theme-color" content="#1a3d1a" />
<title>Offline Jagd Apps Heidekreis</title>
<style>
/* Eigenständige Seite: sie wird vom Service Worker ausgeliefert, wenn das
Netz fehlt, und kann deshalb keine Stylesheets der App nachladen.
Palette und Schriftmodell entsprechen dem Portal, inklusive Nachtansicht. */
* { box-sizing: border-box; }
:root {
--bg: #e8e8e2;
--card: #f4f4ee;
--text: #1a1a1a;
--muted: #55554c;
--border: #c9c9b8;
--green: #2d5a2d;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #14180f;
--card: #1e241a;
--text: #e9e7dd;
--muted: #a6a698;
--border: #333b28;
--green: #7fb36f;
}
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #f5f5f0;
min-height: 100dvh;
padding: 2rem 1.25rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 2rem;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
text-align: center;
}
.icon { font-size: 3rem; margin-bottom: 1rem; }
h1 { color: #1a1a1a; font-size: 1.5rem; margin: 0 0 0.5rem; }
p { color: #555; font-size: 1rem; }
.card {
max-width: 26rem;
padding: 2rem 1.5rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 2px;
}
.icon { font-size: 3rem; line-height: 1; margin-bottom: 1rem; }
h1 {
margin: 0 0 0.5rem;
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.5rem;
color: var(--text);
}
p { margin: 0 0 1.5rem; color: var(--muted); font-size: 1rem; line-height: 1.5; }
button {
min-height: 44px;
padding: 0.6rem 1.4rem;
background: var(--green);
color: var(--bg);
border: none;
border-radius: 2px;
font: inherit;
font-weight: 600;
cursor: pointer;
}
button:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
</style>
</head>
<body>
<div class="icon">📡</div>
<h1>Keine Verbindung</h1>
<p>Bitte prüfen Sie Ihre Internetverbindung und laden Sie die Seite neu.</p>
<div class="card">
<div class="icon" role="img" aria-label="Kein Empfang">📡</div>
<h1>Keine Verbindung</h1>
<p>
Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
Sobald wieder Empfang besteht, lädt die Seite normal.
</p>
<button type="button" onclick="location.reload()">Erneut versuchen</button>
</div>
</body>
</html>

View File

@ -5,7 +5,7 @@
<link rel="icon" href="%BASE_URL%icons/icon-192.png" />
<link rel="apple-touch-icon" href="%BASE_URL%icons/icon-192.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2d6a2d" />
<meta name="theme-color" content="#1a3d1a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="Stöberhunde" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 KiB

View File

@ -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"
}

View File

@ -1,16 +1,93 @@
<!DOCTYPE html>
<html lang="en">
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Offline - Stöberhundeführer</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
h1 { color: #333; }
</style>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#1a3d1a" />
<title>Offline Jagd Apps Heidekreis</title>
<style>
/* Eigenständige Seite: sie wird vom Service Worker ausgeliefert, wenn das
Netz fehlt, und kann deshalb keine Stylesheets der App nachladen.
Palette und Schriftmodell entsprechen dem Portal, inklusive Nachtansicht. */
* { box-sizing: border-box; }
:root {
--bg: #e8e8e2;
--card: #f4f4ee;
--text: #1a1a1a;
--muted: #55554c;
--border: #c9c9b8;
--green: #2d5a2d;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #14180f;
--card: #1e241a;
--text: #e9e7dd;
--muted: #a6a698;
--border: #333b28;
--green: #7fb36f;
}
}
body {
margin: 0;
min-height: 100dvh;
padding: 2rem 1.25rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
text-align: center;
}
.card {
max-width: 26rem;
padding: 2rem 1.5rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 2px;
}
.icon { font-size: 3rem; line-height: 1; margin-bottom: 1rem; }
h1 {
margin: 0 0 0.5rem;
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.5rem;
color: var(--text);
}
p { margin: 0 0 1.5rem; color: var(--muted); font-size: 1rem; line-height: 1.5; }
button {
min-height: 44px;
padding: 0.6rem 1.4rem;
background: var(--green);
color: var(--bg);
border: none;
border-radius: 2px;
font: inherit;
font-weight: 600;
cursor: pointer;
}
button:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
</style>
</head>
<body>
<h1>Du bist offline</h1>
<p>Die App ist derzeit nicht verfügbar. Bitte überprüfe deine Internetverbindung.</p>
<div class="card">
<div class="icon" role="img" aria-label="Kein Empfang">📡</div>
<h1>Keine Verbindung</h1>
<p>
Im Funkloch sind die zuletzt geladenen Daten nicht verfügbar.
Sobald wieder Empfang besteht, lädt die Seite normal.
</p>
<button type="button" onclick="location.reload()">Erneut versuchen</button>
</div>
</body>
</html>

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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); }
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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%;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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%;
}