/* ========================================================================= Unifi Voucher Tool – Design System Ein einziges Stylesheet fuer Frontend, Login und Admin-Backend. Aufbau: Tokens -> Base -> Layout -> Komponenten -> Seiten -> Responsive ========================================================================= */ /* ========================================================================= 1. TOKENS ========================================================================= */ :root { /* Flaechen */ --bg-body: #f6f7f9; --bg-canvas: #f6f7f9; --bg-card: #ffffff; --bg-header: rgba(255,255,255,0.82); --bg-sidebar: #ffffff; --bg-hover: #f2f4f7; --bg-subtle: #f8f9fb; --bg-input: #ffffff; --bg-table-head: #f8f9fb; --bg-overlay: rgba(15,20,30,0.45); --modal-overlay: rgba(15,20,30,0.45); --toast-bg: #ffffff; --code-bg: #f2f4f7; --stat-sub: #f2f4f7; /* Text */ --text-primary: #101625; --text-secondary: #525c6e; --text-muted: #8a93a3; --text-inverse: #ffffff; /* Linien */ --border-color: #e5e8ee; --border-strong: #d4d9e2; --border-hover: #c3c9d6; --input-border: #dfe3ea; --input-focus: #5b5bd6; /* Marke */ --accent: #5b5bd6; --accent-hover: #4a4ac2; --accent-soft: #eeeefc; --accent-border: #d7d7f7; --accent-2: #8b5cf6; --brand-gradient: linear-gradient(135deg, #5b5bd6 0%, #8b5cf6 100%); /* Status */ --success: #15884b; --success-soft: #e7f6ed; --success-border: #bfe6ce; --warning: #b96a05; --warning-soft: #fdf2e2; --warning-border: #f5dcb2; --danger: #d02f3c; --danger-soft: #fdecee; --danger-border: #f6cfd4; --info: #0d7ec4; --info-soft: #e6f3fc; --info-border: #bfdff5; --bg-badge-info: #e6f3fc; --text-badge-info:#0d5e91; /* Radien */ --r-xs: 6px; --r-sm: 8px; --r-md: 10px; --r-lg: 14px; --r-xl: 20px; --r-pill: 999px; /* Schatten */ --shadow: rgba(16,24,40,0.06); --shadow-lg: rgba(16,24,40,0.16); --shadow-xs: 0 1px 2px rgba(16,24,40,0.05); --shadow-sm: 0 1px 3px rgba(16,24,40,0.06), 0 1px 2px rgba(16,24,40,0.04); --shadow-md: 0 6px 16px -4px rgba(16,24,40,0.10), 0 2px 6px -2px rgba(16,24,40,0.05); --shadow-xl: 0 28px 60px -24px rgba(16,24,40,0.28), 0 8px 24px -12px rgba(16,24,40,0.12); --ring: 0 0 0 4px rgba(91,91,214,0.16); /* Layout */ --sidebar-w: 264px; --topbar-h: 64px; --scrollbar-track: transparent; --scrollbar-thumb: #d3d8e0; --font-sans: 'Inter', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; --font-mono: 'JetBrains Mono', 'SFMono-Regular', ui-monospace, Menlo, Consolas, monospace; } [data-theme="dark"] { --bg-body: #0a0c11; --bg-canvas: #0a0c11; --bg-card: #12151d; --bg-header: rgba(18,21,29,0.82); --bg-sidebar: #0f121a; --bg-hover: #1a1f2b; --bg-subtle: #151925; --bg-input: #171b26; --bg-table-head: #151925; --bg-overlay: rgba(3,5,10,0.66); --modal-overlay: rgba(3,5,10,0.66); --toast-bg: #151925; --code-bg: #1a1f2b; --stat-sub: #1a1f2b; --text-primary: #e9ecf3; --text-secondary: #a2abbd; --text-muted: #6f7889; --text-inverse: #0a0c11; --border-color: #232838; --border-strong: #303750; --border-hover: #3b4360; --input-border: #2a3044; --input-focus: #8b8bf5; --accent: #8b8bf5; --accent-hover: #a3a3fa; --accent-soft: #1e2038; --accent-border: #34356a; --accent-2: #a78bfa; --brand-gradient: linear-gradient(135deg, #6d6df0 0%, #a78bfa 100%); --success: #4ade80; --success-soft: #0f2a1c; --success-border: #1d4d33; --warning: #fbbf24; --warning-soft: #2a2010; --warning-border: #4d3c14; --danger: #f87171; --danger-soft: #2c1417; --danger-border: #58252b; --info: #60b8f0; --info-soft: #0e2534; --info-border: #1d4661; --bg-badge-info: #0e2534; --text-badge-info:#7dc8f0; --shadow: rgba(0,0,0,0.4); --shadow-lg: rgba(0,0,0,0.6); --shadow-xs: 0 1px 2px rgba(0,0,0,0.4); --shadow-sm: 0 1px 3px rgba(0,0,0,0.45); --shadow-md: 0 8px 20px -6px rgba(0,0,0,0.55); --shadow-xl: 0 30px 60px -20px rgba(0,0,0,0.75); --ring: 0 0 0 4px rgba(139,139,245,0.22); --scrollbar-thumb: #2c3346; } /* ========================================================================= 2. BASE ========================================================================= */ *, *::before, *::after { box-sizing: border-box; } html { -webkit-text-size-adjust: 100%; } body { margin: 0; font-family: var(--font-sans); font-size: 14px; line-height: 1.55; color: var(--text-primary); background: var(--bg-body); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-feature-settings: 'cv02','cv03','cv04','ss01'; } h1, h2, h3, h4, h5 { margin: 0; color: var(--text-primary); font-weight: 650; letter-spacing: -0.018em; line-height: 1.25; } h1 { font-size: 26px; } h2 { font-size: 18px; } h3 { font-size: 16px; } p { margin: 0 0 12px; } p:last-child { margin-bottom: 0; } a { color: var(--accent); text-decoration: none; } a:hover { color: var(--accent-hover); } code, pre, kbd, .mono { font-family: var(--font-mono); font-size: 0.92em; } code { background: var(--code-bg); color: var(--text-primary); padding: 2px 6px; border-radius: var(--r-xs); border: 1px solid var(--border-color); } hr, .section-divider { border: none; border-top: 1px solid var(--border-color); margin: 24px 0; } .muted { color: var(--text-muted); font-size: 13px; } .text-sm { font-size: 13px; } .text-xs { font-size: 12px; } .hide-mobile { } ::selection { background: var(--accent-soft); color: var(--accent-hover); } ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: var(--scrollbar-track); } ::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: var(--r-pill); border: 3px solid transparent; background-clip: content-box; } ::-webkit-scrollbar-thumb:hover { background: var(--border-hover); background-clip: content-box; } :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } /* ========================================================================= 3. APP-LAYOUT (Admin) ========================================================================= */ .sidebar { position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w); background: var(--bg-sidebar); border-right: 1px solid var(--border-color); display: flex; flex-direction: column; z-index: 200; } .sidebar-brand { display: flex; align-items: center; gap: 11px; height: var(--topbar-h); padding: 0 20px; flex-shrink: 0; border-bottom: 1px solid var(--border-color); color: var(--text-primary); } .sidebar-brand:hover { color: var(--text-primary); } .brand-mark { width: 32px; height: 32px; border-radius: 9px; background: var(--brand-gradient); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 14px; box-shadow: 0 4px 10px -2px rgba(91,91,214,0.5); flex-shrink: 0; } .brand-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; } .brand-name { font-size: 14px; font-weight: 650; letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .brand-sub { font-size: 11px; color: var(--text-muted); font-weight: 500; } .sidebar nav { flex: 1; overflow-y: auto; padding: 14px 12px 20px; } .sidebar-section { padding: 14px 10px 6px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); } .sidebar-nav { list-style: none; margin: 0; padding: 0; } .sidebar-nav li { margin-bottom: 2px; } .sidebar-nav a { position: relative; display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: var(--r-md); color: var(--text-secondary); font-size: 13.5px; font-weight: 500; transition: background-color .15s, color .15s; } .sidebar-nav a i { width: 17px; text-align: center; font-size: 14px; color: var(--text-muted); transition: color .15s; } .sidebar-nav a:hover { background: var(--bg-hover); color: var(--text-primary); } .sidebar-nav a:hover i { color: var(--text-secondary); } .sidebar-nav a.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; } .sidebar-nav a.active i { color: var(--accent); } .nav-badge { margin-left: auto; font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: var(--r-pill); background: var(--bg-hover); color: var(--text-muted); } .sidebar-nav a.active .nav-badge { background: var(--accent); color: #fff; } .sidebar-foot { flex-shrink: 0; border-top: 1px solid var(--border-color); padding: 12px; } .topbar, .header { position: fixed; top: 0; right: 0; left: var(--sidebar-w); height: var(--topbar-h); display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 0 26px; background: var(--bg-header); backdrop-filter: saturate(180%) blur(12px); -webkit-backdrop-filter: saturate(180%) blur(12px); border-bottom: 1px solid var(--border-color); z-index: 150; } .header-left { display: flex; align-items: center; gap: 12px; min-width: 0; } .header-right { display: flex; align-items: center; gap: 8px; } .header-title { font-size: 15px; font-weight: 600; color: var(--text-primary); } .breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .breadcrumb .sep { opacity: .5; } .breadcrumb .current { color: var(--text-primary); font-weight: 600; } .main-content { margin-left: var(--sidebar-w); padding: calc(var(--topbar-h) + 26px) 26px 48px; min-height: 100vh; } .main-content > *:not(.page-header):not(script):not(style) { max-width: 1440px; } .page-header { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 16px; margin-bottom: 24px; } .page-title { display: flex; align-items: center; gap: 10px; font-size: 24px; font-weight: 680; letter-spacing: -0.022em; color: var(--text-primary); margin: 0; } .page-subtitle { color: var(--text-muted); font-size: 13.5px; margin: 5px 0 0; } .page-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } /* Benutzer-Chip */ .user-menu { display: flex; align-items: center; gap: 10px; padding: 5px 12px 5px 5px; border: 1px solid var(--border-color); border-radius: var(--r-pill); background: var(--bg-card); transition: border-color .15s, background-color .15s; } .user-menu:hover { border-color: var(--border-hover); } .user-avatar, .user-avatar-sm { width: 30px; height: 30px; border-radius: 50%; background: var(--brand-gradient); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 12.5px; flex-shrink: 0; letter-spacing: 0; } .user-avatar-sm { width: 32px; height: 32px; font-size: 13px; } .user-name { font-size: 13px; font-weight: 550; color: var(--text-primary); } .user-role { font-size: 11px; color: var(--text-muted); } /* Icon-Buttons im Topbar */ .dark-mode-toggle, .mobile-menu-btn, .icon-btn { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border-color); border-radius: var(--r-md); background: var(--bg-card); color: var(--text-secondary); font-size: 14px; cursor: pointer; transition: all .15s; flex-shrink: 0; padding: 0; } .dark-mode-toggle:hover, .mobile-menu-btn:hover, .icon-btn:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--border-hover); } .mobile-menu-btn { display: none; } /* Sprachumschalter */ .lang-switcher { display: flex; align-items: center; gap: 2px; padding: 3px; background: var(--bg-hover); border: 1px solid var(--border-color); border-radius: var(--r-md); flex-shrink: 0; } .lang-btn { padding: 4px 9px; border: none; background: none; border-radius: var(--r-xs); font: inherit; font-size: 11.5px; font-weight: 650; letter-spacing: .02em; color: var(--text-muted); cursor: pointer; transition: all .15s; } .lang-btn.active { background: var(--bg-card); color: var(--text-primary); box-shadow: var(--shadow-xs); } .lang-btn:hover:not(.active) { color: var(--text-secondary); } .sidebar-overlay { display: none; position: fixed; inset: 0; background: var(--bg-overlay); backdrop-filter: blur(2px); z-index: 199; } .sidebar-overlay.active { display: block; } /* ========================================================================= 4. KOMPONENTEN – Buttons ========================================================================= */ .btn, .btn-header, .btn-microsoft { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 9px 16px; border: 1px solid transparent; border-radius: var(--r-md); font-family: inherit; font-size: 13.5px; font-weight: 570; line-height: 1.2; white-space: nowrap; cursor: pointer; text-decoration: none; transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, transform .08s; background: var(--bg-card); color: var(--text-primary); border-color: var(--border-color); } .btn:active { transform: translateY(0.5px); } .btn i { font-size: 12.5px; } .btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 1px 2px rgba(16,24,40,0.10); } .btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; } .btn-primary:focus-visible { box-shadow: var(--ring); outline: none; } .btn-secondary { background: var(--bg-card); border-color: var(--border-color); color: var(--text-secondary); } .btn-secondary:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--border-hover); } .btn-ghost, .btn-s { background: var(--bg-hover); border-color: transparent; color: var(--text-secondary); } .btn-ghost:hover, .btn-s:hover { background: var(--border-color); color: var(--text-primary); } .btn-success { background: var(--success); border-color: var(--success); color: #fff; } .btn-success:hover { filter: brightness(1.06); color: #fff; } .btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; } .btn-danger:hover { filter: brightness(1.06); color: #fff; } /* Zurueckhaltende Variante fuer Zeilenaktionen in Tabellen */ .btn-danger-soft { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); } .btn-danger-soft:hover { background: var(--danger); border-color: var(--danger); color: #fff; } .btn-warning { background: var(--warning); border-color: var(--warning); color: #fff; } .btn-outline { background: transparent; border-color: var(--accent-border); color: var(--accent); } .btn-outline:hover { background: var(--accent-soft); color: var(--accent-hover); } .btn-sm, .btn-small { padding: 6px 11px; font-size: 12.5px; border-radius: var(--r-sm); } .btn-lg { padding: 13px 22px; font-size: 15px; border-radius: var(--r-md); } .btn-block { width: 100%; } .btn:disabled, .btn[disabled] { opacity: .55; cursor: not-allowed; box-shadow: none; } /* Marken-Button im oeffentlichen Header */ .btn-header { background: var(--bg-card); border-color: var(--border-color); color: var(--text-primary); box-shadow: var(--shadow-xs); } .btn-header:hover { background: var(--bg-hover); color: var(--text-primary); } /* ========================================================================= 5. KOMPONENTEN – Formulare ========================================================================= */ label { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 550; color: var(--text-secondary); } .form-group { margin-bottom: 18px; } .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } .form-hint, .template-hint, .copy-hint, .field-hint { margin-top: 6px; font-size: 12px; color: var(--text-muted); } input[type="text"], input[type="email"], input[type="password"], input[type="number"], input[type="url"], input[type="tel"], input[type="search"], input[type="date"], select, textarea, .input { width: 100%; padding: 10px 13px; font-family: inherit; font-size: 14px; color: var(--text-primary); background: var(--bg-input); border: 1px solid var(--input-border); border-radius: var(--r-md); transition: border-color .15s, box-shadow .15s, background-color .15s; appearance: none; } textarea { min-height: 110px; resize: vertical; line-height: 1.6; } select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%238a93a3' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 34px; } input::placeholder, textarea::placeholder { color: var(--text-muted); } input:hover, select:hover, textarea:hover { border-color: var(--border-hover); } input:focus, select:focus, textarea:focus, .input:focus { outline: none; border-color: var(--input-focus); box-shadow: var(--ring); } input:disabled, select:disabled, textarea:disabled { background: var(--bg-hover); color: var(--text-muted); cursor: not-allowed; } input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer; } input[type="file"] { width: 100%; font-size: 13px; color: var(--text-secondary); } input[type="file"]::file-selector-button { margin-right: 10px; padding: 7px 13px; border: 1px solid var(--border-color); border-radius: var(--r-sm); background: var(--bg-card); color: var(--text-primary); font: inherit; font-size: 12.5px; font-weight: 550; cursor: pointer; transition: background-color .15s, border-color .15s; } input[type="file"]::file-selector-button:hover { background: var(--bg-hover); border-color: var(--border-hover); } .chk, label.chk { display: flex; align-items: center; gap: 10px; margin: 10px 0; font-size: 13.5px; font-weight: 500; color: var(--text-primary); cursor: pointer; } .chk input { flex-shrink: 0; } .filter-bar, .filter-row, .toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; } .filter-bar select, .filter-bar input, .toolbar select, .toolbar input { width: auto; min-width: 150px; } .filter-btn { padding: 7px 13px; border: 1px solid var(--border-color); border-radius: var(--r-pill); background: var(--bg-card); color: var(--text-secondary); font-size: 12.5px; font-weight: 550; cursor: pointer; transition: all .15s; } .filter-btn:hover { border-color: var(--border-hover); color: var(--text-primary); } .filter-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; } /* ========================================================================= 6. KOMPONENTEN – Cards ========================================================================= */ .card { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); margin-bottom: 22px; padding: 22px; } .card:has(> .card-header), .card:has(> .card-body) { padding: 0; overflow: hidden; } .card > h2, .card > h3 { font-size: 15.5px; font-weight: 620; margin-bottom: 14px; } .card-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; padding: 16px 22px; border-bottom: 1px solid var(--border-color); } .card-title { font-size: 15px; font-weight: 620; color: var(--text-primary); margin: 0; } .card-subtitle { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; } .card-body { padding: 22px; } .card-footer { padding: 14px 22px; border-top: 1px solid var(--border-color); background: var(--bg-subtle); } .card-actions { display: flex; gap: 8px; align-items: center; } .info-box, .placeholder-info { border: 1px solid var(--info-border); background: var(--info-soft); border-radius: var(--r-md); padding: 14px 16px; margin-bottom: 18px; } .info-box h4 { color: var(--info); font-size: 13px; margin-bottom: 4px; } .info-box p { color: var(--text-secondary); font-size: 13px; } .placeholder-info { border-color: var(--warning-border); background: var(--warning-soft); } .placeholder-info h4 { color: var(--warning); font-size: 13px; margin-bottom: 4px; } /* ========================================================================= 7. KOMPONENTEN – Statistik-Kacheln ========================================================================= */ .stats-grid, .grid4 { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 16px; margin-bottom: 24px; } .stat-card, .stat { position: relative; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); padding: 18px; transition: border-color .15s, box-shadow .15s, transform .15s; } .stat-card:hover, .stat:hover { border-color: var(--border-hover); box-shadow: var(--shadow-md); } .stat-card-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; } .stat-card-title { font-size: 12.5px; font-weight: 550; color: var(--text-muted); } .stat-card-icon { width: 32px; height: 32px; border-radius: var(--r-sm); display: flex; align-items: center; justify-content: center; font-size: 13px; background: var(--bg-hover); color: var(--text-secondary); } .stat-card-icon.accent { background: var(--accent-soft); color: var(--accent); } .stat-card-icon.success { background: var(--success-soft); color: var(--success); } .stat-card-icon.warning { background: var(--warning-soft); color: var(--warning); } .stat-card-icon.danger { background: var(--danger-soft); color: var(--danger); } .stat-card-icon.info { background: var(--info-soft); color: var(--info); } .stat-card-value, .stat .n { font-size: 28px; font-weight: 660; letter-spacing: -0.03em; color: var(--text-primary); line-height: 1.1; font-variant-numeric: tabular-nums; } /* Farbe traegt das Icon-Chip – die Zahl bleibt ruhig. */ .stat-card-value.valid, .stat-card-value.used, .stat-card-value.expired { color: var(--text-primary); } .stat-card-sub, .stat .l { margin-top: 5px; font-size: 12px; color: var(--text-muted); } /* ========================================================================= 8. KOMPONENTEN – Tabellen ========================================================================= */ .table, .card table, .table-container table { width: 100%; border-collapse: collapse; font-size: 13.5px; } .table th, .card table th { padding: 10px 18px; text-align: left; background: var(--bg-table-head); color: var(--text-muted); font-size: 11.5px; font-weight: 620; text-transform: uppercase; letter-spacing: 0.055em; border-bottom: 1px solid var(--border-color); white-space: nowrap; } .table code, .card table code { white-space: nowrap; } .table td, .card table td { padding: 13px 18px; border-bottom: 1px solid var(--border-color); color: var(--text-primary); vertical-align: middle; } .card:not(:has(> .card-header)):not(:has(> .card-body)) table { font-size: 13px; } .card:not(:has(> .card-header)):not(:has(> .card-body)) table th, .card:not(:has(> .card-header)):not(:has(> .card-body)) table td { padding-left: 0; padding-right: 10px; } .card:not(:has(> .card-header)):not(:has(> .card-body)) table th:last-child, .card:not(:has(> .card-header)):not(:has(> .card-body)) table td:last-child { padding-right: 0; } .card:not(:has(> .card-header)):not(:has(> .card-body)) table th { background: transparent; } .table tbody tr:last-child td, .card table tbody tr:last-child td { border-bottom: none; } .table tbody tr { transition: background-color .12s; } .table tbody tr:hover td { background: var(--bg-subtle); } .table-container { overflow-x: auto; } .ip-cell { font-family: var(--font-mono); font-size: 12px; color: var(--text-muted); } .details-cell { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-secondary); } /* ========================================================================= 9. KOMPONENTEN – Badges, Chips, Alerts ========================================================================= */ .badge { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; padding: 3px 9px; border-radius: var(--r-pill); font-size: 11.5px; font-weight: 600; line-height: 1.5; border: 1px solid transparent; } .badge::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex-shrink: 0; } /* Badges mit eigenem Icon brauchen keinen zusaetzlichen Punkt. */ .badge:has(i)::before, .badge:has(svg)::before { display: none; } .badge-success, .b-on { background: var(--success-soft); color: var(--success); border-color: var(--success-border); } .badge-warning { background: var(--warning-soft); color: var(--warning); border-color: var(--warning-border); } .badge-danger, .b-off { background: var(--danger-soft); color: var(--danger); border-color: var(--danger-border); } .badge-info { background: var(--info-soft); color: var(--text-badge-info); border-color: var(--info-border); } .badge-neutral { background: var(--bg-hover); color: var(--text-secondary); border-color: var(--border-color); } .b-on, .b-off { display: inline-flex; align-items: center; padding: 3px 9px; border-radius: var(--r-pill); font-size: 11.5px; font-weight: 600; } .chip, .action-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: var(--r-pill); background: var(--bg-hover); border: 1px solid var(--border-color); color: var(--text-secondary); font-size: 12px; font-weight: 550; white-space: nowrap; } .alert { display: flex; align-items: flex-start; gap: 10px; padding: 12px 15px; margin-bottom: 20px; border: 1px solid var(--border-color); border-radius: var(--r-md); font-size: 13.5px; background: var(--bg-card); color: var(--text-primary); } .alert-error, .alert-danger { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); } .alert-success, .alert-ok { background: var(--success-soft); border-color: var(--success-border); color: var(--success); } .alert-warning { background: var(--warning-soft); border-color: var(--warning-border); color: var(--warning); } .alert-info { background: var(--info-soft); border-color: var(--info-border); color: var(--info); } .empty-state { text-align: center; padding: 54px 20px; color: var(--text-muted); } .empty-state i, .empty-state .empty-icon { display: flex; align-items: center; justify-content: center; width: 52px; height: 52px; margin: 0 auto 14px; border-radius: var(--r-lg); background: var(--bg-hover); color: var(--text-muted); font-size: 20px; opacity: 1; } .empty-state p { font-size: 13.5px; margin: 0; } .empty-state h3 { font-size: 15px; margin-bottom: 6px; color: var(--text-secondary); } /* Tabs / Segmented control */ .tab-navigation, .mode-tabs, .segmented { display: inline-flex; gap: 3px; padding: 3px; background: var(--bg-hover); border: 1px solid var(--border-color); border-radius: var(--r-md); margin-bottom: 20px; } .tab-button, .mode-tab, .segmented > button { flex: 1; padding: 7px 16px; border: none; border-radius: var(--r-sm); background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 13px; font-weight: 550; cursor: pointer; transition: all .15s; white-space: nowrap; } .tab-button:hover, .mode-tab:hover { color: var(--text-primary); } .tab-button.active, .mode-tab.active, .segmented > button.active { background: var(--bg-card); color: var(--text-primary); box-shadow: var(--shadow-xs); font-weight: 600; } .mode-tabs { display: flex; width: 100%; } /* Pagination */ .pagination { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; padding: 14px 22px; border-top: 1px solid var(--border-color); } .page-info { font-size: 12.5px; color: var(--text-muted); } .page-btns { display: flex; gap: 4px; flex-wrap: wrap; } .page-btn { min-width: 32px; padding: 6px 10px; border: 1px solid var(--border-color); border-radius: var(--r-sm); background: var(--bg-card); color: var(--text-secondary); font-size: 12.5px; font-weight: 550; text-align: center; cursor: pointer; transition: all .15s; } .page-btn:hover { border-color: var(--border-hover); color: var(--text-primary); background: var(--bg-hover); } .page-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; } .page-btn:disabled { opacity: .45; cursor: not-allowed; } /* Modal */ .modal { display: none; position: fixed; inset: 0; background: var(--modal-overlay); backdrop-filter: blur(3px); z-index: 500; padding: 24px; overflow-y: auto; } .modal.show, .modal.active { display: flex; align-items: flex-start; justify-content: center; } .modal-content { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-xl); box-shadow: var(--shadow-xl); width: 100%; max-width: 560px; margin: 6vh auto; overflow: hidden; animation: modal-in .2s cubic-bezier(.2,.8,.3,1); } @keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px; border-bottom: 1px solid var(--border-color); } .modal-title { font-size: 16px; font-weight: 620; } .modal-close { background: none; border: none; font-size: 20px; line-height: 1; color: var(--text-muted); cursor: pointer; } .modal-close:hover { color: var(--text-primary); } .modal-body { padding: 22px; } .modal-footer { display: flex; justify-content: flex-end; gap: 10px; padding: 16px 22px; border-top: 1px solid var(--border-color); background: var(--bg-subtle); } /* Toasts */ #toast-container { position: fixed; bottom: 24px; right: 24px; z-index: 900; display: flex; flex-direction: column; gap: 10px; pointer-events: none; } .toast { display: flex; align-items: flex-start; gap: 11px; min-width: 300px; max-width: 400px; padding: 13px 16px; background: var(--toast-bg); border: 1px solid var(--border-color); border-radius: var(--r-lg); box-shadow: var(--shadow-xl); transform: translateX(130%); transition: transform .35s cubic-bezier(.2,.9,.3,1), opacity .2s; pointer-events: all; } .toast.show { transform: translateX(0); } .toast-icon { width: 22px; height: 22px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 11px; font-weight: 700; } .toast.success .toast-icon { background: var(--success-soft); color: var(--success); } .toast.error .toast-icon { background: var(--danger-soft); color: var(--danger); } .toast.info .toast-icon { background: var(--accent-soft); color: var(--accent); } .toast.warning .toast-icon { background: var(--warning-soft); color: var(--warning); } .toast-body { flex: 1; min-width: 0; } .toast-title { font-size: 13.5px; font-weight: 600; color: var(--text-primary); } .toast-msg { font-size: 12.5px; color: var(--text-muted); margin-top: 1px; } .toast-close { background: none; border: none; padding: 0; font-size: 17px; line-height: 1; color: var(--text-muted); cursor: pointer; } .toast-close:hover { color: var(--text-primary); } /* Live-Status */ .live-badge { display: inline-flex; align-items: center; gap: 7px; padding: 6px 13px; border-radius: var(--r-pill); background: var(--success-soft); border: 1px solid var(--success-border); color: var(--success); font-size: 12.5px; font-weight: 600; } .live-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: pulse 2s infinite; } .live-badge.loading { background: var(--warning-soft); border-color: var(--warning-border); color: var(--warning); } .live-badge.error { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); } .live-badge.error .dot { animation: none; } @keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } } /* ========================================================================= 10. DASHBOARD ========================================================================= */ .site-status, .sites-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; } .site-status-card, .site-card { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-lg); padding: 16px; transition: border-color .15s, box-shadow .15s; } .site-status-card:hover, .site-card:hover { border-color: var(--border-hover); box-shadow: var(--shadow-sm); } .site-status-card.error { border-color: var(--danger-border); } .site-status-name { font-size: 14px; font-weight: 600; color: var(--text-primary); } .site-voucher-count { padding: 2px 10px; border-radius: var(--r-pill); background: var(--accent-soft); color: var(--accent); font-size: 12.5px; font-weight: 650; font-variant-numeric: tabular-nums; } .site-voucher-count.zero { background: var(--bg-hover); color: var(--text-muted); } .site-status-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 14px; } .site-stat { text-align: center; padding: 9px 6px; background: var(--bg-subtle); border: 1px solid var(--border-color); border-radius: var(--r-sm); } .site-stat-value { font-size: 17px; font-weight: 650; font-variant-numeric: tabular-nums; } .site-stat-value.valid { color: var(--success); } .site-stat-value.used { color: var(--warning); } .site-stat-value.expired { color: var(--danger); } .site-stat-label { margin-top: 1px; font-size: 11px; color: var(--text-muted); } .site-error { margin-top: 10px; font-size: 12px; color: var(--danger); } .chart-container { position: relative; height: 280px; } .top-users-list { list-style: none; margin: 0; padding: 0; } .top-users-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--border-color); } .top-users-list li:last-child { border-bottom: none; } .user-info-row { display: flex; align-items: center; gap: 11px; min-width: 0; } .user-count { padding: 2px 10px; border-radius: var(--r-pill); background: var(--bg-hover); color: var(--text-primary); font-size: 12.5px; font-weight: 650; font-variant-numeric: tabular-nums; } .refresh-indicator { display: flex; align-items: center; gap: 10px; } .last-update { font-size: 12px; color: var(--text-muted); } .two-col-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin-bottom: 22px; } .two-col-grid > .card { margin-bottom: 0; } /* ========================================================================= 11. AUTH – Login, Passwort, 2FA ========================================================================= */ .auth-body { min-height: 100vh; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); background: var(--bg-card); } .auth-visual { /* Über die Einstellungen überschreibbar (login_bg_from/-to/-image/-overlay). */ --login-from: #3b2f8f; --login-to: #6d5ce7; --login-overlay: 0.4; position: relative; overflow: hidden; padding: 56px; display: flex; flex-direction: column; justify-content: space-between; color: #fff; background: radial-gradient(900px 480px at 12% 8%, rgba(255,255,255,.18), transparent 60%), radial-gradient(700px 520px at 88% 92%, rgba(0,0,0,.18), transparent 62%), linear-gradient(150deg, var(--login-from) 0%, var(--login-to) 100%); } .auth-visual::after { content: ''; position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,.055) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.055) 1px, transparent 1px); background-size: 56px 56px; mask-image: radial-gradient(70% 70% at 50% 40%, #000 30%, transparent 100%); -webkit-mask-image: radial-gradient(70% 70% at 50% 40%, #000 30%, transparent 100%); pointer-events: none; } /* Eigenes Hintergrundbild: Bild füllt die Spalte, darüber liegt eine abdunkelnde Ebene, damit der Text lesbar bleibt. */ .auth-visual.has-image { background: var(--login-image) center / cover no-repeat, var(--login-from); } .auth-visual.has-image::after { display: none; } .auth-visual.has-image::before { content: ''; position: absolute; inset: 0; background: linear-gradient(160deg, rgba(0,0,0,calc(var(--login-overlay) * 0.7)) 0%, rgba(0,0,0,var(--login-overlay)) 100%); pointer-events: none; } .auth-brand-logo { max-height: 42px; max-width: 220px; width: auto; } /* Ohne Bildspalte: zentrierte Karte auf dem App-Hintergrund. */ .auth-body-single { grid-template-columns: 1fr; background: radial-gradient(760px 420px at 8% -6%, var(--accent-soft), transparent 60%), radial-gradient(640px 400px at 102% 4%, rgba(139,92,246,.10), transparent 62%), var(--bg-body); } .auth-body-single .auth-panel { background: transparent; } .auth-body-single .login-container { max-width: 420px; padding: 34px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-xl); box-shadow: var(--shadow-xl); } /* Bildfeld: Vorschau, Upload und URL nebeneinander */ .image-field { display: flex; gap: 14px; align-items: flex-start; } .image-preview { width: 84px; height: 64px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; padding: 6px; background: var(--bg-subtle); border: 1px solid var(--border-color); border-radius: var(--r-md); color: var(--text-muted); overflow: hidden; } .image-preview img { max-width: 100%; max-height: 100%; object-fit: contain; } .image-field-controls { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; } .image-field-controls .chk { margin: 0; font-size: 12.5px; color: var(--text-secondary); } /* Farbwähler mit Hex-Eingabe */ .color-field { display: flex; align-items: center; gap: 8px; } .color-field input[type="color"] { width: 42px; height: 38px; flex-shrink: 0; padding: 3px; border: 1px solid var(--input-border); border-radius: var(--r-md); background: var(--bg-input); cursor: pointer; } .color-field input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; } .color-field input[type="color"]::-webkit-color-swatch { border: none; border-radius: 6px; } .color-field input[type="text"] { font-family: var(--font-mono); font-size: 13px; } .auth-mark { display: flex; align-items: center; gap: 11px; margin-bottom: 20px; font-size: 15px; font-weight: 620; color: var(--text-primary); } .auth-visual > * { position: relative; z-index: 1; } .auth-brand { display: flex; align-items: center; gap: 12px; font-size: 15px; font-weight: 600; } .auth-brand .brand-mark { background: rgba(255,255,255,.16); backdrop-filter: blur(6px); box-shadow: none; } .auth-claim { max-width: 420px; } .auth-claim h2 { color: #fff; font-size: 32px; line-height: 1.2; letter-spacing: -0.03em; margin-bottom: 14px; } .auth-claim p { color: rgba(255,255,255,.76); font-size: 14.5px; line-height: 1.6; } .auth-features { list-style: none; margin: 28px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; } .auth-features li { display: flex; align-items: center; gap: 11px; font-size: 13.5px; color: rgba(255,255,255,.88); } .auth-features .tick { width: 22px; height: 22px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(255,255,255,.16); font-size: 10px; } .auth-foot { font-size: 12.5px; color: rgba(255,255,255,.55); } .auth-panel { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 48px 28px; background: var(--bg-card); position: relative; } .auth-tools { position: absolute; top: 20px; right: 24px; display: flex; gap: 8px; } .login-container, .auth-card { width: 100%; max-width: 380px; } .auth-card h1, .login-container h1 { font-size: 24px; margin-bottom: 8px; letter-spacing: -0.025em; } .subtitle, .auth-sub { color: var(--text-muted); font-size: 13.5px; margin-bottom: 26px; } .auth-card .logo, .login-container .logo { max-width: 170px; height: auto; margin-bottom: 22px; display: block; } .auth-card form, .login-container form { text-align: left; } .login-container .btn, .auth-card .btn { width: 100%; } .login-container .btn + .btn, .auth-card .btn + .btn { margin-top: 10px; } .btn-microsoft { width: 100%; background: var(--bg-card); border: 1px solid var(--border-color); color: var(--text-primary); font-weight: 550; padding: 11px 16px; } .btn-microsoft:hover { background: var(--bg-hover); border-color: var(--border-hover); color: var(--text-primary); } .btn-microsoft svg { width: 17px; height: 17px; } .divider { position: relative; margin: 20px 0; text-align: center; } .divider::before { content: ''; position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: var(--border-color); } .divider span { position: relative; padding: 0 12px; background: var(--bg-card); color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; } .back-link, .local-login-link, .forgot-link { display: inline-block; font-size: 13px; color: var(--text-muted); text-decoration: none; } .back-link:hover, .local-login-link:hover, .forgot-link:hover { color: var(--accent); } .auth-links { margin-top: 22px; text-align: center; } .forgot-link { display: block; margin: -6px 0 16px; text-align: right; } .code-input { text-align: center; letter-spacing: .32em; font-family: var(--font-mono); font-size: 19px; padding: 13px; } .codes-box { border: 1px solid var(--warning-border); background: var(--warning-soft); border-radius: var(--r-md); padding: 16px; margin-bottom: 20px; } .codes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; } .codes span { padding: 8px; border: 1px solid var(--warning-border); border-radius: var(--r-xs); background: var(--bg-card); font-family: var(--font-mono); font-size: 13px; text-align: center; letter-spacing: .1em; } .qr { display: flex; justify-content: center; margin: 18px 0; } .qr img, .qr canvas { border: 1px solid var(--border-color); border-radius: var(--r-md); padding: 10px; background: #fff; } .secret { padding: 11px; border: 1px solid var(--border-color); border-radius: var(--r-sm); background: var(--bg-subtle); font-family: var(--font-mono); font-size: 13px; letter-spacing: .12em; text-align: center; word-break: break-all; margin-bottom: 18px; } .status { display: inline-flex; align-items: center; gap: 7px; padding: 5px 12px; margin-bottom: 20px; border-radius: var(--r-pill); font-size: 12.5px; font-weight: 600; } .status.on { background: var(--success-soft); color: var(--success); border: 1px solid var(--success-border); } .status.off { background: var(--bg-hover); color: var(--text-muted); border: 1px solid var(--border-color); } /* ========================================================================= 12. OEFFENTLICHES FRONTEND (Voucher-Erstellung) ========================================================================= */ .app-body { min-height: 100vh; padding: 0 20px 64px; background: radial-gradient(760px 420px at 8% -6%, var(--accent-soft), transparent 60%), radial-gradient(640px 400px at 102% 4%, rgba(139,92,246,.10), transparent 62%), var(--bg-body); background-attachment: fixed; } .app-topbar { position: sticky; top: 0; z-index: 100; max-width: 1120px; margin: 0 auto 34px; height: 68px; display: flex; align-items: center; justify-content: space-between; gap: 14px; } .app-topbar .brand { display: flex; align-items: center; gap: 11px; color: var(--text-primary); } .app-topbar .brand-name { font-size: 15px; font-weight: 620; } .app-actions { display: flex; align-items: center; gap: 8px; } .container, .app-card { position: relative; max-width: 560px; margin: 0 auto; padding: 34px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-xl); box-shadow: var(--shadow-xl); } .app-card-head { margin-bottom: 26px; } .app-card-head h1 { font-size: 23px; letter-spacing: -0.025em; } .app-card-head p { margin-top: 6px; font-size: 13.5px; color: var(--text-muted); } .container > .logo { max-width: 180px; display: block; margin: 0 auto 22px; } .template-dropdown { padding: 14px 16px; margin-bottom: 20px; background: var(--bg-subtle); border: 1px solid var(--border-color); border-radius: var(--r-md); } .template-dropdown label { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); } .email-option { padding: 15px 16px; margin: 16px 0; background: var(--bg-subtle); border: 1px solid var(--border-color); border-radius: var(--r-md); transition: border-color .15s, background-color .15s; } .email-option.active { border-color: var(--accent-border); background: var(--accent-soft); } .email-checkbox-wrapper { display: flex; align-items: center; gap: 11px; cursor: pointer; } .email-checkbox-wrapper label { margin: 0; font-size: 13.5px; font-weight: 570; color: var(--text-primary); cursor: pointer; display: flex; align-items: center; gap: 8px; } .email-input-wrapper { max-height: 0; overflow: hidden; opacity: 0; transition: all .28s ease; } .email-input-wrapper.show { max-height: 140px; opacity: 1; margin-top: 14px; } /* Voucher-Ticket */ .voucher-result { position: relative; overflow: hidden; padding: 30px 26px 26px; margin-bottom: 20px; border-radius: var(--r-lg); color: #fff; text-align: center; background: radial-gradient(520px 280px at 20% 0%, rgba(167,139,250,.55), transparent 62%), linear-gradient(140deg, #4b3ec4 0%, #6d5ce7 100%); box-shadow: 0 20px 40px -22px rgba(75,62,196,.85); } .voucher-result .result-label { display: inline-flex; align-items: center; gap: 7px; padding: 4px 12px; margin-bottom: 18px; border-radius: var(--r-pill); background: rgba(255,255,255,.14); font-size: 12px; font-weight: 600; letter-spacing: .02em; } .voucher-code { font-family: var(--font-mono); font-size: 32px; font-weight: 600; letter-spacing: .12em; cursor: pointer; transition: opacity .15s; } .voucher-code:hover { opacity: .82; } .voucher-info { margin-top: 10px; font-size: 13px; color: rgba(255,255,255,.75); } .voucher-meta { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin-top: 16px; } .voucher-meta span { padding: 4px 11px; border-radius: var(--r-pill); background: rgba(255,255,255,.12); font-size: 12px; color: rgba(255,255,255,.9); } .ticket-divider { position: relative; height: 1px; margin: 24px -26px; border-top: 1.5px dashed rgba(255,255,255,.3); } .ticket-divider::before, .ticket-divider::after { content: ''; position: absolute; top: -11px; width: 22px; height: 22px; border-radius: 50%; background: var(--bg-card); } .ticket-divider::before { left: -11px; } .ticket-divider::after { right: -11px; } .qr-wrapper { display: flex; flex-direction: column; align-items: center; } .qr-wrapper #qrcode { padding: 12px; border-radius: var(--r-md); background: #fff; line-height: 0; box-shadow: 0 8px 20px -10px rgba(0,0,0,.5); } .qr-wrapper canvas, .qr-wrapper img { border-radius: 4px; } .qr-label { margin-top: 10px; font-size: 12px; color: rgba(255,255,255,.7); } .instruction-box { padding: 18px; margin-top: 20px; background: var(--bg-subtle); border: 1px solid var(--border-color); border-radius: var(--r-md); } .instruction-box h3 { font-size: 14px; margin-bottom: 8px; } .instruction-box p, .instruction-box div { font-size: 13px; color: var(--text-secondary); line-height: 1.65; } .bulk-table { width: 100%; border-collapse: collapse; font-size: 13.5px; } .bulk-table th { padding: 9px 12px; text-align: left; background: var(--bg-table-head); color: var(--text-muted); font-size: 11px; font-weight: 620; text-transform: uppercase; letter-spacing: .05em; border-bottom: 1px solid var(--border-color); } .bulk-table th:first-child { border-top-left-radius: var(--r-sm); } .bulk-table th:last-child { border-top-right-radius: var(--r-sm); } .bulk-table td { padding: 11px 12px; border-bottom: 1px solid var(--border-color); color: var(--text-primary); } .bulk-table tr:last-child td { border-bottom: none; } .bulk-table code { cursor: pointer; letter-spacing: .08em; } .bulk-table code:hover { border-color: var(--accent-border); color: var(--accent); } /* ========================================================================= 15. SEITEN-KOMPONENTEN (Admin-Detailseiten) ========================================================================= */ /* Voucher-Liste */ .stat-label { font-size: 12.5px; font-weight: 550; color: var(--text-muted); margin-bottom: 6px; } .stat-value { font-size: 26px; font-weight: 660; letter-spacing: -0.03em; color: var(--text-primary); font-variant-numeric: tabular-nums; } .stat-value.valid { color: var(--success); } .stat-value.used { color: var(--warning); } .stat-value.expired { color: var(--danger); } .site-selector { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } .site-selector select { width: auto; min-width: 210px; } input.search-bar, .site-selector .search-bar { min-width: 240px; width: auto; flex: 1; max-width: 360px; } .usage-info { display: flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; } .usage-bar { width: 52px; height: 5px; border-radius: var(--r-pill); background: var(--bg-hover); overflow: hidden; } .usage-bar-fill { height: 100%; border-radius: var(--r-pill); background: var(--accent); } .voucher-note { max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-secondary); } .table tr.deleting { opacity: .4; pointer-events: none; } .live-indicator { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 550; color: var(--success); } .live-indicator .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: pulse 2s infinite; } .loading { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 56px; color: var(--text-muted); } .loading i { font-size: 20px; animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0); } to { transform: rotate(360deg); } } .no-sites-warning { padding: 28px; text-align: center; border: 1px solid var(--warning-border); background: var(--warning-soft); color: var(--warning); border-radius: var(--r-lg); } /* Sites */ .site-card-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; } .site-name { font-size: 15.5px; font-weight: 620; color: var(--text-primary); } .site-id-label { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-muted); } .site-info { margin: 12px 0; font-size: 13px; color: var(--text-secondary); } .site-info-item { display: flex; align-items: center; gap: 9px; margin-bottom: 6px; } .site-info-item i { width: 14px; color: var(--text-muted); } .site-actions { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border-color); } .empty-card { padding: 56px 20px; text-align: center; color: var(--text-muted); background: var(--bg-card); border: 1px dashed var(--border-strong); border-radius: var(--r-lg); } /* Gestapelte Felder ohne .form-group (Einstellungs-Cards) */ .card > label, .card .input + label, .card input + label, .card select + label, .card textarea + label, .card .chk + label, .card .row + label, .card .row3 + label { margin-top: 16px; } .card .input + label:first-of-type { margin-top: 0; } /* Formular-Helfer */ .checkbox-group { display: flex; align-items: center; gap: 10px; } .checkbox-group input { width: auto; } .checkbox-group label { margin: 0; font-weight: 500; color: var(--text-primary); } .site-selection { max-height: 185px; overflow-y: auto; padding: 12px; background: var(--bg-subtle); border: 1px solid var(--border-color); border-radius: var(--r-sm); } .help-text { margin-top: 5px; font-size: 12px; color: var(--text-muted); } .action-btns { display: flex; flex-wrap: nowrap; gap: 6px; } .table td:last-child { white-space: nowrap; } .duration-badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: var(--r-pill); background: var(--bg-hover); border: 1px solid var(--border-color); font-size: 12px; color: var(--text-secondary); } .badge-secondary { background: var(--bg-hover); color: var(--text-secondary); border-color: var(--border-color); } .placeholder-list { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; } /* Einstellungen: Tabs */ .tab-container { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); overflow: hidden; } .tab-container .tab-navigation { display: flex; gap: 4px; width: 100%; margin: 0; padding: 10px 14px 0; background: var(--bg-subtle); border: none; border-bottom: 1px solid var(--border-color); border-radius: 0; overflow-x: auto; } .tab-container .tab-button { flex: 0 0 auto; padding: 10px 14px; border-radius: var(--r-sm) var(--r-sm) 0 0; border-bottom: 2px solid transparent; background: transparent; box-shadow: none; color: var(--text-secondary); } .tab-container .tab-button:hover { background: var(--bg-hover); color: var(--text-primary); } .tab-container .tab-button.active { background: var(--bg-card); border-bottom-color: var(--accent); color: var(--accent); box-shadow: none; } .tab-content { display: none; padding: 28px; } .tab-content.active { display: block; animation: fade-in .2s ease; } @keyframes fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } } .token-box, .keybox { padding: 13px; border-radius: var(--r-sm); background: var(--bg-subtle); border: 1px solid var(--border-color); font-family: var(--font-mono); font-size: 13px; color: var(--text-primary); word-break: break-all; } .keybox { background: #0d1017; border-color: #1d2432; color: #7ee7a8; margin-top: 10px; } .a-link { margin-right: 10px; font-size: 13px; color: var(--accent); } .a-link:hover { text-decoration: underline; } /* Fokus-Seiten (2FA, Passwort, Installer) */ .focus-page { display: flex; align-items: center; justify-content: center; padding: 40px 20px; } .focus-card { width: 100%; max-width: 480px; margin: 0; padding: 30px; border-radius: var(--r-xl); box-shadow: var(--shadow-xl); } .focus-card.wide { max-width: 720px; } .focus-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 22px; } .focus-icon { width: 40px; height: 40px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; border-radius: var(--r-md); background: var(--accent-soft); color: var(--accent); font-size: 16px; } .focus-card h1 { font-size: 19px; } .focus-card .sub, .sub { font-size: 13px; color: var(--text-muted); } .focus-card ol { margin: 0 0 18px 18px; padding: 0; color: var(--text-secondary); font-size: 13.5px; line-height: 1.8; } .focus-card .btn + .btn, .focus-card form + form { margin-top: 10px; } .codes-box strong { display: block; font-size: 14px; color: var(--warning); } .codes-box p { margin: 6px 0 0; font-size: 12.5px; color: var(--text-secondary); } /* Kompakte Raster fuer Einstellungsformulare */ .row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; } .row3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; } @media (max-width: 720px) { .row, .row3 { grid-template-columns: 1fr; } } /* ========================================================================= 13. RESPONSIVE ========================================================================= */ @media (max-width: 1240px) { .two-col-grid { grid-template-columns: 1fr; } } @media (max-width: 1024px) { .auth-body { grid-template-columns: 1fr; } .auth-visual { display: none; } } @media (max-width: 860px) { :root { --sidebar-w: 260px; } .mobile-menu-btn { display: flex; } .sidebar { transform: translateX(-100%); transition: transform .25s ease; box-shadow: var(--shadow-xl); } .sidebar.mobile-open { transform: translateX(0); } .topbar, .header { left: 0; padding: 0 16px; } .main-content { margin-left: 0; padding: calc(var(--topbar-h) + 18px) 16px 40px; } .stats-grid, .grid4 { grid-template-columns: repeat(2, 1fr); } .site-status, .sites-grid { grid-template-columns: 1fr; } .form-grid { grid-template-columns: 1fr; } .page-header { align-items: flex-start; } .hide-mobile { display: none; } .user-menu { padding: 4px; } .table-container { overflow-x: auto; } } @media (max-width: 560px) { .stats-grid, .grid4 { grid-template-columns: 1fr; } .lang-switcher { display: none; } .container, .app-card { padding: 24px 20px; border-radius: var(--r-lg); } .app-topbar { margin-bottom: 22px; } .voucher-code { font-size: 26px; } .codes { grid-template-columns: 1fr; } } /* ========================================================================= 14. DRUCK ========================================================================= */ @media print { .sidebar, .topbar, .header, .toolbar, .no-print, #toast-container, .app-topbar { display: none !important; } body { background: #fff !important; } .main-content { margin: 0 !important; padding: 0 !important; } .card { box-shadow: none !important; border-color: #ddd !important; } }