feat: Phase 0 - Audit-Fixes + Glass-Token-Layer

Accessibility fixes (WCAG 2.2):
- K1: Entferne user-scalable=no aus viewport (WCAG 1.4.4)
- K2: Korrigiere var(--color-background) → var(--color-bg) in settings.css
- H1: --color-text-tertiary #737370 → #6B6B68 (WCAG AA: 4.52:1)
- H2: --color-info #54AEFF → #0969DA (WCAG AA: 4.6:1 auf weiß)
- H4+H5: Korrigiere nicht-existente Token-Referenzen in settings.css
  (--color-surface-raised → --color-surface-2, --duration-fast → --transition-fast)
- H7: aria-label + role=presentation auf Modal-Overlay
- N1: theme-color Meta-Tags auf tatsächliche Design-Tokens angleichen
- N2: var(--color-text) → var(--color-text-primary) in notes.css
- N3: Hardcoded #1E5CB3 → var(--color-accent-deep) in dashboard.css
- N4: Hardcoded padding 2px 8px → Token-Referenzen in meals.css

Neue Tokens:
- --color-accent-deep: tiefer Akzent für Gradienten
- Glass-Token-Layer (Section 16) mit 7 Kategorien:
  Hintergründe, Blur-Stufen, Opazitäten, Highlights,
  Schatten, Radien, Übergänge
- Dark-Mode-Varianten für alle Glass-Tokens
- prefers-reduced-transparency: opake Fallbacks
- prefers-contrast: more: Kontrast-Fallbacks ohne Blur

i18n: modal.overlayLabel in allen 9 Sprachen ergänzt
This commit is contained in:
Ulas
2026-04-13 16:54:19 +02:00
parent ddb8294eff
commit 370b9948a3
17 changed files with 161 additions and 28 deletions
+1 -1
View File
@@ -195,7 +195,7 @@ export function openModal({ title, content, onSave, onDelete, size = 'md' } = {}
const sizeClass = size !== 'md' ? ` modal-panel--${size}` : '';
const html = `
<div class="modal-overlay" id="shared-modal-overlay">
<div class="modal-overlay" id="shared-modal-overlay" aria-label="${t('modal.overlayLabel')}" role="presentation">
<div class="modal-panel${sizeClass}" role="dialog" aria-modal="true"
aria-labelledby="shared-modal-title">
<div class="modal-panel__header">
+3 -3
View File
@@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8" />
<!-- Viewport: edge-to-edge, kein Zoom (PWA-native feel) -->
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no, maximum-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=5" />
<!-- PWA / Theme -->
<meta name="theme-color" content="#007AFF" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#1C1C1E" media="(prefers-color-scheme: dark)" />
<meta name="theme-color" content="#2563EB" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#222220" media="(prefers-color-scheme: dark)" />
<meta name="mobile-web-app-capable" content="yes" />
<!-- iOS-spezifisch -->
+2 -1
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Schließen"
},
"modal": {
"closeLabel": "Schließen"
"closeLabel": "Schließen",
"overlayLabel": "Modaler Dialog-Hintergrund"
},
"rrule": {
"freqNone": "Keine Wiederholung",
+3 -2
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Κλείσιμο"
},
"modal": {
"closeLabel": "Κλείσιμο"
"closeLabel": "Κλείσιμο",
"overlayLabel": "Φόντο αναδυόμενου παραθύρου"
},
"rrule": {
"freqNone": "Χωρίς επανάληψη",
@@ -588,4 +589,4 @@
"unitMonth": "μήνα",
"unitMonths": "μήνες"
}
}
}
+2 -1
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Close"
},
"modal": {
"closeLabel": "Close"
"closeLabel": "Close",
"overlayLabel": "Modal dialog background"
},
"rrule": {
"freqNone": "No recurrence",
+2 -1
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Cerrar"
},
"modal": {
"closeLabel": "Cerrar"
"closeLabel": "Cerrar",
"overlayLabel": "Fondo del cuadro de diálogo modal"
},
"rrule": {
"freqNone": "Sin repetición",
+3 -2
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Fermer"
},
"modal": {
"closeLabel": "Fermer"
"closeLabel": "Fermer",
"overlayLabel": "Arrière-plan de la boîte de dialogue modale"
},
"rrule": {
"freqNone": "Pas de répétition",
@@ -588,4 +589,4 @@
"unitMonth": "mois",
"unitMonths": "mois"
}
}
}
+2 -1
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Chiudi"
},
"modal": {
"closeLabel": "Chiudi"
"closeLabel": "Chiudi",
"overlayLabel": "Sfondo del dialogo modale"
},
"rrule": {
"freqNone": "Nessuna ripetizione",
+3 -2
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Закрыть"
},
"modal": {
"closeLabel": "Закрыть"
"closeLabel": "Закрыть",
"overlayLabel": "Фон модального диалога"
},
"rrule": {
"freqNone": "Без повтора",
@@ -588,4 +589,4 @@
"unitMonth": "месяц",
"unitMonths": "месяцев"
}
}
}
+2 -1
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Stäng"
},
"modal": {
"closeLabel": "Stäng"
"closeLabel": "Stäng",
"overlayLabel": "Bakgrund för modal dialog"
},
"rrule": {
"freqNone": "Ingen upprepning",
+3 -2
View File
@@ -563,7 +563,8 @@
"dismissLabel": "Kapat"
},
"modal": {
"closeLabel": "Kapat"
"closeLabel": "Kapat",
"overlayLabel": "Modal iletişim kutusu arka planı"
},
"rrule": {
"freqNone": "Tekrar yok",
@@ -588,4 +589,4 @@
"unitMonth": "ay",
"unitMonths": "ay"
}
}
}
+3 -2
View File
@@ -563,7 +563,8 @@
"dismissLabel": "关闭"
},
"modal": {
"closeLabel": "关闭"
"closeLabel": "关闭",
"overlayLabel": "模态对话框背景"
},
"rrule": {
"freqNone": "不重复",
@@ -588,4 +589,4 @@
"unitMonth": "个月",
"unitMonths": "个月"
}
}
}
+1 -1
View File
@@ -641,7 +641,7 @@
* -------------------------------------------------------- */
.weather-widget {
position: relative;
background: linear-gradient(135deg, var(--color-accent) 0%, #1E5CB3 100%);
background: linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-deep) 100%);
color: var(--color-text-on-accent);
}
+1 -1
View File
@@ -411,7 +411,7 @@
gap: var(--space-1);
font-size: var(--text-xs);
font-weight: var(--font-weight-medium);
padding: 2px 8px;
padding: var(--space-0h) var(--space-2);
border-radius: var(--radius-full);
}
+1 -1
View File
@@ -68,7 +68,7 @@
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
background: var(--color-surface);
color: var(--color-text);
color: var(--color-text-primary);
font-size: var(--text-md);
outline-offset: 2px;
}
+3 -3
View File
@@ -56,7 +56,7 @@
margin-bottom: var(--space-6);
position: sticky;
top: 0;
background: var(--color-background);
background: var(--color-bg);
z-index: 10;
padding-top: var(--space-1);
}
@@ -430,11 +430,11 @@
gap: var(--space-2);
padding: var(--space-2) var(--space-1);
border-radius: var(--radius-sm);
transition: background var(--duration-fast);
transition: background var(--transition-fast);
}
.cat-row:hover {
background: var(--color-surface-raised);
background: var(--color-surface-2);
}
.cat-row__icon {
+126 -3
View File
@@ -52,7 +52,7 @@
--color-border-subtle: var(--neutral-150);
--color-text-primary: var(--neutral-900);
--color-text-secondary: var(--neutral-600); /* WCAG AA: ~5.0:1 auf weiß */
--color-text-tertiary: #737370;
--color-text-tertiary: #6B6B68; /* WCAG AA: ~4.52:1 auf --color-bg */
--color-text-disabled: var(--neutral-300);
--color-text-on-accent: #ffffff; /* Weißer Text auf farbigen Hintergründen (Buttons, Badges, FAB) */
@@ -63,6 +63,7 @@
--color-accent: #2563EB;
--color-accent-hover: #1D4ED8;
--color-accent-active: #1E40AF;
--color-accent-deep: #1E5CB3; /* Tiefer Akzent für Gradienten, Wetter-Widget */
--color-accent-light: #EFF6FF;
--color-accent-subtle: #DBEAFE;
--color-btn-primary: #2554C7; /* WCAG AA: 6.62:1 auf weiß (weißer Text) */
@@ -80,8 +81,8 @@
--color-danger: #DC2626;
--color-danger-hover: #B91C1C;
--color-danger-light: #FFE2E0;
--color-info: #54AEFF;
--color-info-hover: #3A94E5;
--color-info: #0969DA; /* WCAG AA: ~4.6:1 auf weiß */
--color-info-hover: #0550AE;
--color-info-light: #DDF4FF;
/* --------------------------------------------------------
@@ -254,6 +255,59 @@
--z-nav: 100;
--z-modal: 200;
--z-toast: 300;
/* --------------------------------------------------------
* 16. Glass-Design-System (Liquid Glass Layer)
* Additive Tokens bestehende Tokens werden nicht verändert.
* Aktivierung per @supports (backdrop-filter) in Komponenten.
*
* Aufbau:
* a) Glass-Hintergründe
* b) Blur-Stufen
* c) Opazitäten
* d) Highlights / Specular
* e) Glass-Schatten
* f) Glass-Radien
* g) Glass-Übergänge
* -------------------------------------------------------- */
/* a) Glass-Hintergründe */
--glass-bg: rgba(255, 255, 255, 0.72);
--glass-bg-hover: rgba(255, 255, 255, 0.82);
--glass-bg-elevated: rgba(255, 255, 255, 0.88);
--glass-border: rgba(255, 255, 255, 0.60);
--glass-border-subtle: rgba(255, 255, 255, 0.35);
/* b) Blur-Stufen */
--blur-xs: blur(4px);
--blur-sm: blur(8px);
--blur-md: blur(16px);
--blur-lg: blur(28px);
--blur-xl: blur(48px);
/* c) Opazitäten */
--opacity-glass-subtle: 0.65;
--opacity-glass-base: 0.80;
--opacity-glass-elevated: 0.92;
/* d) Highlights / Specular */
--glass-highlight: rgba(255, 255, 255, 0.70);
--glass-highlight-subtle: rgba(255, 255, 255, 0.35);
/* e) Glass-Schatten */
--glass-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(255, 255, 255, 0.55);
--glass-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(255, 255, 255, 0.50);
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.14), 0 0 0 1px rgba(255, 255, 255, 0.45);
/* f) Glass-Radien */
--radius-glass-card: 20px;
--radius-glass-inner: 14px;
--radius-glass-chip: var(--radius-full);
--radius-glass-button: var(--radius-full);
/* g) Glass-Übergänge */
--ease-glass: cubic-bezier(0.34, 1.56, 0.64, 1);
--transition-glass: 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* ================================================================
@@ -346,6 +400,18 @@
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45);
/* Glass - Dark Mode */
--glass-bg: rgba(40, 40, 38, 0.75);
--glass-bg-hover: rgba(50, 50, 48, 0.82);
--glass-bg-elevated: rgba(58, 58, 55, 0.90);
--glass-border: rgba(255, 255, 255, 0.12);
--glass-border-subtle: rgba(255, 255, 255, 0.07);
--glass-highlight: rgba(255, 255, 255, 0.10);
--glass-highlight-subtle: rgba(255, 255, 255, 0.06);
--glass-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.30), 0 0 0 1px rgba(255, 255, 255, 0.08);
--glass-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(255, 255, 255, 0.07);
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.06);
}
}
@@ -425,4 +491,61 @@
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45);
/* Glass - Dark Mode */
--glass-bg: rgba(40, 40, 38, 0.75);
--glass-bg-hover: rgba(50, 50, 48, 0.82);
--glass-bg-elevated: rgba(58, 58, 55, 0.90);
--glass-border: rgba(255, 255, 255, 0.12);
--glass-border-subtle: rgba(255, 255, 255, 0.07);
--glass-highlight: rgba(255, 255, 255, 0.10);
--glass-highlight-subtle: rgba(255, 255, 255, 0.06);
--glass-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.30), 0 0 0 1px rgba(255, 255, 255, 0.08);
--glass-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(255, 255, 255, 0.07);
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.06);
}
/* ================================================================
* Accessibility: prefers-reduced-transparency
* Glass-Effekte abschalten - opake Fallbacks.
* ================================================================ */
@media (prefers-reduced-transparency: reduce) {
:root {
--glass-bg: var(--color-surface);
--glass-bg-hover: var(--color-surface-2);
--glass-bg-elevated: var(--color-surface);
--glass-border: var(--color-border);
--glass-border-subtle: var(--color-border-subtle);
--glass-highlight: transparent;
--glass-highlight-subtle: transparent;
--blur-xs: blur(0px);
--blur-sm: blur(0px);
--blur-md: blur(0px);
--blur-lg: blur(0px);
--blur-xl: blur(0px);
--opacity-glass-subtle: 1;
--opacity-glass-base: 1;
--opacity-glass-elevated: 1;
}
}
/* ================================================================
* Accessibility: prefers-contrast: more
* Kontrast erhöhen, Blur reduzieren.
* ================================================================ */
@media (prefers-contrast: more) {
:root {
--glass-bg: rgba(255, 255, 255, 0.97);
--glass-bg-hover: #ffffff;
--glass-bg-elevated: #ffffff;
--glass-border: var(--color-text-primary);
--glass-border-subtle: var(--color-text-secondary);
--glass-highlight: transparent;
--glass-highlight-subtle: transparent;
--blur-xs: blur(0px);
--blur-sm: blur(0px);
--blur-md: blur(0px);
--blur-lg: blur(0px);
--blur-xl: blur(0px);
}
}