/** * Modul: Liquid Glass - Shell Components (Phase 1–3) * Zweck: Glass-Effekte für Navigation, Modal, Buttons, FAB, Animationen * Rein additiv: überschreibt nur optische Eigenschaften, * keine Layout-, Größen- oder Funktionsänderungen. * Abhängigkeiten: tokens.css (Section 16 Glass-Tokens), layout.css * * Architektur: * Nicht-Blur-Stile (background, border, shadow) sind AUSSERHALB von * @supports gesetzt → wirken auf allen Geräten und Browsern. * Blur-Filter (backdrop-filter) sind INNERHALB von @supports mit * webkit-Fallback → greifen wenn vom Browser unterstützt. * @supports-Check: (backdrop-filter) OR (-webkit-backdrop-filter) * deckt Safari < 18 (nur webkit-Prefix) und moderne Browser ab. */ /* ================================================================ * 1. Bottom Navigation — Glass Bar * ================================================================ */ /* Immer aktiv: Glass-Hintergrund, Border, Shadow */ .nav-bottom { background-color: var(--glass-bg); border-top: 1px solid var(--glass-border); box-shadow: var(--glass-shadow-sm); } /* Blur nur wenn unterstützt (webkit-Fallback für Safari < 18) */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .nav-bottom { backdrop-filter: var(--blur-md) saturate(180%); -webkit-backdrop-filter: var(--blur-md) saturate(180%); } } /* Active-State: Glass-Kapsel hinter aktivem Nav-Item */ .nav-item[aria-current="page"] { background: color-mix(in srgb, var(--active-module-accent, var(--color-accent)) 14%, transparent); border-radius: var(--radius-glass-chip); box-shadow: inset 0 1px 0 var(--glass-highlight-subtle); } /* Hover-State auf Desktop */ @media (hover: hover) { .nav-item:hover:not([aria-current="page"]) { background: color-mix(in srgb, var(--color-text-tertiary) 8%, transparent); border-radius: var(--radius-glass-chip); } } /* ================================================================ * 2. Sidebar (Desktop ≥ 1024px) — Glass Panel * ================================================================ */ @media (min-width: 1024px) { .nav-sidebar { background: var(--glass-bg-elevated); border-right: 1px solid var(--glass-border); box-shadow: var(--glass-shadow-md); } @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .nav-sidebar { backdrop-filter: var(--blur-sm) saturate(160%); -webkit-backdrop-filter: var(--blur-sm) saturate(160%); } } /* Active-State in Sidebar */ .nav-sidebar .nav-item[aria-current="page"] { background: color-mix(in srgb, var(--active-module-accent, var(--color-accent)) 12%, transparent); border-radius: var(--radius-sm); box-shadow: inset 0 1px 0 var(--glass-highlight-subtle); } } /* ================================================================ * 3. Modal — Glass Overlay + Glass Panel * ================================================================ */ /* Immer aktiv: stärkerer Schatten und Glass-Border */ .modal-panel { border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow-lg); } .modal-panel__header { border-bottom-color: var(--glass-border); } /* Blur nur wenn unterstützt */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .modal-overlay { background-color: var(--color-overlay-glass); backdrop-filter: var(--blur-xs) saturate(120%); -webkit-backdrop-filter: var(--blur-xs) saturate(120%); } .modal-panel { background: var(--glass-bg-elevated); backdrop-filter: var(--blur-sm); -webkit-backdrop-filter: var(--blur-sm); } .modal-panel__header { background: var(--glass-bg-elevated); } } /* Bottom-Sheet Handle */ @media (max-width: 767px) { @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .modal-panel::before { background: var(--glass-border); } } } /* ================================================================ * 4. Buttons — Capsule Shape + Specular Highlight * ================================================================ */ .btn--primary { border-radius: var(--radius-glass-button); box-shadow: var(--shadow-sm), var(--glass-inset-medium); } .btn--primary:hover { box-shadow: var(--shadow-md), var(--glass-inset-soft); } .btn--secondary { border-radius: var(--radius-glass-button); } /* Ghost-Buttons */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .btn--ghost:hover { background: color-mix(in srgb, var(--color-text-tertiary) 10%, transparent); backdrop-filter: var(--blur-xs); -webkit-backdrop-filter: var(--blur-xs); } } /* ================================================================ * 5. FAB — Specular Highlight * ================================================================ */ .fab { box-shadow: var(--shadow-lg), var(--glass-inset-elevated), var(--glass-inset-bottom-base); } .fab:hover { box-shadow: var(--shadow-lg), var(--glass-inset-strong), var(--glass-inset-bottom-hover); } /* ================================================================ * 6. Cards — Glass auf hover (nur interaktive Cards) * ================================================================ */ @media (hover: hover) { .card--interactive:hover { border: 1px solid var(--glass-border-subtle); box-shadow: var(--glass-shadow-md); } @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .card--interactive:hover { background: var(--glass-bg-hover); backdrop-filter: var(--blur-xs); -webkit-backdrop-filter: var(--blur-xs); } } } /* ================================================================ * 7. Accessibility Overrides — Phase 1 * ================================================================ */ @media (prefers-reduced-transparency: reduce) { .nav-item[aria-current="page"], .nav-item:hover:not([aria-current="page"]) { box-shadow: none; } .btn--primary, .btn--primary:hover, .fab, .fab:hover { box-shadow: var(--shadow-sm); } } @media (prefers-reduced-motion: reduce) { .nav-item, .nav-sidebar .nav-item, .btn, .fab, .card--interactive { transition-duration: 0.01ms !important; } } /* ================================================================ * PHASE 2 — Modul-Komponenten * ================================================================ */ /* ================================================================ * 8. Form-Inputs — Glass Border + verbesserter Focus-Ring * ================================================================ */ .input, .form-input, select.form-input, textarea.form-input { border-color: var(--glass-border-subtle); background-color: color-mix(in srgb, var(--color-surface) 95%, transparent); } .input:focus, .form-input:focus { border-color: var(--color-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent), var(--glass-inset-input); } /* ================================================================ * 9. Toasts — Glass + Capsule * ================================================================ */ .toast { border-radius: var(--radius-glass-card); box-shadow: var(--glass-shadow-md); } @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .toast:not(.toast--success):not(.toast--danger):not(.toast--warning) { background-color: color-mix(in srgb, var(--neutral-800) 90%, transparent); backdrop-filter: var(--blur-sm); -webkit-backdrop-filter: var(--blur-sm); border: 1px solid var(--glass-border-overlay); } } .toast--success, .toast--danger, .toast--warning { border-radius: var(--radius-glass-card); box-shadow: var(--glass-shadow-md), var(--glass-inset-soft); } /* ================================================================ * 10. Filter-Chips — Glass Border (immer aktiv) * Aktiver Glass-State: direkt in tasks.css (Load-Order-Konflikt) * ================================================================ */ .filter-chip { border-color: var(--glass-border-subtle); } .filter-chip:hover:not(.filter-chip--active) { border-color: var(--glass-border); background-color: color-mix(in srgb, var(--color-text-tertiary) 8%, transparent); } /* ================================================================ * 11. Priority Badges — Capsule + Glass Border * Immer aktiv (kein backdrop-filter nötig) * ================================================================ */ .nav-badge { box-shadow: var(--glass-inset-base); } /* ================================================================ * 12. Toggle-Switch — Specular Thumb * ================================================================ */ .toggle__track::after { box-shadow: var(--shadow-sm), var(--glass-inset-thumb); } .toggle input:checked + .toggle__track::after { transition: transform var(--transition-glass); } /* ================================================================ * 13. FAB-Backdrop (Dashboard) — Glass Blur * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .fab-backdrop--visible { backdrop-filter: var(--blur-xs); -webkit-backdrop-filter: var(--blur-xs); background: var(--color-backdrop-glass); } } /* ================================================================ * 14. Dashboard-Widgets — Glass Cards * Glass-Styles direkt in dashboard.css (Load-Order-Konflikt) * ================================================================ */ /* ================================================================ * 15. Modal-Inputs * ================================================================ */ .modal-panel .form-input, .modal-panel .input { background-color: var(--color-surface-2); } /* ================================================================ * 16. Accessibility — Phase 2 * ================================================================ */ @media (prefers-reduced-transparency: reduce) { .filter-chip--active, .toast:not(.toast--success):not(.toast--danger):not(.toast--warning) { background-color: var(--color-accent-light); border-color: var(--color-accent); backdrop-filter: none; -webkit-backdrop-filter: none; } } @media (prefers-reduced-motion: reduce) { .toggle__track::after { transition: none; } .toast { animation-duration: 0.01ms !important; } } /* ================================================================ * PHASE 3 — Micro-Interactions + Polish * ================================================================ */ /* ================================================================ * 17. Bottom-Nav Auto-Hide on Scroll * ================================================================ */ .nav-bottom { margin-bottom: 0; transition: transform var(--transition-base) var(--ease-out), margin-bottom var(--transition-base) var(--ease-out), background-color var(--transition-fast), box-shadow var(--transition-fast); /* will-change: transform absichtlich weggelassen - auf iOS (WebKit) korrumpiert die * dauerhafte GPU-Layer-Promotion eines position:relative Flex-Kinds dessen Position. */ } .nav-bottom--hidden { transform: translateY(100%); margin-bottom: calc(-1 * (var(--nav-height-mobile))); pointer-events: none; } /* ================================================================ * 18. Modal-Entrance — Glass Spring * ================================================================ */ @keyframes glass-modal-scale-in { from { opacity: 0; transform: scale(0.90) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } } @keyframes glass-sheet-in { from { opacity: 0.6; transform: translateY(40%); } to { opacity: 1; transform: translateY(0); } } @media (min-width: 768px) { .modal-panel { animation: glass-modal-scale-in 0.32s var(--ease-glass) forwards; } } @media (max-width: 767px) { .modal-panel { animation: glass-sheet-in 0.30s var(--ease-glass) forwards; } } /* ================================================================ * 19. Seitentransitionen — Spring Easing * ================================================================ */ .page-transition--in-right, .page-transition--in-left { animation-duration: 0.20s; animation-timing-function: var(--ease-glass); } .page-transition--out-left, .page-transition--out-right { animation-duration: 0.12s; animation-timing-function: var(--ease-out); } /* Performance: backdrop-filter deaktivieren während Seitenübergängen. * Auf Android verursachen viele gleichzeitige backdrop-filter-Layer * (Widgets, Cards, Inputs) hohen GPU-Aufwand → Transition wirkt träge. * html.navigating wird von router.js für die Dauer des Übergangs gesetzt. */ html.navigating .app-content *, html.navigating .app-content *::before, html.navigating .app-content *::after { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; } /* ================================================================ * 20. List-Stagger — Spring Timing * ================================================================ */ .list-stagger > * { animation-duration: 0.28s; animation-timing-function: var(--ease-glass); } /* ================================================================ * 21. Focus-Ring — Scale-In Animation * ================================================================ */ :focus-visible { transition: box-shadow var(--transition-fast), outline-offset var(--transition-fast); outline-offset: 3px; } /* ================================================================ * 22. Skeleton Shimmer — Glass Shimmer * ================================================================ */ .skeleton { background: linear-gradient( 105deg, var(--color-border-subtle) 0%, var(--color-border-subtle) 30%, color-mix(in srgb, var(--color-surface) 90%, var(--glass-highlight)) 50%, var(--color-border-subtle) 70%, var(--color-border-subtle) 100% ); background-size: 250% 100%; } /* ================================================================ * 23. FAB — Attention Pulse * ================================================================ */ @keyframes fab-ring-pulse { 0% { box-shadow: var(--shadow-lg), var(--glass-inset-elevated), 0 0 0 0 color-mix(in srgb, var(--module-accent, var(--color-btn-primary)) 50%, transparent); } 60% { box-shadow: var(--shadow-lg), var(--glass-inset-elevated), 0 0 0 10px transparent; } 100% { box-shadow: var(--shadow-lg), var(--glass-inset-elevated), 0 0 0 0 transparent; } } .fab { animation: fab-in 0.35s var(--ease-out) backwards, fab-ring-pulse 0.6s var(--ease-out) 0.4s 1 backwards; } /* ================================================================ * 24. Accessibility — Phase 3 * ================================================================ */ @media (prefers-reduced-motion: reduce) { .nav-bottom { transition: none; } .nav-bottom--hidden { transition: none; } .modal-panel { animation: none; } .page-transition--in-right, .page-transition--in-left, .page-transition--out-left, .page-transition--out-right { animation-duration: 0.01ms !important; } .list-stagger > * { animation-duration: 0.01ms !important; } .fab { animation: none; } } /* ================================================================ * PHASE 4 — Liquid Glass Vibrancy + Tint * ================================================================ */ /* ================================================================ * 25. Widget Cards — Glass Vibrancy * * Widgets bekommen transparente Hintergruende mit Blur, * sodass darunterliegender Content durchscheint. * Tint: subtile Tonung durch Modul-Akzentfarbe. * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { /* .dashboard Eltern-Selektor fuer Spezifitaet (Load-Order: glass.css < dashboard.css) */ .dashboard .widget { background-color: var(--glass-bg-card); backdrop-filter: var(--blur-sm) saturate(180%); -webkit-backdrop-filter: var(--blur-sm) saturate(180%); } .dashboard .widget:hover { background-color: var(--glass-bg-card-hover); } /* Modul-Tint: subtiler Farbverlauf durch Akzentfarbe */ .dashboard .widget::after { content: ''; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient( 135deg, color-mix(in srgb, var(--module-accent, var(--color-accent)) var(--glass-tint-strength), transparent), transparent 70% ); pointer-events: none; z-index: 0; } } /* ================================================================ * 26. Greeting-Widget — Glass + Vibrancy auf Gradient * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .widget-greeting { backdrop-filter: var(--blur-xs) saturate(200%); -webkit-backdrop-filter: var(--blur-xs) saturate(200%); } /* Greeting braucht keinen separaten Tint - hat eigenen Gradient */ .widget-greeting::after { display: none; } } /* ================================================================ * 27. Wetter-Widget — Vibrancy auf Gradient * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .weather-widget { backdrop-filter: var(--blur-xs) saturate(200%); -webkit-backdrop-filter: var(--blur-xs) saturate(200%); } .weather-widget::after { display: none; } } /* ================================================================ * 28. Page-Toolbars — Glass Bar mit Tint * * Modul-Header/Toolbars als Glass-Elemente mit * Modul-Akzentfarbe als dezenter Tint. * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { /* Eltern-Selektoren fuer Spezifitaet */ .tasks-page .tasks-toolbar, .notes-page .notes-toolbar, .contacts-page .contacts-toolbar, .calendar-page .cal-toolbar { background-color: var(--glass-bg-toolbar); backdrop-filter: var(--blur-sm) saturate(160%); -webkit-backdrop-filter: var(--blur-sm) saturate(160%); border-top: 3px solid var(--module-accent); border-bottom: 1px solid var(--glass-border-subtle); padding-left: var(--space-4); padding-right: var(--space-4); } } /* ================================================================ * 29. Note-Items — Glass Cards * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .notes-page .note-item, .dashboard .note-item { background-color: var(--glass-bg-card); backdrop-filter: var(--blur-xs) saturate(150%); -webkit-backdrop-filter: var(--blur-xs) saturate(150%); border: 1px solid var(--glass-border-subtle); box-shadow: var(--glass-shadow-sm); } .notes-page .note-item:hover, .dashboard .note-item:hover { background-color: var(--glass-bg-card-hover); box-shadow: var(--glass-shadow-md); } } /* ================================================================ * 30. Meal-Slots — Glass Grid-Zellen * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .dashboard .meal-slot, .meals-page .meal-slot { background-color: var(--glass-bg-card); backdrop-filter: var(--blur-xs) saturate(140%); -webkit-backdrop-filter: var(--blur-xs) saturate(140%); } .dashboard .meal-slot:hover, .meals-page .meal-slot:hover { background-color: var(--glass-bg-card-hover); } .dashboard .meal-slot--filled, .meals-page .meal-slot--filled { background-color: color-mix(in srgb, var(--module-accent, var(--module-meals)) 4%, var(--glass-bg-card)); } } /* ================================================================ * 31. Form-Inputs — Glass Vibrancy * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .input, .form-input, select.form-input, textarea.form-input { background-color: var(--glass-bg-input); backdrop-filter: var(--blur-xs) saturate(120%); -webkit-backdrop-filter: var(--blur-xs) saturate(120%); } } /* ================================================================ * 32. List-Items — Subtile Glass-Trennung * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { /* Eltern-Selektoren fuer Spezifitaet (glass.css < page CSS) */ .tasks-page .task-card { background-color: var(--glass-bg-card); backdrop-filter: var(--blur-xs) saturate(150%); -webkit-backdrop-filter: var(--blur-xs) saturate(150%); } .tasks-page .task-card:hover { background-color: color-mix(in srgb, var(--module-accent, var(--color-accent)) 4%, var(--glass-bg-card-hover)); } .shopping-page .shopping-item:hover, .contacts-page .contact-item:hover { background-color: color-mix(in srgb, var(--module-accent, var(--color-accent)) 4%, var(--glass-bg-card-hover)); border-radius: var(--radius-sm); } } /* ================================================================ * 33. Group-Toggle / Filter-Chips — Glass Segmented Control * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .group-toggle { background-color: var(--glass-bg-input); backdrop-filter: var(--blur-xs) saturate(140%); -webkit-backdrop-filter: var(--blur-xs) saturate(140%); border: 1px solid var(--glass-border-subtle); } .group-toggle__btn--active { background-color: var(--glass-bg-elevated); box-shadow: var(--glass-shadow-sm); } } /* ================================================================ * 34. FAB Speed-Dial Actions — Glass Labels + Buttons * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .fab-action__label { background-color: var(--glass-bg-elevated); backdrop-filter: var(--blur-sm) saturate(160%); -webkit-backdrop-filter: var(--blur-sm) saturate(160%); border: 1px solid var(--glass-border-subtle); box-shadow: var(--glass-shadow-md); } .fab-action__btn { background-color: var(--glass-bg-elevated); backdrop-filter: var(--blur-sm) saturate(160%); -webkit-backdrop-filter: var(--blur-sm) saturate(160%); border: 1px solid var(--glass-border-subtle); } } /* ================================================================ * 35. App-Content-Hintergrund — Vibrancy-Basis * * Subtiler Gradient im Seitenhintergrund damit Glass- * Elemente darauf lebendiger wirken. * ================================================================ */ .app-content { background: radial-gradient( ellipse at 20% 0%, color-mix(in srgb, var(--module-accent, var(--color-accent)) 3%, transparent), transparent 60% ), var(--color-bg); } /* ================================================================ * 36. Skeleton — Glass Shimmer Update * ================================================================ */ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) { .widget-skeleton { background-color: var(--glass-bg-card); backdrop-filter: var(--blur-xs) saturate(140%); -webkit-backdrop-filter: var(--blur-xs) saturate(140%); border: 1px solid var(--glass-border-subtle); } } /* ================================================================ * 37. Accessibility — Phase 4 * ================================================================ */ @media (prefers-reduced-transparency: reduce) { .dashboard .widget, .tasks-page .task-card, .notes-page .note-item, .dashboard .note-item, .dashboard .meal-slot, .meals-page .meal-slot, .widget-skeleton { background-color: var(--color-surface); backdrop-filter: none; -webkit-backdrop-filter: none; } .dashboard .widget::after { display: none; } .app-content { background: var(--color-bg); } .group-toggle, .fab-action__label, .fab-action__btn { backdrop-filter: none; -webkit-backdrop-filter: none; } .input, .form-input, select.form-input, textarea.form-input { backdrop-filter: none; -webkit-backdrop-filter: none; } .tasks-page .tasks-toolbar, .notes-page .notes-toolbar, .contacts-page .contacts-toolbar, .calendar-page .cal-toolbar { background-color: var(--color-surface); backdrop-filter: none; -webkit-backdrop-filter: none; } }