/** * Modul: Layout * Zweck: App-Shell-Layout, Navigation (Bottom Mobile / Sidebar Desktop), Responsive Grid * Abhängigkeiten: tokens.css, reset.css * * Navigation: * Mobile (<1024px): Bottom-Nav-Bar, 5 Haupt-Module * Desktop (1024–1279px): Collapsed Sidebar, nur Icons (56px) * Wide Desktop (≥1280px): Expanded Sidebar mit Labels (220px) * * Referenz: Apple HIG Sidebar-Pattern */ /* -------------------------------------------------------- * App-Shell * -------------------------------------------------------- */ .app-shell { display: flex; flex-direction: column; min-height: 100dvh; } /* -------------------------------------------------------- * Loading-Screen * -------------------------------------------------------- */ .app-loading { display: flex; align-items: center; justify-content: center; min-height: 100dvh; background-color: var(--color-bg); } .app-loading__logo { font-size: var(--text-2xl); font-weight: var(--font-weight-bold); color: var(--color-accent); animation: pulse 1.5s ease-in-out infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* -------------------------------------------------------- * Seiten-Übergangs-Animation (direktional) * -------------------------------------------------------- */ @keyframes page-slide-in-right { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } } @keyframes page-slide-in-left { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } } @keyframes page-out-left { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(-20px); } } @keyframes page-out-right { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(20px); } } .page-transition--in-right { animation: page-slide-in-right 0.2s var(--ease-out) forwards; } .page-transition--in-left { animation: page-slide-in-left 0.2s var(--ease-out) forwards; } .page-transition--out-left { animation: page-out-left 0.12s ease forwards; pointer-events: none; } .page-transition--out-right { animation: page-out-right 0.12s ease forwards; pointer-events: none; } @media (prefers-reduced-motion: reduce) { .page-transition--in-right, .page-transition--in-left { animation: none; opacity: 1; } .page-transition--out-left, .page-transition--out-right { animation: none; } } /* -------------------------------------------------------- * Layout: Mobile (Standard, < 1024px) * -------------------------------------------------------- */ .app-content { flex: 1; padding-bottom: calc(var(--nav-height-mobile) + 12px + var(--safe-area-inset-bottom)); overflow-y: auto; } /* Sidebar auf Mobile verstecken */ .nav-sidebar { display: none; } /* -------------------------------------------------------- * Bottom Navigation (Mobil + Tablet) * * Kompakte Bar: 56px Höhe, Icons 22px, Labels 11px. * Leichter Blur-Effekt für Glassmorphismus. * -------------------------------------------------------- */ .nav-bottom { position: fixed; bottom: 0; left: 0; right: 0; background-color: color-mix(in srgb, var(--color-surface) 85%, transparent); border-top: 1px solid var(--color-border-subtle); display: flex; flex-direction: column; z-index: var(--z-nav); backdrop-filter: blur(16px) saturate(180%); -webkit-backdrop-filter: blur(16px) saturate(180%); padding-bottom: var(--safe-area-inset-bottom); } /* ── Dot-Indikator ── */ .nav-bottom__dots { display: flex; justify-content: center; gap: 6px; padding: 5px 0 2px; } .nav-bottom__dot { width: 5px; height: 5px; border-radius: 50%; background-color: var(--color-text-tertiary); opacity: 0.25; transition: opacity 0.2s ease, transform 0.2s ease; } .nav-bottom__dot--active { opacity: 0.7; transform: scale(1.2); } /* ── Scroll-Container ── */ .nav-bottom__scroll { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; /* Firefox */ height: var(--nav-height-mobile); } .nav-bottom__scroll::-webkit-scrollbar { display: none; /* Chrome/Safari */ } /* ── Einzelne Seiten ── */ .nav-bottom__page { display: flex; min-width: 100%; flex-shrink: 0; scroll-snap-align: start; } /* ── Nav-Item (Bottom-Bar): Basis-State ── */ .nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: var(--space-1) var(--space-1); color: var(--color-text-tertiary); transition: color var(--transition-fast); -webkit-tap-highlight-color: transparent; min-height: var(--target-lg); min-width: var(--target-lg); text-decoration: none; } .nav-item:active { transform: scale(0.92); } /* ── Nav-Item: Aktiv ── */ .nav-item[aria-current="page"] { color: var(--color-accent); } .nav-item__icon { width: 22px; height: 22px; flex-shrink: 0; } .nav-item__label { font-size: var(--text-xs); font-weight: var(--font-weight-medium); line-height: 1; } /* -------------------------------------------------------- * Page FAB — Schwebender Erstellen-Button (alle Breakpoints) * * Einheitlicher runder Plus-Button auf allen Unterseiten. * Mobile: über der Bottom-Nav. Desktop: unten rechts im Content. * Toolbar-"Neu"-Buttons werden überall versteckt. * -------------------------------------------------------- */ .page-fab { position: fixed; bottom: calc(var(--nav-height-mobile) + 24px + var(--safe-area-inset-bottom)); right: var(--space-4); width: 52px; height: 52px; border-radius: var(--radius-full); background-color: var(--module-accent, var(--color-accent)); color: #ffffff; box-shadow: var(--shadow-lg); display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; z-index: calc(var(--z-nav) - 1); transition: transform var(--transition-base), background-color var(--transition-fast); -webkit-tap-highlight-color: transparent; } .page-fab:hover { background-color: color-mix(in srgb, var(--module-accent, var(--color-accent)) 85%, black); } .page-fab:active { transform: scale(0.92); } /* Desktop: FAB Position anpassen (keine Bottom-Nav) und etwas kleiner */ @media (min-width: 1024px) { .page-fab { bottom: var(--space-8); right: var(--space-8); width: 48px; height: 48px; } } /* Toolbar-"Neu"-Buttons überall verstecken — FAB übernimmt */ #btn-new-task, #notes-add-btn, #contacts-add-btn, #budget-add, #cal-add { display: none !important; } /* ================================================================ * Sidebar Navigation — Desktop (≥ 1024px) * * Design: Flach, kein Neumorphismus. Dezenter Seitenrand. * Aktiver State: Hintergrund-Highlight + Akzentstreifen links. * Hover: Subtile Hintergrundfarbe, kein Shadow. * ================================================================ */ @media (min-width: 1024px) { .app-shell { flex-direction: row; } .app-content { flex: 1; padding-bottom: 0; margin-left: var(--sidebar-width); transition: margin-left var(--transition-slow); } .nav-bottom { display: none; } /* ── Sidebar anzeigen ── */ .nav-sidebar { display: flex; position: fixed; top: 0; left: 0; bottom: 0; width: var(--sidebar-width); background: var(--sidebar-bg); border-right: 1px solid var(--color-border-subtle); flex-direction: column; z-index: var(--z-nav); padding: var(--space-4) 0 var(--space-4); transition: width var(--transition-slow); overflow: hidden; } /* ── Logo: Icon-only bei collapsed ── */ .nav-sidebar__logo { display: flex; justify-content: center; align-items: center; padding: var(--space-2) 0 var(--space-4); margin-bottom: var(--space-1); flex-shrink: 0; } /* App-Icon als kompaktes Logo */ .nav-sidebar__logo::before { content: 'O'; width: 32px; height: 32px; border-radius: var(--radius-sm); background: linear-gradient(135deg, var(--color-accent) 0%, #7C5CFC 100%); color: #ffffff; font-size: var(--text-sm); font-weight: var(--font-weight-bold); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } /* Logo-Text verstecken im collapsed-Modus */ .nav-sidebar__logo > span { display: none; } /* ── Nav-Items Container ── */ .nav-sidebar__items { display: flex; flex-direction: column; gap: var(--space-0h); padding: 0 var(--space-2); flex: 1; overflow-y: auto; scrollbar-width: none; } .nav-sidebar__items::-webkit-scrollbar { display: none; } /* ── Nav-Item: Sidebar-Basis ── */ .nav-sidebar .nav-item { flex-direction: row; justify-content: center; align-items: center; border-radius: var(--radius-sm); padding: 8px var(--space-2); gap: 0; min-height: var(--target-lg); font-size: var(--text-sm); color: var(--color-text-secondary); background: transparent; transition: color var(--transition-fast), background-color var(--transition-fast); position: relative; } .nav-sidebar .nav-item__icon { width: 20px; height: 20px; flex-shrink: 0; } .nav-sidebar .nav-item__label { display: none; font-size: var(--text-sm); font-weight: var(--font-weight-medium); white-space: nowrap; overflow: hidden; } /* ── Hover: dezente Hintergrundfarbe ── */ .nav-sidebar .nav-item:hover:not([aria-current="page"]) { color: var(--color-text-primary); background-color: var(--color-surface-3); } /* ── Aktiv: Hintergrund-Highlight + Akzent-Indikator ── */ .nav-sidebar .nav-item[aria-current="page"] { color: var(--color-accent); font-weight: var(--font-weight-semibold); background-color: var(--color-accent-light); } /* Akzentstreifen links */ .nav-sidebar .nav-item[aria-current="page"]::before { content: ''; position: absolute; left: 0; top: 6px; bottom: 6px; width: 3px; border-radius: 0 var(--radius-full) var(--radius-full) 0; background: var(--color-accent); } /* Active-Press auf Desktop */ .nav-sidebar .nav-item:active { transform: scale(0.97); } /* ── Einstellungen ans Ende ── */ .nav-sidebar__items > a:last-child { margin-top: auto; } } /* ================================================================ * Sidebar Expanded (≥ 1280px) — Labels sichtbar * ================================================================ */ @media (min-width: 1280px) { :root { --sidebar-width: var(--sidebar-width-expanded); } /* Logo: Text-Variante */ .nav-sidebar__logo { justify-content: flex-start; padding: var(--space-2) var(--space-5) var(--space-4); gap: var(--space-3); } .nav-sidebar__logo::before { width: 28px; height: 28px; font-size: var(--text-xs); } .nav-sidebar__logo > span { display: inline-block; font-size: var(--text-lg); font-weight: var(--font-weight-bold); letter-spacing: -0.3px; color: var(--color-text-primary); } .nav-sidebar__items { padding: 0 var(--space-2); gap: var(--space-0h); } /* Nav-Items: horizontal mit Label */ .nav-sidebar .nav-item { justify-content: flex-start; padding: 8px var(--space-3); gap: var(--space-3); } .nav-sidebar .nav-item__icon { width: 18px; height: 18px; } .nav-sidebar .nav-item__label { display: block; font-weight: inherit; } } /* -------------------------------------------------------- * Seiten-Container * -------------------------------------------------------- */ .page { padding: var(--space-4); max-width: var(--content-max-width); margin: 0 auto; } .page__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-5); gap: var(--space-4); } .page__title { font-size: var(--text-xl); font-weight: var(--font-weight-bold); letter-spacing: -0.3px; } @media (min-width: 1024px) { .page { padding: var(--space-8) var(--space-8); } .page__title { font-size: var(--text-2xl); letter-spacing: -0.5px; } } @media (min-width: 1440px) { .page { padding: var(--space-8) var(--space-10); } } /* -------------------------------------------------------- * Cards * * Einheitliches Card-Pattern für alle Module: * - Padding: 16px (mobile), 20px (desktop) * - Radius: 12px * - Shadow: subtle (sm) * - Internes Spacing: 8–12px * - Hover auf Desktop: leichter Lift (1px) * * Varianten: * .card — Basis (kein Padding) * .card--padded — Mit Padding * .card--compact — Enges Padding (12px) * .card--flat — Kein Shadow, nur Border * .card--interactive — Hover-Lift + Cursor * -------------------------------------------------------- */ .card { background-color: var(--color-surface); border-radius: var(--radius-md); box-shadow: var(--shadow-sm); overflow: hidden; } .card--padded { padding: var(--space-4); } .card--compact { padding: var(--space-3); } .card--flat { box-shadow: none; border: 1px solid var(--color-border-subtle); } .card--interactive { cursor: pointer; transition: transform var(--transition-fast), box-shadow var(--transition-fast); } .card--interactive:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); } .card--interactive:active { transform: scale(0.99); } @media (min-width: 1024px) { .card--padded { padding: var(--space-5); } } /* ── Card-Inhalts-Utilities ── */ .card__header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding-bottom: var(--space-3); margin-bottom: var(--space-3); border-bottom: 1px solid var(--color-border-subtle); } .card__title { font-size: var(--text-sm); font-weight: var(--font-weight-semibold); color: var(--color-text-primary); } .card__body { display: flex; flex-direction: column; gap: var(--space-2); } /* -------------------------------------------------------- * Modal-Basis * * Einheitliches Modal-Pattern für alle Module: * - Mobile: Bottom-Sheet (gerundet oben) * - Desktop: Zentriert (max-width variabel) * - Overlay: var(--color-overlay) * - Padding: 16px * - Radius: 16px * -------------------------------------------------------- */ .modal-overlay { position: fixed; inset: 0; background-color: var(--color-overlay); z-index: var(--z-modal); display: flex; align-items: flex-end; justify-content: center; animation: modal-overlay-in 0.2s ease forwards; } @media (min-width: 768px) { .modal-overlay { align-items: center; padding: var(--space-6); } } .modal-panel { background-color: var(--color-surface); width: 100%; max-height: 90dvh; overflow-y: auto; border-radius: var(--radius-lg) var(--radius-lg) 0 0; animation: modal-slide-up 0.25s var(--ease-out) forwards; } @media (min-width: 768px) { .modal-panel { max-width: 520px; border-radius: var(--radius-lg); animation: modal-scale-in 0.2s var(--ease-out) forwards; } .modal-panel--sm { max-width: 400px; } .modal-panel--lg { max-width: 680px; } } .modal-panel__header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4); border-bottom: 1px solid var(--color-border-subtle); position: sticky; top: 0; background-color: var(--color-surface); z-index: 1; } .modal-panel__title { font-size: var(--text-md); font-weight: var(--font-weight-semibold); } .modal-panel__close { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-full); color: var(--color-text-secondary); transition: background-color var(--transition-fast); position: relative; } .modal-panel__close::before { content: ''; position: absolute; inset: -8px; } .modal-panel__close:hover { background-color: var(--color-surface-3); } .modal-panel__body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); } .modal-panel__footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-border-subtle); } @keyframes modal-overlay-in { from { opacity: 0; } to { opacity: 1; } } @keyframes modal-slide-up { from { transform: translateY(100%); } to { transform: translateY(0); } } @keyframes modal-scale-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* -------------------------------------------------------- * Buttons * -------------------------------------------------------- */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-2) var(--space-4); border-radius: var(--radius-sm); font-size: var(--text-sm); font-weight: var(--font-weight-medium); min-height: var(--target-lg); transition: background-color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); cursor: pointer; white-space: nowrap; } @media (min-width: 1024px) { .btn { min-height: var(--target-md); } } .btn:active { transform: scale(0.98); } .btn--primary { background-color: var(--color-btn-primary); color: #ffffff; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } .btn--primary:hover { background-color: var(--color-btn-primary-hover); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); } .btn--secondary { background-color: transparent; color: var(--color-accent); border: 1.5px solid var(--color-border); } .btn--secondary:hover { background-color: var(--color-accent-light); border-color: var(--color-accent); } .btn--danger { background-color: var(--color-danger); color: #ffffff; } .btn--danger:hover { background-color: var(--color-danger-hover); } .btn--ghost { background-color: transparent; color: var(--color-text-secondary); } .btn--ghost:hover { background-color: var(--color-surface-2); color: var(--color-text-primary); } .btn:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; } .btn--icon { padding: var(--space-2); min-height: var(--target-lg); min-width: var(--target-lg); border-radius: var(--radius-sm); } @media (min-width: 1024px) { .btn--icon { min-height: var(--target-md); min-width: var(--target-md); } } /* FAB (Floating Action Button) */ .fab { position: fixed; bottom: calc(var(--nav-height-mobile) + var(--safe-area-inset-bottom) + var(--space-4)); right: var(--space-4); width: 52px; height: 52px; border-radius: var(--radius-full); background-color: var(--module-accent, var(--color-btn-primary)); color: #ffffff; box-shadow: var(--shadow-lg); display: flex; align-items: center; justify-content: center; z-index: calc(var(--z-nav) - 1); transition: transform var(--transition-fast), box-shadow var(--transition-fast); } .fab:hover { background-color: color-mix(in srgb, var(--module-accent, var(--color-btn-primary)) 85%, black); transform: scale(1.05); } .fab:active { transform: scale(0.95); } @media (min-width: 1024px) { .fab { bottom: var(--space-8); width: 48px; height: 48px; } } /* -------------------------------------------------------- * Form-Elemente * -------------------------------------------------------- */ .input, .form-input { width: 100%; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); border: 1.5px solid var(--color-border); background-color: var(--color-surface); color: var(--color-text-primary); font-size: var(--text-md); transition: border-color var(--transition-fast), box-shadow var(--transition-fast); min-height: var(--target-lg); } @media (min-width: 1024px) { .input, .form-input { min-height: var(--target-md); font-size: var(--text-base); } } .input:focus, .form-input:focus { outline: none; border-color: var(--color-accent); box-shadow: 0 0 0 3px var(--color-accent-light); } .input::placeholder, .form-input::placeholder { color: var(--color-text-disabled); } .label { display: block; font-size: var(--text-sm); font-weight: var(--font-weight-medium); color: var(--color-text-secondary); margin-bottom: var(--space-1); } .form-group { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: var(--space-4); } /* -------------------------------------------------------- * Skeleton-Loading * -------------------------------------------------------- */ .skeleton { background: linear-gradient( 90deg, var(--color-border-subtle) 25%, var(--color-surface-2) 50%, var(--color-border-subtle) 75% ); background-size: 200% 100%; animation: skeleton-shimmer 1.5s infinite; border-radius: var(--radius-sm); } @keyframes skeleton-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } /* -------------------------------------------------------- * Leer-Zustände (Empty States) * -------------------------------------------------------- */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3); padding: var(--space-12) var(--space-6); text-align: center; } .empty-state__icon { width: 56px; height: 56px; color: var(--color-text-disabled); } .empty-state__title { font-size: var(--text-md); font-weight: var(--font-weight-semibold); color: var(--color-text-primary); } .empty-state__description { font-size: var(--text-sm); color: var(--color-text-secondary); max-width: 280px; line-height: var(--line-height-base); } .empty-state--compact { padding: var(--space-4) var(--space-3); gap: var(--space-2); } .empty-state--compact .empty-state__description { font-size: var(--text-sm); } /* -------------------------------------------------------- * Responsive Grid (Utility) * -------------------------------------------------------- */ .grid { display: grid; gap: var(--space-4); grid-template-columns: 1fr; } @media (min-width: 768px) { .grid--2 { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 1024px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } } @media (min-width: 1440px) { .grid--4 { grid-template-columns: repeat(4, 1fr); } } /* -------------------------------------------------------- * Layout-Primitives * * Wiederverwendbare Content-Area-Patterns für Desktop. * Mobile: immer single-column (Stacking). * * .layout-master-detail — Liste links, Detail rechts (Aufgaben, Einkauf) * .layout-content-aside — Hauptinhalt + schmale Seitenleiste (Kalender) * .layout-center — Zentrierter schmaler Content (Settings, Login) * .layout-wide — Volle Breite mit max-width (Dashboard) * -------------------------------------------------------- */ /* ── Master-Detail ── * Mobile: gestapelt (Detail wird programmatisch ein-/ausgeblendet). * Desktop: 2 Spalten — Liste ~40%, Detail ~60%. */ .layout-master-detail { display: flex; flex-direction: column; gap: var(--space-4); max-width: var(--content-max-width); margin: 0 auto; } .layout-master-detail__master { flex: 1; min-width: 0; } .layout-master-detail__detail { flex: 1; min-width: 0; } @media (min-width: 1024px) { .layout-master-detail { flex-direction: row; gap: var(--space-6); } .layout-master-detail__master { flex: 0 0 380px; max-width: 420px; overflow-y: auto; max-height: calc(100dvh - var(--space-16)); position: sticky; top: var(--space-8); } .layout-master-detail__detail { flex: 1; } } @media (min-width: 1440px) { .layout-master-detail__master { flex: 0 0 420px; max-width: 460px; } } /* ── Content + Aside ── * Mobile: gestapelt. * Desktop: Hauptinhalt nimmt Platz ein, Aside ist 280–320px. */ .layout-content-aside { display: flex; flex-direction: column; gap: var(--space-4); max-width: var(--content-max-width); margin: 0 auto; } .layout-content-aside__main { flex: 1; min-width: 0; } .layout-content-aside__aside { min-width: 0; } @media (min-width: 1024px) { .layout-content-aside { flex-direction: row; gap: var(--space-6); } .layout-content-aside__main { flex: 1; } .layout-content-aside__aside { flex: 0 0 280px; overflow-y: auto; max-height: calc(100dvh - var(--space-16)); position: sticky; top: var(--space-8); } } @media (min-width: 1440px) { .layout-content-aside__aside { flex: 0 0 320px; } } /* ── Center ── * Schmaler, zentrierter Content-Bereich (max. 720px). * Ideal für Settings, Formulare, Einzelansichten. */ .layout-center { max-width: 720px; margin: 0 auto; } /* ── Wide ── * Volle verfügbare Breite mit max-width. * Für Dashboard und andere Multi-Column-Ansichten. */ .layout-wide { max-width: var(--content-max-width); margin: 0 auto; } /* ── Prose ── * Text-Content mit optimaler Lesebreite. */ .prose { max-width: 720px; } /* ── Sticky-Header (Modul-Toolbars) ── * Klebt am oberen Rand beim Scrollen. */ .sticky-header { position: sticky; top: 0; z-index: var(--z-sticky); background-color: color-mix(in srgb, var(--color-bg) 90%, transparent); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); padding-bottom: var(--space-3); margin-bottom: var(--space-4); } /* -------------------------------------------------------- * Toast-Benachrichtigungen * -------------------------------------------------------- */ .toast-container { position: fixed; bottom: calc(var(--nav-height-mobile) + var(--safe-area-inset-bottom) + var(--space-4)); left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; gap: var(--space-2); z-index: var(--z-toast); pointer-events: none; width: min(calc(100% - var(--space-8)), 380px); } @media (min-width: 1024px) { .toast-container { bottom: var(--space-6); left: calc(var(--sidebar-width) + (100% - var(--sidebar-width)) / 2); } } .toast { background-color: var(--neutral-800); color: var(--neutral-50); padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); font-size: var(--text-sm); box-shadow: var(--shadow-lg); pointer-events: auto; animation: toast-in 0.25s var(--ease-out) forwards; } .toast--success { background-color: var(--color-success); color: #fff; } .toast--danger { background-color: var(--color-danger); color: #fff; } .toast--warning { background-color: var(--color-warning); color: #fff; } @keyframes toast-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } } .toast--out { animation: toast-out 0.2s ease forwards; } @keyframes toast-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.95) translateY(4px); } } /* -------------------------------------------------------- * RRULE-Felder (Wiederholungs-Formular, shared Tasks + Kalender) * -------------------------------------------------------- */ .rrule-fields { margin-top: var(--space-4); border-top: 1px solid var(--color-border-subtle); padding-top: var(--space-4); } .rrule-details { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-3); padding: var(--space-3); background: var(--color-surface-2); border-radius: var(--radius-sm); } .rrule-row { display: flex; align-items: flex-end; gap: var(--space-3); } .rrule-interval-wrap { display: flex; align-items: center; gap: var(--space-2); } .rrule-interval-unit { font-size: var(--text-sm); color: var(--color-text-secondary); white-space: nowrap; } .rrule-day-grid { display: flex; gap: var(--space-1); flex-wrap: wrap; margin-top: var(--space-1); } .rrule-day { width: 40px; height: 40px; border-radius: var(--radius-sm); border: 1.5px solid var(--color-border); background: transparent; color: var(--color-text-secondary); font-size: var(--text-sm); font-weight: var(--font-weight-medium); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all var(--transition-fast); position: relative; } .rrule-day::before { content: ''; position: absolute; inset: -4px; } .rrule-day:hover { border-color: var(--color-accent); color: var(--color-accent); } .rrule-day--active { background: var(--color-accent); border-color: var(--color-accent); color: #fff; } .rrule-day--active:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); } /* -------------------------------------------------------- * Print-Styles * -------------------------------------------------------- */ @media print { .nav-sidebar, .nav-bottom, .fab, .toast-container, .modal-overlay, .modal-backdrop { display: none !important; } .app-content { margin-left: 0 !important; padding-bottom: 0 !important; } .app-shell { display: block; } body { background: #fff; color: #000; } .card { box-shadow: none; border: 1px solid #ddd; break-inside: avoid; } a[href]::after { content: " (" attr(href) ")"; font-size: 0.85em; color: #666; } .nav-item, a[data-route]::after { content: none; } } /* -------------------------------------------------------- * Skip-Link (sichtbar bei Keyboard-Focus) * -------------------------------------------------------- */ .sr-only:focus-visible { position: fixed; top: 0; left: 0; z-index: 9999; width: auto; height: auto; padding: var(--space-2) var(--space-4); margin: 0; clip: auto; white-space: normal; overflow: visible; background: var(--color-accent); color: #fff; font-size: var(--text-sm); border-radius: 0 0 var(--radius-sm) 0; }