* { 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 { /* Sagt dem Browser, dass die Seite beide Ansichten kann. Native Bedienelemente — Checkboxen, Auswahllisten, Bildlaufleisten — passen sich dadurch an, statt in der Nachtansicht hell aufzublitzen. */ color-scheme: light dark; --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: #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); } /* 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; } /* Checkbox, Radio und Schieberegler in der Markenfarbe statt im Browser-Blau. */ input[type="checkbox"], input[type="radio"], input[type="range"] { accent-color: var(--color-primary); } 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; transition: background 0.2s, box-shadow 0.2s, transform 0.2s; } .btn:disabled { 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: var(--color-on-primary); } .btn-primary:hover:not(:disabled) { background: var(--color-primary-dark); transform: translateY(-1px); } .btn-secondary { background: var(--color-secondary); color: var(--color-on-secondary); } .btn-secondary:hover:not(:disabled) { background: var(--color-secondary-dark); transform: translateY(-1px); } .btn-danger { background: var(--color-danger); color: var(--color-on-danger); } .btn-danger:hover:not(:disabled) { background: var(--color-danger-dark); transform: translateY(-1px); } .input, .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; } .input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--color-primary); box-shadow: 0 0 0 3px var(--color-focus); } .panel-title { margin: 0 0 var(--space-2); font-family: var(--font-display); font-size: 1.1rem; color: var(--color-text); } /* ── Grundgerüst ────────────────────────────────────────────────────────── */ .App { /* dvh statt vh: mit ein- und ausblendender Adressleiste auf Mobilgeräten entsteht mit vh sonst Überlauf. */ min-height: 100dvh; display: flex; flex-direction: column; } .app-main { flex: 1; padding: 0; } .app-loading { display: flex; justify-content: center; align-items: center; min-height: 100dvh; font-size: 1.2rem; color: var(--color-text-muted); } /* 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; } .btn:hover:not(:disabled), .btn-primary:hover:not(:disabled), .btn-secondary:hover:not(:disabled), .btn-danger:hover:not(:disabled) { transform: none; } }