jagd-apps/stoeberhunde/frontend/src/App.css

335 lines
9.4 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

* {
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;
}
}