Files
Intune-Manager/www/styles.css
T
marcoandClaude Sonnet 4.6 07b462dc3d Geräte-Tab: eigene Suchfeld-Klassen statt globale search-wrap
dev-search-wrap und dev-search-input unabhängig von globalen Styles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-12 14:38:30 +02:00

5343 lines
132 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================
Intune Manager — Cal.com-Aesthetik
Weißes Canvas, schwarze CTAs, Inter, dezente Hairlines.
============================================================= */
:root {
/* Cal.com Tokens */
--primary: #111111;
--primary-active: #242424;
--primary-disabled: #e5e7eb;
--ink: #111111;
--body: #374151;
--muted: #6b7280;
--muted-soft: #898989;
--hairline: #e5e7eb;
--hairline-soft: #f3f4f6;
--canvas: #ffffff;
--surface-soft: #f8f9fa;
--surface-card: #f5f5f5;
--surface-strong: #e5e7eb;
--surface-dark: #101010;
--surface-dark-elev: #1a1a1a;
--on-primary: #ffffff;
--on-dark: #ffffff;
--on-dark-soft: #a1a1aa;
--brand-primary: #27a078; /* Logo-Hintergrund, Stepper-Indikator — Firmenfarbe */
--brand-accent: #3b82f6; /* Available-Pillen, Links, Akzent-Hover */
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
--pink: #ec4899;
--violet: #8b5cf6;
--emerald: #34d399;
--orange: #fb923c;
--teal: #14b8a6;
--teal-deep: #0d9488;
/* Tinted accent backgrounds — automatisch angepasst per Dark-Mode-Override */
--success-bg: rgba(16,185,129,0.05);
--success-soft: rgba(16,185,129,0.12);
--success-strong: rgba(16,185,129,0.18);
--success-border: rgba(16,185,129,0.28);
--success-shadow: rgba(16,185,129,0.35);
--error-bg: rgba(239,68,68,0.06);
--error-soft: rgba(239,68,68,0.12);
--error-strong: rgba(239,68,68,0.18);
--error-border: rgba(239,68,68,0.30);
--warning-bg: rgba(245,158,11,0.06);
--warning-soft: rgba(245,158,11,0.12);
--warning-strong: rgba(245,158,11,0.18);
--warning-border: rgba(245,158,11,0.30);
--accent-bg: rgba(59,130,246,0.06);
--accent-soft: rgba(59,130,246,0.12);
--accent-strong: rgba(59,130,246,0.18);
--pink-soft: rgba(236,72,153,0.12);
--violet-soft: rgba(139,92,246,0.12);
--teal-soft: rgba(20,184,166,0.12);
--app-expanded-bg: #f7f7f7;
/* Aufgeklappte App-Zeile: solid background, kein rgba. Wird vom Frontend
per applyThemeColors() mit der gewaehlten Farbe 1:1 ueberschrieben. */
--row-selected-border: #71e5c4;
--row-selected-bg: #71e5c4;
--row-selected-bg-hover: #71e5c4;
/* Radii */
--r-xs: 4px;
--r-sm: 6px;
--r-md: 8px;
--r-lg: 12px;
--r-xl: 16px;
--r-pill: 9999px;
/* Spacing (Cal token-Basis 4px) */
--s-xxs: 4px;
--s-xs: 8px;
--s-sm: 12px;
--s-md: 16px;
--s-lg: 24px;
--s-xl: 32px;
/* Shadows — Cal: subtle, soft */
--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.12);
--tx: 150ms cubic-bezier(0.2, 0.7, 0.3, 1);
--tx-slow: 240ms cubic-bezier(0.2, 0.7, 0.3, 1);
--font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-mono: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, Consolas, monospace;
}
@supports (font-variation-settings: normal) {
:root { --font-display: 'Inter var', 'Inter', sans-serif; --font-body: 'Inter var', 'Inter', sans-serif; }
}
/* =============================================================
Dark Mode — blau-getoente Schwarz-Skala, equal lightness steps,
entsaettigte Akzentfarben. Wird via data-theme="dark" am <html>
aktiviert, JS persistiert die Wahl in localStorage.
============================================================= */
html[data-theme="dark"] {
--primary: #ffffff;
--primary-active: #f0f1f5;
--primary-disabled: #3a4150;
--ink: #f5f6fa;
--body: #d8dde6;
--muted: #9aa3b3;
--muted-soft: #6b7383;
--hairline: #353b4a;
--hairline-soft: #2a2f3d;
--canvas: #1f2430; /* aufgehellt — kein tiefschwarz mehr */
--surface-soft: #262b38;
--surface-card: #2c313f;
--surface-strong: #353b4a;
--surface-dark: #f5f6fa;
--surface-dark-elev: #e0e4eb;
--on-primary: #1f2430;
--on-dark: #1f2430;
--on-dark-soft: #6b7383;
/* Tints im Dark-Mode kraeftiger, mit den hellen Akzentfarben */
--success-bg: rgba(102,204,190,0.10);
--success-soft: rgba(102,204,190,0.18);
--success-strong: rgba(102,204,190,0.26);
--success-border: rgba(102,204,190,0.40);
--success-shadow: rgba(102,204,190,0.45);
--error-bg: rgba(231,139,139,0.10);
--error-soft: rgba(231,139,139,0.18);
--error-strong: rgba(231,139,139,0.26);
--error-border: rgba(231,139,139,0.40);
--warning-bg: rgba(229,196,67,0.10);
--warning-soft: rgba(229,196,67,0.18);
--warning-strong: rgba(229,196,67,0.26);
--warning-border: rgba(229,196,67,0.40);
--accent-bg: rgba(127,177,240,0.10);
--accent-soft: rgba(127,177,240,0.18);
--accent-strong: rgba(127,177,240,0.26);
--pink-soft: rgba(240,166,204,0.18);
--violet-soft: rgba(192,134,234,0.18);
--teal-soft: rgba(102,204,190,0.18);
/* Akzent-Farben entsaettigen — hellere Variante fuer dunklen Hintergrund */
--brand-primary: #5ec4a0;
--brand-accent: #7fb1f0;
--success: #66ccbe;
--warning: #e5c443;
--error: #e78b8b;
--pink: #f0a6cc;
--violet: #c086ea;
--emerald: #66ccbe;
--orange: #f4a261;
--teal: #66ccbe;
--teal-deep: #5cc0b1;
/* Schatten dezenter im Dark Mode */
--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.6);
}
/* Verhindert Flash beim ersten Render */
html[data-theme="dark"] body { background: var(--canvas); color: var(--body); }
/* Waehrend des Theme-Wechsels ALLE Transitions deaktivieren — sonst animiert
jedes Element gleichzeitig seine Farbaenderungen und das ganze Layout ruckelt. */
html.theme-switching,
html.theme-switching *,
html.theme-switching *::before,
html.theme-switching *::after {
transition: none !important;
animation-duration: 0s !important;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
height: 100%;
background: var(--canvas);
color: var(--ink);
font-family: var(--font-body);
font-size: 14px;
line-height: 1.5;
font-feature-settings: 'cv11', 'ss01', 'ss03';
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
color: var(--body);
}
button { font-family: inherit; cursor: pointer; }
input, select { font-family: inherit; }
a { color: var(--ink); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }
.hidden { display: none !important; }
.flex-1 { flex: 1; }
.muted { color: var(--muted); }
/* Display headlines: -0.04em letter-spacing on Inter approximates Cal Sans */
h1, h2, h3 {
font-family: var(--font-display);
color: var(--ink);
font-weight: 600;
letter-spacing: -0.025em;
}
/* =============================================================
HEADER (top-nav)
============================================================= */
.topbar {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 24px;
height: 64px;
padding: 0 32px;
background: var(--canvas);
border-bottom: 1px solid var(--hairline);
position: sticky;
top: 0;
z-index: 50;
}
.topbar .header-actions { justify-self: end; }
/* Topbar Navigation Tabs */
.topbar-nav {
display: flex;
align-items: center;
gap: 4px;
height: 100%;
}
.nav-tab {
display: flex;
align-items: center;
height: 100%;
padding: 0 16px;
background: none;
border: none;
border-bottom: 2px solid transparent;
color: var(--muted);
font-size: 13.5px;
font-weight: 500;
cursor: pointer;
transition: color var(--tx), border-color var(--tx);
white-space: nowrap;
}
.nav-tab:hover { color: var(--ink); }
.nav-tab.active {
color: var(--ink);
border-bottom-color: var(--brand);
font-weight: 600;
}
/* Group Management Vollbild-View */
.group-mgmt-view {
display: flex;
flex-direction: column;
height: calc(100vh - 64px);
overflow: hidden;
}
.group-mgmt-body {
flex: 1;
display: flex;
flex-direction: column;
padding: 20px 28px;
overflow: hidden;
}
.group-mgmt-tabs {
flex-shrink: 0;
margin-bottom: 16px;
}
.group-mgmt-columns {
flex: 1;
overflow: hidden;
min-height: 0;
}
.group-mgmt-columns .gex-left,
.group-mgmt-columns .gex-right {
overflow-y: auto;
}
.group-mgmt-foot {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 12px;
border-top: 1px solid var(--hairline);
margin-top: 12px;
flex-shrink: 0;
}
.brand { display: flex; align-items: center; gap: 12px; }
.logo {
width: 32px; height: 32px;
border-radius: var(--r-md);
background: var(--brand-primary);
color: var(--on-primary);
display: grid; place-items: center;
font-weight: 700;
font-size: 16px;
letter-spacing: -0.04em;
overflow: hidden;
flex-shrink: 0;
}
/* Wenn ein eigenes Logo gesetzt ist: Hintergrund weg und Bild voll fuellen. */
.logo.has-custom-logo {
background: transparent;
border-radius: var(--r-sm);
}
.logo-img {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
.brand-name {
font-size: 15px;
font-weight: 600;
color: var(--ink);
letter-spacing: -0.02em;
}
.header-actions { display: flex; align-items: center; gap: 12px; }
/* Theme-Toggle — Slide-Switch */
.theme-toggle {
appearance: none;
background: transparent;
border: none;
padding: 0;
cursor: pointer;
flex-shrink: 0;
display: inline-flex;
align-items: center;
}
.theme-track {
position: relative;
display: block;
width: 44px;
height: 22px;
border-radius: 999px;
background: linear-gradient(135deg, #fcd34d 0%, #f59e0b 100%);
transition: background-color var(--tx-slow);
box-shadow:
inset 0 1px 2px rgba(120, 70, 0, 0.30),
inset 0 0 0 1px rgba(120, 70, 0, 0.18);
}
.theme-toggle:hover .theme-track {
filter: brightness(1.06);
}
.theme-ico {
position: absolute;
top: 50%;
width: 11px;
height: 11px;
z-index: 2; /* Icons UEBER dem Knob — Knob wirkt wie ein "Halter" */
transform: translateY(-50%);
transition: opacity var(--tx);
pointer-events: none;
}
/* Knob-Mitte links: 3 + 8 = 11; Sun 11px breit -> left = 11 - 5.5 = 5.5 */
.theme-ico-sun { left: 6px; color: #b45309; }
/* Knob-Mitte rechts: 44 - 3 - 8 = 33; Moon 11px breit -> right = 44 - 33 - 5.5 = 5.5 */
.theme-ico-moon { right: 6px; color: #1e293b; transform: translate(1px, -50%); }
.theme-knob {
position: absolute;
top: 50%;
left: 3px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #ffffff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.30), 0 0 0 1px rgba(0, 0, 0, 0.06);
transform: translate3d(0, -50%, 0);
transition: transform 220ms cubic-bezier(0.34, 1.2, 0.64, 1), background-color 220ms ease-out;
z-index: 1; /* unter den Icons */
will-change: transform;
}
/* Light-Mode: Sun sichtbar (sitzt unter dem Knob → erscheint AUF dem Knob), Moon ausgeblendet */
html:not([data-theme="dark"]) .theme-ico-moon { opacity: 0; }
html:not([data-theme="dark"]) .theme-ico-sun { opacity: 1; }
/* Dark-Mode: Knob slidet nach rechts (60 - 24 - 3 - 3 = 30) */
html[data-theme="dark"] .theme-track {
background: #3b384f;
box-shadow:
inset 0 1px 2px rgba(0, 0, 0, 0.35),
inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}
html[data-theme="dark"] .theme-knob {
/* Slide-Distance: 44 - 16 - 3 - 3 = 22 */
transform: translate3d(22px, -50%, 0);
}
html[data-theme="dark"] .theme-ico-sun { opacity: 0; }
html[data-theme="dark"] .theme-ico-moon { opacity: 1; }
/* Connection pill */
/* Connection-Pill ist jetzt ein Avatar-Icon (Bootstrap person-circle).
Kein Border/Background — das Icon bringt seinen eigenen Kreis-Outline mit.
Status durch Icon-Farbe + kleiner Online-Dot unten rechts. Tooltip zeigt
den vollen Account-String. */
.conn-pill {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: none;
background: transparent;
color: var(--muted);
cursor: default;
transition: color var(--tx);
user-select: none;
}
.conn-pill .conn-text {
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 0;
}
.conn-pill .conn-text svg {
display: block;
}
/* Online-Dot rechts unten — Status-Indikator wie aus Teams/Slack bekannt */
.conn-pill .dot {
position: absolute;
right: 4px;
bottom: 4px;
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--muted-soft);
border: 1.5px solid var(--canvas);
box-sizing: content-box;
}
.conn-off { color: var(--muted); }
.conn-on { color: var(--brand-primary); }
.conn-on .dot { background: var(--success); animation: pulse 2.4s infinite; }
.conn-busy { color: var(--warning); }
.conn-busy .dot { background: var(--warning); animation: pulse 0.9s infinite; }
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(0.7); }
}
/* =============================================================
BUTTONS — Cal.com (black primary, white secondary, text link)
============================================================= */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
height: 40px;
padding: 0 20px;
border-radius: var(--r-md);
font-size: 14px;
font-weight: 600;
border: 1px solid transparent;
background: transparent;
color: var(--ink);
transition: all var(--tx);
white-space: nowrap;
letter-spacing: -0.005em;
user-select: none;
font-family: inherit;
}
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-sm { height: 32px; padding: 0 12px; font-size: 13px; }
.btn-lg { height: 44px; padding: 0 24px; font-size: 15px; }
.btn-primary {
background: var(--primary);
color: var(--on-primary);
}
.btn-primary:hover:not(:disabled) { background: var(--primary-active); }
.btn-primary:disabled { background: var(--primary-disabled); color: var(--muted); }
.btn-secondary {
background: var(--canvas);
color: var(--ink);
border-color: var(--hairline);
}
.btn-secondary:hover:not(:disabled) {
background: var(--surface-soft);
border-color: var(--surface-strong);
}
.btn-danger {
background: var(--error);
color: #fff;
border-color: var(--error);
}
.btn-danger:hover:not(:disabled) { filter: brightness(1.1); }
.btn-danger:disabled { opacity: .45; }
.btn-text {
background: transparent;
color: var(--muted);
font-weight: 500;
height: 36px;
padding: 0 12px;
}
.btn-text:hover:not(:disabled) { color: var(--ink); background: var(--surface-soft); }
.btn-apply {
width: 100%;
height: 44px;
background: var(--primary);
color: var(--on-primary);
font-weight: 600;
border-radius: var(--r-md);
margin-top: 4px;
}
.btn-apply:hover:not(:disabled) { background: var(--primary-active); }
.btn-apply:disabled { background: var(--primary-disabled); color: var(--muted); }
/* Icon button — circular */
.icon-btn {
width: 32px; height: 32px;
border-radius: var(--r-md);
background: transparent;
border: 1px solid transparent;
color: var(--muted);
display: inline-grid;
place-items: center;
transition: all var(--tx);
}
.icon-btn:hover { background: var(--surface-soft); color: var(--ink); border-color: var(--hairline); }
/* Link-style button */
.link-btn {
background: transparent;
border: none;
color: var(--ink);
font-size: 13px;
font-weight: 500;
padding: 4px 6px;
border-radius: var(--r-sm);
letter-spacing: -0.005em;
}
.link-btn:hover { background: var(--surface-soft); }
.link-btn-danger { color: var(--error); display: block; margin: 8px auto 0; }
.link-btn-danger:hover { background: var(--error-bg); }
.dotsep { color: var(--muted-soft); font-size: 12px; }
/* =============================================================
LAYOUT
============================================================= */
.layout {
display: grid;
grid-template-columns: 440px minmax(0, 1fr) 440px;
gap: 14px;
padding: 16px 20px 24px;
max-width: 1920px;
margin: 0 auto;
width: 100%;
flex: 1;
align-items: stretch;
}
.panel {
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-lg);
display: flex;
flex-direction: column;
overflow: hidden;
position: sticky;
top: 80px;
height: calc(100vh - 96px); /* feste, identische Hoehe */
}
.panel-head {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 16px 12px;
gap: 12px;
}
.panel-title { display: flex; align-items: center; gap: 10px; }
.panel-title h2 {
font-size: 16px;
font-weight: 600;
color: var(--ink);
letter-spacing: -0.015em;
}
.panel-head-actions { display: flex; gap: 4px; }
.count-badge {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: var(--r-pill);
font-size: 12px;
font-weight: 500;
background: var(--surface-card);
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.count-badge.accent {
background: var(--ink);
color: var(--on-primary);
}
/* =============================================================
MODE SEGMENT — nav-pill-group
============================================================= */
.mode-segment {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
margin: 0 16px 12px;
padding: 3px;
background: var(--surface-soft);
border-radius: var(--r-pill);
box-shadow:
inset 0 1px 2px rgba(0, 0, 0, 0.06),
inset 0 0 0 1px var(--hairline);
}
.seg {
position: relative;
padding: 7px 10px;
background: transparent;
border: none;
border-radius: var(--r-pill);
color: var(--muted);
font-size: 13px;
font-weight: 500;
transition: color 180ms ease-out;
letter-spacing: -0.005em;
z-index: 1;
}
.seg:hover { color: var(--ink); }
.seg.active {
background: var(--ink);
color: var(--on-primary);
font-weight: 600;
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.30),
0 0 0 1px rgba(0, 0, 0, 0.06);
}
.seg.active:hover { color: var(--on-primary); }
/* =============================================================
FORMS
============================================================= */
.search-wrap {
position: relative;
margin: 0 16px 12px;
display: flex;
align-items: center;
}
.search-ico {
position: absolute;
left: 12px;
color: var(--muted);
pointer-events: none;
}
.input, .select {
width: 100%;
height: 38px;
padding: 0 14px;
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
color: var(--ink);
font-size: 14px;
transition: all var(--tx);
font-family: inherit;
letter-spacing: -0.005em;
}
.input-search { padding-left: 36px; padding-right: 80px; }
.input:focus, .select:focus {
outline: none;
border-color: var(--ink);
box-shadow: 0 0 0 3px rgba(17,17,17,0.08);
}
.input::placeholder { color: var(--muted-soft); }
.select {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236b7280'%3E%3Cpath d='M4 6l4 4 4-4z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: 32px;
}
.search-hint {
position: absolute;
right: 10px;
font-size: 10px;
color: var(--muted);
background: var(--surface-card);
padding: 3px 7px;
border-radius: var(--r-sm);
pointer-events: none;
font-weight: 500;
letter-spacing: 0.3px;
text-transform: uppercase;
}
.select-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px 10px;
}
.select-info {
font-size: 12px;
color: var(--muted);
font-weight: 500;
}
.select-actions { display: flex; align-items: center; gap: 4px; }
.apps-toolbar {
display: flex;
gap: 8px;
margin: 0 16px 10px;
}
.apps-toolbar .search-wrap { margin: 0; flex: 1; }
.apps-toolbar .select { width: 180px; flex-shrink: 0; }
.filter-chips {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 20px;
margin: 0 16px 12px;
}
.legend-group {
display: inline-flex;
align-items: center;
gap: 12px;
margin-left: auto;
padding-left: 12px;
}
/* Date-Range-Filter (Geaendert von-bis) — kein Pillen-Rahmen mehr,
liegt nahtlos in der Filter-Zeile zwischen den anderen Filtern. */
.date-filter-chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0;
background: transparent;
border: none;
border-radius: 0;
font-size: 12px;
color: var(--body);
height: 28px;
box-sizing: border-box;
}
.date-filter-label {
font-weight: 500;
color: var(--body);
cursor: help;
line-height: 1;
}
/* Date-Inputs: gleiche Schriftart wie der Rest der UI (Inter), keine
Monospace. Hoehe so dass sie sauber im Chip sitzen. flatpickr legt ein
altInput direkt nach dem Original an — beide selectoren werden gestyled. */
.date-filter-chip .date-input,
.date-filter-chip input.flatpickr-input {
border: 1px solid var(--hairline);
background: var(--canvas);
border-radius: var(--r-xs);
padding: 0 8px;
font-family: inherit;
font-size: 12px;
color: var(--ink);
width: 96px;
height: 22px;
box-sizing: border-box;
transition: none;
outline: none;
box-shadow: none;
}
.date-filter-chip .date-input:focus,
.date-filter-chip input.flatpickr-input:focus {
outline: none;
border-color: var(--brand-accent);
}
.date-sep { color: var(--muted); font-weight: 400; }
.date-clear {
background: transparent;
border: none;
color: var(--muted);
cursor: pointer;
font-size: 16px;
line-height: 1;
padding: 0 4px;
border-radius: var(--r-xs);
transition: all var(--tx);
}
.date-clear:hover { color: var(--error); background: var(--error-bg); }
/* Dark-Mode: Input-Background dunkel halten — flatpickr macht den Picker-
Popup selbst (siehe Theming weiter unten). */
html[data-theme="dark"] .date-filter-chip .date-input,
html[data-theme="dark"] .date-filter-chip input.flatpickr-input {
color: var(--ink);
background: var(--surface-soft);
border-color: var(--hairline);
}
.legend-item {
display: inline-flex;
align-items: center;
gap: 5px;
font-size: 11px;
color: var(--muted);
cursor: help;
}
.legend-item .row-status {
width: 14px; height: 14px;
font-size: 9px;
}
.check-chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0 4px 0 0;
background: transparent;
border: none;
border-radius: 0;
font-size: 12px;
color: var(--body);
cursor: pointer;
transition: color var(--tx);
user-select: none;
font-weight: 500;
/* Exakte Hoehe — synchron mit .date-filter-chip damit alles in der
Filter-Zeile auf einer Linie ist. */
height: 28px;
box-sizing: border-box;
}
.check-chip:hover { color: var(--ink); }
.check-chip input[type=checkbox] {
appearance: none;
width: 14px; height: 14px;
border: 1.5px solid var(--surface-strong);
border-radius: var(--r-xs);
display: inline-grid; place-items: center;
cursor: pointer;
transition: all var(--tx);
}
.check-chip input[type=checkbox]:checked {
background: var(--ink);
border-color: var(--ink);
}
.check-chip input[type=checkbox]:checked::after {
content: '✓';
font-size: 10px;
color: var(--on-primary);
font-weight: 900;
line-height: 1;
}
/* Active-State: nur Text-Farbe verstaerken, kein flaechiger BG-Fill.
Der gefuellte Checkbox-Indikator (siehe input[type=checkbox]:checked
weiter oben) gibt schon ausreichend visuelles Feedback. */
.check-chip:has(input:checked) {
color: var(--ink);
font-weight: 600;
}
/* =============================================================
LIST AREAS
============================================================= */
.list-area {
flex: 1;
overflow-y: auto;
border-top: 1px solid var(--hairline);
background: var(--canvas);
}
.list-area::-webkit-scrollbar { width: 8px; }
.list-area::-webkit-scrollbar-track { background: transparent; }
.list-area::-webkit-scrollbar-thumb { background: var(--surface-strong); border-radius: 4px; }
.list-area::-webkit-scrollbar-thumb:hover { background: var(--muted-soft); }
/* Target rows */
.target-row {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 12px;
border-bottom: 1px solid var(--hairline-soft);
cursor: pointer;
transition: background var(--tx);
min-height: 38px;
}
.target-row:hover { background: var(--surface-soft); }
.target-row.selected {
background: rgba(16,185,129,0.22);
border-left: 2px solid var(--success);
padding-left: 14px;
}
.target-row.selected:hover {
background: rgba(16,185,129,0.30);
}
html[data-theme="dark"] .target-row.selected { background: var(--success-strong); }
html[data-theme="dark"] .target-row.selected:hover { background: var(--success-strong); filter: brightness(1.1); }
/* Gruppen ohne Mitglieder — analog zu Apps ohne Zuweisungen */
.target-row.empty .target-name,
.target-row.empty a.target-link {
color: var(--error);
}
.target-row.empty a.target-link:hover {
filter: brightness(0.9);
}
.target-row.empty .target-meta {
color: var(--error);
opacity: 0.7;
}
/* Flash-Animation beim Springen aus Pin-Chip */
@keyframes flash-row {
0% { background: var(--success-shadow); }
100% { background: var(--success-soft); }
}
.target-row.flash { animation: flash-row 1.2s ease-out; }
/* Pinned-Targets — kompakte Chip-Leiste, immer sichtbar oberhalb der Liste */
.pinned-targets {
background: var(--success-bg);
border-top: 1px solid var(--success-strong);
border-bottom: 1px solid var(--success-strong);
padding: 8px 16px 10px 16px;
max-height: 160px;
overflow-y: auto;
flex-shrink: 0;
}
.pin-head {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.pin-head-title {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--success);
}
.pin-head-count {
font-size: 11px;
background: var(--success);
color: white;
padding: 1px 7px;
border-radius: 10px;
font-weight: 600;
}
.pin-clear-all {
margin-left: auto;
font-size: 11.5px;
color: var(--muted);
}
.pin-chips {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.pin-chip {
display: inline-flex;
align-items: center;
gap: 6px;
background: var(--canvas);
border: 1px solid var(--success-shadow);
border-radius: 12px;
padding: 2px 4px 2px 8px;
font-size: 12px;
cursor: pointer;
transition: all var(--tx);
max-width: 100%;
}
.pin-chip:hover {
background: var(--success-strong);
border-color: var(--success);
}
.pin-chip.pin-empty {
border-color: var(--error-border);
}
.pin-chip.pin-empty .pin-name { color: var(--error); }
.pin-mode {
font-size: 9.5px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--success);
background: var(--success-soft);
padding: 1px 5px;
border-radius: 6px;
flex-shrink: 0;
}
.pin-name {
color: var(--ink);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 180px;
}
.pin-remove {
appearance: none;
background: transparent;
border: none;
color: var(--muted);
cursor: pointer;
width: 18px; height: 18px;
border-radius: 50%;
display: inline-grid;
place-items: center;
font-size: 14px;
line-height: 1;
flex-shrink: 0;
transition: all var(--tx);
}
.pin-remove:hover {
background: var(--error-soft);
color: var(--error);
}
.target-row input[type=checkbox] {
appearance: none;
width: 16px; height: 16px;
border: 1.5px solid var(--surface-strong);
border-radius: var(--r-xs);
display: inline-grid; place-items: center;
cursor: pointer;
transition: all var(--tx);
flex-shrink: 0;
background: var(--canvas);
}
.target-row input[type=checkbox]:checked {
background: var(--ink);
border-color: var(--ink);
}
.target-row input[type=checkbox]:checked::after {
content: '✓';
font-size: 11px;
color: var(--on-primary);
font-weight: 900;
line-height: 1;
}
.target-name {
flex: 1;
font-size: 13.5px;
color: var(--ink);
word-break: break-word;
font-weight: 500;
letter-spacing: -0.005em;
}
/* Empfaenger-Name als Link → in Entra oeffnen */
a.target-link {
color: inherit;
text-decoration: none;
}
a.target-link:hover {
color: var(--brand-accent);
text-decoration: underline;
text-underline-offset: 2px;
}
.target-meta {
font-size: 12px;
color: var(--muted);
margin-top: 2px;
font-weight: 400;
}
/* Entra-Link-Icon (User/Group im Entra-Portal oeffnen) */
.entra-link {
display: inline-grid;
place-items: center;
width: 22px;
height: 22px;
border-radius: var(--r-sm);
background: transparent;
border: 1px solid transparent;
color: var(--muted);
flex-shrink: 0;
text-decoration: none;
opacity: 0;
transition: all var(--tx);
}
.target-row:hover .entra-link,
.ex-member-row:hover .entra-link { opacity: 1; }
.entra-link:hover {
background: var(--surface-soft);
color: var(--brand-accent);
border-color: var(--hairline);
text-decoration: none;
}
/* Teams: Hover-Farbe im offiziellen Teams-Lila — sofortiger Wiedererkennungswert */
.entra-link.teams-link:hover {
color: #4b53bc;
background: rgba(75, 83, 188, 0.10);
}
html[data-theme="dark"] .entra-link.teams-link:hover {
color: #8a91e3;
background: rgba(138, 145, 227, 0.16);
}
/* Expand-Button auf dept/rpa-Zeilen → Mitglieder inline einsehen */
.row-expand {
width: 24px;
height: 24px;
border-radius: var(--r-sm);
background: transparent;
border: 1px solid var(--hairline);
color: var(--muted);
font-size: 16px;
font-weight: 700;
display: inline-grid;
place-items: center;
flex-shrink: 0;
cursor: pointer;
transition: all var(--tx);
line-height: 1;
}
.row-expand:hover {
background: var(--surface-soft);
color: var(--ink);
border-color: var(--ink);
}
.row-expand.is-open {
background: var(--ink);
color: var(--on-primary);
border-color: var(--ink);
transform: rotate(90deg);
}
/* Inline-Aufklapp-Bereich */
.target-row-wrap {
border-bottom: 1px solid var(--hairline-soft);
}
.target-row-wrap > .target-row { border-bottom: none; }
.target-row-wrap.expanded {
background: var(--surface-soft);
}
.expand-body {
padding: 8px 12px 12px;
border-top: 1px solid var(--hairline);
background: var(--surface-soft);
display: flex;
flex-direction: column;
gap: 8px;
}
.expand-search .input { height: 32px; font-size: 12.5px; }
.expand-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 11.5px;
color: var(--muted);
padding: 0 2px;
}
.expand-count strong { color: var(--ink); font-weight: 700; }
.expand-actions { display: flex; align-items: center; gap: 4px; }
.expand-list {
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
max-height: 280px;
overflow-y: auto;
}
.ex-member-row {
display: flex;
align-items: center;
gap: 10px;
padding: 7px 12px;
border-bottom: 1px solid var(--hairline-soft);
cursor: pointer;
transition: background var(--tx);
min-height: 36px;
}
.ex-member-row:last-child { border-bottom: none; }
.ex-member-row:hover { background: var(--surface-soft); }
.ex-member-row.selected {
background: var(--surface-soft);
border-left: 2px solid var(--ink);
padding-left: 10px;
}
.ex-member-row input[type=checkbox] {
appearance: none;
width: 14px; height: 14px;
border: 1.5px solid var(--surface-strong);
border-radius: var(--r-xs);
display: inline-grid; place-items: center;
cursor: pointer;
transition: all var(--tx);
flex-shrink: 0;
background: var(--canvas);
}
.ex-member-row input[type=checkbox]:checked {
background: var(--ink);
border-color: var(--ink);
}
.ex-member-row input[type=checkbox]:checked::after {
content: '✓';
font-size: 10px;
color: var(--on-primary);
font-weight: 900;
line-height: 1;
}
.ex-member-info { flex: 1; min-width: 0; }
.ex-member-name {
font-size: 12.5px;
font-weight: 500;
color: var(--ink);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ex-member-upn {
font-size: 11px;
color: var(--muted);
font-family: var(--font-mono);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-top: 1px;
}
/* Member-Icons (Entra-Link + Teams-Chat) — rechtsbuendig und immer voll
sichtbar, identisch zur Empfaenger-Liste oben. */
.ex-member-icons {
display: inline-flex;
align-items: center;
gap: 2px;
flex-shrink: 0;
margin-left: auto;
}
.ex-member-icons .entra-link {
opacity: 1;
}
.expand-loading,
.expand-error,
.expand-empty {
padding: 16px;
text-align: center;
font-size: 12.5px;
color: var(--muted);
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
}
.expand-loading {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.expand-error { color: var(--error); }
.expand-foot {
display: flex;
justify-content: flex-end;
}
/* Member-Liste im Modal */
.mm-toolbar {
display: flex;
align-items: center;
gap: 4px;
padding: 0 0 8px;
border-bottom: 1px solid var(--hairline-soft);
margin-bottom: 8px;
}
.member-list {
max-height: 50vh;
overflow-y: auto;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
}
.member-row {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
border-bottom: 1px solid var(--hairline-soft);
cursor: pointer;
transition: background var(--tx);
min-height: 40px;
}
.member-row:last-child { border-bottom: none; }
.member-row:hover { background: var(--surface-soft); }
.member-row.selected {
background: var(--surface-soft);
border-left: 2px solid var(--ink);
padding-left: 10px;
}
.member-row input[type=checkbox] {
appearance: none;
width: 16px; height: 16px;
border: 1.5px solid var(--surface-strong);
border-radius: var(--r-xs);
display: inline-grid; place-items: center;
cursor: pointer;
transition: all var(--tx);
flex-shrink: 0;
background: var(--canvas);
}
.member-row input[type=checkbox]:checked {
background: var(--ink);
border-color: var(--ink);
}
.member-row input[type=checkbox]:checked::after {
content: '✓';
font-size: 11px;
color: var(--on-primary);
font-weight: 900;
line-height: 1;
}
.member-info { flex: 1; min-width: 0; }
.member-name {
font-size: 13.5px;
font-weight: 500;
color: var(--ink);
letter-spacing: -0.005em;
}
.member-upn {
font-size: 11.5px;
color: var(--muted);
font-family: var(--font-mono);
margin-top: 1px;
}
/* =============================================================
APPS LIST — kompakt, 2 Spalten
============================================================= */
.apps-list { border-radius: 0; }
/* Tabellen-Layout: feste Spalten damit alles sauber untereinander steht.
Name nimmt den GANZEN Rest (1fr), andere Spalten so klein wie noetig. */
.app-row {
display: grid;
grid-template-columns:
22px /* status */
minmax(200px, 1fr) /* name + publisher — alles uebrige */
24px /* source-logo (Intune/PMPC) */
58px /* type chip */
92px /* version */
98px /* available */
98px /* required */
26px /* + */
32px /* −R */
32px /* −A */
26px; /* delete */
column-gap: 8px;
padding: 6px 12px;
border-bottom: 1px solid var(--hairline-soft);
transition: background var(--tx);
align-items: center;
/* Reihe waechst bei Bedarf — Default 48px, aber kein hartes Limit damit
lange App-Namen umbrechen koennen ohne abgeschnitten zu werden. */
min-height: 48px;
}
.app-row { cursor: pointer; }
.app-row:hover { background: var(--surface-soft); }
.app-row.has-queued {
background: var(--surface-soft);
box-shadow: inset 2px 0 0 var(--ink);
}
.app-row.is-open {
background: var(--row-selected-bg);
box-shadow: inset 3px 0 0 var(--row-selected-border);
}
.app-row.is-open:hover {
background: var(--row-selected-bg-hover);
}
/* Text und Icons werden vom Frontend auf Kontrast berechnet — vars werden
in applyThemeColors() gesetzt. Fallbacks fuer den allerersten Render. */
.app-row.is-open .app-name {
color: var(--row-selected-text, var(--ink));
font-weight: 600;
}
.app-row.is-open .app-publisher {
color: var(--row-selected-text-muted, var(--muted));
}
.app-row.is-open .app-type,
.app-row.is-open .app-version {
color: var(--row-selected-text-muted, var(--body));
}
/* Icons in markierter Row: volle Sichtbarkeit (overridet die globale
opacity: 0/0.55-Regel) UND Kontrast-Farbe aus applyThemeColors. */
.app-row.is-open .app-name-icons .entra-link,
.app-row.is-open .app-rename-btn,
.app-row.is-open .app-rename-locked,
.app-row.is-open .col-delete .app-delete-btn,
.app-row.is-open .col-delete .app-delete-locked {
color: var(--row-selected-icon, currentColor) !important;
opacity: 0.85;
}
.app-row.is-open .app-name-icons .entra-link:hover,
.app-row.is-open .app-rename-btn:hover,
.app-row.is-open .col-delete .app-delete-btn:hover {
opacity: 1;
color: var(--row-selected-icon-hover, currentColor) !important;
}
/* Source-Logo + Type/Version Chip in markierter Row — Overlay-Vars werden
in applyThemeColors aus der effektiven BG-Helligkeit abgeleitet, daher
passt es automatisch sowohl in Light- als auch Dark-Mode. */
.app-row.is-open .app-source { opacity: 0.95; }
.app-row.is-open .app-type {
background: var(--row-selected-surface-strong, var(--surface-soft));
color: var(--row-selected-text, var(--ink)) !important;
}
.app-row.is-open .app-version {
background: var(--row-selected-surface-strong, var(--surface-soft));
color: var(--row-selected-text, var(--body)) !important;
}
/* Queue-Badge invertieren */
.app-row.is-open .row-queued {
background: var(--row-selected-text, var(--ink));
color: var(--row-selected-bg, var(--on-primary));
}
.app-row-wrap {
border-bottom: 1px solid var(--hairline-soft);
}
.app-row-wrap > .app-row { border-bottom: none; }
.app-row-wrap.expanded {
background: var(--app-expanded-bg);
box-shadow:
inset 0 0 0 1px var(--success-border),
0 6px 14px -8px var(--success-shadow),
0 1px 0 0 var(--success-strong);
border-radius: var(--r-sm, 4px);
margin: 6px 4px 14px 4px;
border-bottom: none;
}
.app-row-wrap.expanded .app-detail {
background: var(--app-expanded-bg, var(--canvas));
}
.app-row-wrap.expanded + .app-row-wrap {
border-top: 1px solid var(--hairline);
}
.app-row-wrap.expanded .app-detail {
border-bottom-left-radius: var(--r-sm, 4px);
border-bottom-right-radius: var(--r-sm, 4px);
}
/* App-Detail-Panel — max. 2 Spalten, lange Inhalte (Zuweisungen,
Detection, ...) spannen ueber beide via .app-detail-section--wide. */
.app-detail {
padding: 14px 18px 18px 44px;
font-size: 12.5px;
color: var(--detail-text, var(--ink));
background: var(--canvas);
border-top: 1px dashed var(--hairline-soft);
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px 28px;
align-items: start;
}
.app-detail .app-detail-section-title {
color: var(--detail-text-muted, var(--muted));
border-bottom-color: var(--detail-border-soft, var(--hairline-soft));
}
.app-detail .app-detail-lbl {
color: var(--detail-text-faint, var(--muted));
}
.app-detail .app-detail-val {
color: var(--detail-text, var(--ink));
}
.app-detail .app-detail-desc {
color: var(--detail-text, var(--ink));
}
/* Mono-Felder (Datei, Setup-Pfad, Befehle), Copy-Buttons und Listen-Border
nutzen die abgeleiteten Overlay-Surfaces, damit sie zur gewaehlten Tint-
Farbe passen — egal ob User Dark/Light Mode oder Custom-Color verwendet. */
.app-detail .app-detail-val.mono {
background: var(--detail-surface, var(--surface-soft));
border-color: var(--detail-border-soft, var(--hairline-soft));
color: var(--detail-text, var(--ink));
}
.app-detail .app-detail-copy {
background: transparent;
border-color: var(--detail-border-soft, var(--hairline-soft));
color: var(--detail-text-muted, var(--muted));
}
.app-detail .app-detail-copy:hover {
background: var(--detail-surface, var(--surface-soft));
border-color: var(--detail-border, var(--surface-strong));
color: var(--detail-text, var(--ink));
}
.app-detail .app-detail-list { color: var(--detail-text, var(--ink)); }
.app-detail .app-detail-notes { color: var(--detail-text-muted, var(--muted)); }
/* Zuweisungs-Block innerhalb des Detail-Panels */
.app-detail .asg-col {
background: var(--detail-surface, var(--surface));
border-color: var(--detail-border-soft, var(--hairline));
}
.app-detail .asg-col-head {
background: var(--detail-surface-strong, var(--surface-soft));
border-bottom-color: var(--detail-border-soft, var(--hairline-soft));
}
.app-detail .asg-row { border-bottom-color: var(--detail-border-soft, var(--hairline-soft)); }
.app-detail .asg-row:hover { background: var(--detail-surface, var(--surface-soft)); }
.app-detail .asg-name { color: var(--detail-text, var(--ink)); }
.app-detail .asg-row.native .asg-name { color: var(--detail-text-faint, var(--muted)); }
.app-detail .asg-native-tag {
background: var(--detail-surface, var(--surface-soft));
color: var(--detail-text-muted, var(--muted));
border-color: var(--detail-border-soft, var(--hairline));
}
.app-detail .asg-empty { color: var(--detail-text-faint, var(--muted)); }
.app-detail .asg-del { color: var(--detail-text-muted, var(--muted)); }
.app-detail .asg-actions .entra-link { color: var(--detail-text-muted, var(--muted)); }
.app-detail .asg-actions .entra-link:hover { color: var(--detail-text, var(--ink)); }
@media (max-width: 1100px) {
.app-detail { grid-template-columns: 1fr; }
}
.app-detail-loading,
.app-detail-error,
.app-detail-empty {
grid-column: 1 / -1;
padding: 8px 0;
color: var(--muted);
font-size: 12.5px;
display: flex;
align-items: center;
gap: 8px;
}
.app-detail-error { color: var(--error); }
.app-detail-section {
min-width: 0;
}
.app-detail-section--wide {
grid-column: 1 / -1;
}
.app-detail-section-title {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--muted);
margin-bottom: 6px;
padding-bottom: 4px;
border-bottom: 1px solid var(--hairline-soft);
}
.app-detail-row {
display: grid;
grid-template-columns: 110px 1fr;
gap: 8px;
padding: 3px 0;
align-items: baseline;
}
.app-detail-lbl {
color: var(--muted);
font-size: 11.5px;
}
.app-detail-val {
color: var(--ink);
word-break: break-word;
display: flex;
align-items: center;
gap: 6px;
}
.app-detail-val.mono {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 11.5px;
background: var(--surface-soft);
padding: 2px 6px;
border-radius: var(--r-xs);
border: 1px solid var(--hairline-soft);
word-break: break-all;
overflow-wrap: anywhere;
min-width: 0;
}
.app-detail-copy {
appearance: none;
background: transparent;
border: 1px solid var(--hairline-soft);
color: var(--muted);
cursor: pointer;
width: 20px; height: 20px;
border-radius: var(--r-xs);
display: inline-grid; place-items: center;
font-size: 11px;
flex-shrink: 0;
transition: all var(--tx);
}
.app-detail-copy:hover { color: var(--ink); border-color: var(--surface-strong); background: var(--surface-soft); }
.app-detail-copy.copied { color: var(--success); border-color: var(--success-border); }
.app-detail-desc {
white-space: pre-wrap;
line-height: 1.5;
color: var(--ink);
}
.app-detail-notes { margin-top: 6px; font-size: 12px; color: var(--muted); }
.app-detail-list {
margin: 0;
padding-left: 18px;
list-style: disc;
color: var(--ink);
}
.app-detail-list li {
padding: 2px 0;
word-break: break-all;
overflow-wrap: anywhere;
line-height: 1.5;
}
/* Apps ohne irgendeine Zuweisung — leicht roetlich, damit sofort auffaellt */
.app-row.no-assignments .app-name {
color: var(--error);
}
.app-row.no-assignments .app-publisher {
color: var(--error);
opacity: 0.7;
}
.col { display: flex; align-items: center; min-width: 0; }
.col-status { justify-content: center; }
/* col-name als Flex-Column wie urspruenglich, mit position:relative — die
Icons werden per absoluter Positionierung an die rechte Mitte gelegt, sodass
sie vertikal in der ganzen Zeilenhoehe zentriert sind (nicht nur in der
oberen Name-Line). */
.col-name { flex-direction: column; align-items: stretch; min-width: 0; gap: 1px; justify-content: center; position: relative; padding-right: 50px; }
.col-source { justify-content: center; }
.col-type { justify-content: flex-start; }
.col-version { justify-content: flex-start; }
.col-avail { justify-content: stretch; }
.col-req { justify-content: stretch; }
.col-create { justify-content: stretch; }
.col-remove-req { justify-content: stretch; }
.col-remove-avail { justify-content: stretch; }
/* Buttons fuellen ihre Spalte komplett — saubere vertikale Linien.
Available/Required: Label klebt links, Count-Badge rechts, damit die
Schrift egal bei wievielen Gruppen immer an derselben Position startet. */
.col-avail .type-btn,
.col-req .type-btn {
width: 100%;
justify-content: flex-start;
padding: 0 10px;
}
.col-create .type-btn,
.col-remove-req .type-btn,
.col-remove-req .type-remove,
.col-remove-avail .type-btn,
.col-remove-avail .type-remove {
width: 100%;
justify-content: center;
padding: 0;
}
.col-avail .type-btn > span:first-child,
.col-req .type-btn > span:first-child {
flex: 1 1 auto;
text-align: left;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.col-avail .type-btn > .type-btn-count,
.col-avail .type-btn > .type-btn-queued,
.col-req .type-btn > .type-btn-count,
.col-req .type-btn > .type-btn-queued {
flex-shrink: 0;
}
.app-name-line {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
min-width: 0;
}
/* Aktions-Icons: absolut positioniert am rechten Rand der col-name, vertikal
ueber die ganze Zeilenhoehe (48 px) zentriert — egal ob die App nur einen
Namen hat oder Name + Publisher (zwei Zeilen).
Das padding-right: 50px auf col-name reserviert den Platz, damit lange
Namen/Publisher nicht unter die Icons rutschen. */
.app-name-icons {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
display: inline-flex;
align-items: center;
gap: 2px;
flex-shrink: 0;
}
/* Source-Logo: dezent, klein, klickbar */
.app-source-link {
display: inline-grid;
place-items: center;
width: 18px;
height: 18px;
border-radius: var(--r-sm);
text-decoration: none;
transition: background var(--tx);
}
.app-source-link:hover { background: var(--surface-soft); }
.app-source {
width: 14px;
height: 14px;
object-fit: contain;
opacity: 0.7;
border-radius: 2px;
transition: opacity var(--tx);
display: block;
}
.app-source-link:hover .app-source { opacity: 1; }
/* Letter-Fallback wenn das Vendor-Logo nicht ausgeliefert werden kann
(z.B. fehlende Datei). Wird per onerror in app.js eingehaengt. */
.app-source.app-source-letter {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: 700;
color: var(--ink);
background: var(--surface-soft);
text-transform: uppercase;
line-height: 1;
}
.cell-empty {
color: var(--surface-strong);
font-size: 12px;
font-weight: 500;
}
.app-name {
font-size: 13.5px;
font-weight: 600;
color: var(--ink);
/* App-Namen NIE truncieren — bei Bedarf in mehrere Zeilen umbrechen.
overflow-wrap: anywhere greift auch fuer Namen ohne Leerzeichen. */
white-space: normal;
overflow: visible;
overflow-wrap: anywhere;
word-break: normal;
letter-spacing: -0.01em;
min-width: 0;
text-decoration: none;
display: inline;
max-width: 100%;
line-height: 1.35;
}
a.app-name:hover {
color: var(--brand-accent);
text-decoration: underline;
text-underline-offset: 2px;
}
.app-row.no-assignments a.app-name { color: var(--error); }
.app-row.no-assignments a.app-name:hover { filter: brightness(0.9); }
.app-meta {
display: inline-flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.app-type {
font-size: 10px;
padding: 2px 7px;
border-radius: var(--r-xs);
background: var(--surface-card);
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.4px;
font-weight: 600;
flex-shrink: 0;
}
.app-version {
font-size: 10.5px;
padding: 2px 7px;
border-radius: var(--r-xs);
background: var(--surface-soft);
color: var(--body);
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
font-weight: 500;
flex-shrink: 1;
min-width: 0;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
.app-publisher {
font-size: 12px;
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
max-width: 100%;
display: block;
}
.row-status {
display: inline-grid;
place-items: center;
width: 18px; height: 18px;
font-size: 11px;
font-weight: 800;
flex-shrink: 0;
line-height: 1;
border-radius: 50%;
cursor: help;
}
.row-status.full { background: var(--success-soft); color: var(--success); }
.row-status.partial { background: var(--warning-soft); color: var(--warning); }
.row-queued {
background: var(--ink);
color: var(--on-primary);
font-size: 10px;
font-weight: 700;
padding: 1px 7px;
border-radius: var(--r-pill);
flex-shrink: 0;
font-variant-numeric: tabular-nums;
letter-spacing: 0.2px;
}
.app-row-actions {
display: flex;
align-items: center;
flex-wrap: nowrap;
gap: 6px;
justify-content: flex-end;
}
/* Sammel-Buttons "Available" / "Required" / "+" */
.type-btn {
display: inline-flex;
align-items: center;
gap: 5px;
height: 28px;
padding: 0 12px;
border-radius: var(--r-md);
font-size: 12px;
font-weight: 600;
font-family: inherit;
background: var(--canvas);
border: 1px solid var(--hairline);
color: var(--ink);
cursor: pointer;
transition: all var(--tx);
letter-spacing: -0.005em;
white-space: nowrap;
flex-shrink: 0;
}
.type-btn:hover:not(:disabled) {
background: var(--surface-soft);
border-color: var(--ink);
}
.type-btn:active:not(:disabled) { transform: scale(0.98); }
.type-btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* Subtile Intent-Faerbung */
.type-available { color: var(--brand-accent); border-color: var(--accent-soft); }
.type-available:hover:not(:disabled) { background: var(--accent-bg); border-color: var(--brand-accent); }
.type-required { color: var(--pink); border-color: var(--pink-soft); }
.type-required:hover:not(:disabled) { background: var(--pink-soft); border-color: var(--pink); }
/* Im Warenkorb → schwarz mit weisser Schrift */
.type-btn.has-queued {
background: var(--ink);
border-color: var(--ink);
color: var(--on-primary);
}
.type-btn.has-queued:hover { background: var(--primary-active); border-color: var(--primary-active); }
/* Mitgliedschafts-State */
.type-btn.member-full {
background: var(--success-soft);
border-color: var(--success-border);
color: var(--success);
}
.type-btn.member-partial {
background: var(--warning-soft);
border-color: var(--warning-border);
color: var(--warning);
}
/* Native-Only (All Users / All Devices) */
.type-btn.native-only {
background: var(--surface-card);
border-color: var(--hairline);
color: var(--muted);
font-style: italic;
}
/* "+" Button */
.type-create {
width: 28px;
padding: 0;
font-size: 16px;
color: var(--muted);
border-style: dashed;
justify-content: center;
}
.type-create:hover:not(:disabled) {
color: var(--ink);
border-color: var(--ink);
border-style: solid;
}
.type-remove {
width: 100%;
padding: 0;
font-size: 11px;
font-weight: 600;
color: var(--muted);
border-style: dashed;
justify-content: center;
letter-spacing: -0.5px;
}
.type-remove:hover:not(:disabled) {
color: var(--danger, #e55);
border-color: var(--danger, #e55);
border-style: solid;
}
.type-remove--empty {
visibility: hidden;
pointer-events: none;
border: none;
}
/* Anzahl-Hinweis (z.B. "Available 3" wenn 3 Available-Gruppen existieren) */
.type-btn-count {
display: inline-grid;
place-items: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
border-radius: var(--r-pill);
background: var(--surface-card);
color: var(--muted);
font-size: 10px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.type-btn.has-queued .type-btn-count {
background: rgba(255,255,255,0.18);
color: var(--on-primary);
}
.type-btn.member-full .type-btn-count { background: var(--success-strong); color: var(--success); }
.type-btn.member-partial .type-btn-count { background: var(--warning-strong); color: var(--warning); }
/* Im-Warenkorb-Counter */
.type-btn-queued {
display: inline-grid;
place-items: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
border-radius: var(--r-pill);
background: var(--on-primary);
color: var(--ink);
font-size: 10px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
/* =============================================================
GROUP PICKER POPOVER
============================================================= */
.group-picker {
position: fixed;
z-index: 800;
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
box-shadow: var(--shadow-lg);
min-width: 280px;
max-width: 420px;
overflow: hidden;
animation: picker-in 140ms cubic-bezier(0.2, 0.8, 0.3, 1);
}
@keyframes picker-in {
from { transform: translateY(-4px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.picker-head {
padding: 10px 14px;
font-size: 12px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.5px;
border-bottom: 1px solid var(--hairline);
background: var(--surface-soft);
}
.picker-list {
max-height: 320px;
overflow-y: auto;
}
.picker-item {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
padding: 10px 14px;
background: transparent;
border: none;
border-bottom: 1px solid var(--hairline-soft);
font-size: 13px;
font-family: inherit;
color: var(--ink);
text-align: left;
cursor: pointer;
transition: background var(--tx);
}
.picker-item:last-child { border-bottom: none; }
.picker-item:hover { background: var(--surface-soft); }
.picker-item.queued { background: rgba(17,17,17,0.04); font-weight: 600; }
.picker-check {
width: 18px;
height: 18px;
display: inline-grid;
place-items: center;
flex-shrink: 0;
font-weight: 800;
color: var(--ink);
}
.picker-name {
flex: 1;
word-break: break-all;
font-family: var(--font-mono);
font-size: 12px;
}
.picker-mb {
font-size: 10px;
font-weight: 700;
padding: 2px 6px;
border-radius: var(--r-xs);
letter-spacing: 0.3px;
flex-shrink: 0;
}
.picker-mb.full { background: var(--success-soft); color: var(--success); }
.picker-mb.partial { background: var(--warning-soft); color: var(--warning); }
/* A/R Marker — sehr dezent, nur farbiger Punkt mit Buchstabe */
.pill-group-marker {
display: inline-grid;
place-items: center;
width: 16px; height: 16px;
font-size: 9px;
font-weight: 700;
border-radius: var(--r-xs);
margin-right: 2px;
flex-shrink: 0;
letter-spacing: 0;
}
.pill-group-marker.avail { background: var(--accent-soft); color: var(--brand-accent); }
.pill-group-marker.req { background: var(--pink-soft); color: var(--pink); }
.pill-divider {
width: 1px;
height: 16px;
background: var(--hairline);
margin: 0 6px;
flex-shrink: 0;
}
/* "+ Required-Gruppe" — nur sichtbar bei Hover oder wenn Apps keine Required-Pillen hat */
.pill-create {
opacity: 0;
transition: opacity var(--tx);
}
.app-row:hover .pill-create,
.app-row .pill-create.always-show {
opacity: 1;
}
/* =============================================================
PILLS — Cal.com style: white, hairline border, ink hover
============================================================= */
.group-pill {
position: relative;
display: inline-flex;
align-items: center;
gap: 4px;
padding: 3px 10px;
border-radius: var(--r-sm);
font-size: 12px;
background: var(--canvas);
border: 1px solid var(--hairline);
color: var(--ink);
cursor: pointer;
transition: all var(--tx);
font-weight: 500;
max-width: 100%;
height: 24px;
line-height: 1;
letter-spacing: -0.005em;
}
.group-pill.pill-available {
border-color: var(--accent-soft);
}
.group-pill.pill-required {
border-color: var(--pink-soft);
}
.group-pill:hover:not(:disabled):not(.queued) {
border-color: var(--ink);
background: var(--surface-soft);
box-shadow: var(--shadow-xs);
}
.group-pill.queued {
background: var(--ink);
border-color: var(--ink);
color: var(--on-primary);
font-weight: 600;
padding-left: 8px;
}
.group-pill.queued::before {
content: '✓';
font-size: 11px;
font-weight: 700;
color: var(--on-primary);
margin-right: 2px;
}
.group-pill.queued:hover { background: var(--primary-active); }
.group-pill.member-full {
background: var(--success-bg);
border-color: var(--success-border);
color: var(--success);
}
.group-pill.member-partial {
background: var(--warning-bg);
border-color: var(--warning-border);
color: var(--warning);
}
.group-pill.native {
background: var(--surface-card);
border-color: var(--hairline);
color: var(--muted);
cursor: not-allowed;
font-style: italic;
}
.group-pill.unknown {
background: var(--error-bg);
border: 1px dashed var(--error-border);
color: var(--muted);
cursor: not-allowed;
font-style: italic;
}
.group-pill .pill-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 160px;
}
.group-pill .pill-ico {
font-size: 11px;
margin-left: 2px;
opacity: 0.85;
}
.pill-create {
background: transparent;
border: 1px dashed var(--surface-strong);
color: var(--muted);
width: 24px;
padding: 0;
font-size: 14px;
font-weight: 600;
display: inline-grid;
place-items: center;
flex-shrink: 0;
}
.pill-create:hover {
border-color: var(--ink);
color: var(--ink);
border-style: solid;
background: var(--surface-soft);
}
.no-assignments {
font-size: 12px;
color: var(--muted);
font-style: italic;
}
/* =============================================================
SIDE PANEL (Cart / Existing)
============================================================= */
.side-tabs {
display: grid;
grid-template-columns: 1fr 1fr;
border-bottom: 1px solid var(--hairline);
}
.side-tab {
position: relative;
padding: 12px 14px;
background: transparent;
border: none;
color: var(--muted);
font-size: 13px;
font-weight: 500;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
transition: color var(--tx);
letter-spacing: -0.005em;
min-height: 56px;
line-height: 1.25;
}
.side-tab:hover { color: var(--ink); }
.side-tab.active { color: var(--ink); font-weight: 600; }
.side-tab.active::after {
content: '';
position: absolute;
inset: auto 0 -1px 0;
height: 2px;
background: var(--ink);
}
.side-pane { padding: 16px; display: flex; flex-direction: column; gap: 12px; flex: 1; min-height: 0; }
.side-pane.hidden { display: none; }
.side-pane-hint {
font-size: 12.5px;
color: var(--muted);
padding: 2px;
line-height: 1.5;
}
.session-list {
flex: 1;
min-height: 120px;
max-height: 36vh;
overflow-y: auto;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
background: var(--canvas);
}
.session-item {
padding: 10px 12px;
border-bottom: 1px solid var(--hairline-soft);
display: flex;
align-items: center;
gap: 8px;
transition: background var(--tx);
}
.session-item:hover { background: var(--surface-soft); }
.session-item:last-child { border-bottom: none; }
.session-info { flex: 1; min-width: 0; }
.session-app {
font-size: 13px;
font-weight: 600;
color: var(--ink);
word-break: break-word;
letter-spacing: -0.005em;
}
.session-grp {
font-size: 11.5px;
color: var(--muted);
margin-top: 2px;
word-break: break-all;
font-family: var(--font-mono);
}
.session-scope {
margin-top: 4px;
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.scope-tag {
font-size: 10px;
font-weight: 700;
padding: 1px 6px;
border-radius: var(--r-xs);
letter-spacing: 0.2px;
}
.scope-tag.scope-dept { background: var(--teal-soft); color: var(--teal-deep); }
.scope-tag.scope-user { background: var(--violet-soft); color: var(--violet); }
.scope-target {
font-size: 11.5px;
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
.session-type-badge {
font-size: 9px;
font-weight: 700;
padding: 2px 6px;
border-radius: var(--r-xs);
text-transform: uppercase;
flex-shrink: 0;
letter-spacing: 0.4px;
}
.session-type-badge.avail { background: var(--accent-soft); color: var(--brand-accent); }
.session-type-badge.req { background: var(--pink-soft); color: var(--pink); }
.session-remove {
background: transparent;
border: none;
color: var(--muted);
width: 24px; height: 24px;
border-radius: var(--r-sm);
font-size: 17px;
flex-shrink: 0;
display: grid; place-items: center;
transition: all var(--tx);
}
.session-remove:hover { background: var(--error-bg); color: var(--error); }
.session-summary {
background: var(--surface-soft);
border-radius: var(--r-md);
padding: 12px 14px;
}
.summary-section {
margin-bottom: 10px;
}
.summary-section:last-of-type { margin-bottom: 4px; }
.summary-section-title {
font-size: 10.5px;
font-weight: 700;
text-transform: uppercase;
color: var(--muted);
letter-spacing: 0.5px;
margin-bottom: 4px;
}
.summary-row {
display: flex;
justify-content: space-between;
font-size: 13px;
padding: 2px 0;
color: var(--body);
}
.summary-row.sub {
font-size: 12.5px;
padding-left: 4px;
}
.summary-row span:last-child {
color: var(--ink);
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.summary-row.total {
border-top: 1px solid var(--hairline);
margin-top: 8px;
padding-top: 10px;
font-size: 14px;
font-weight: 700;
color: var(--ink);
}
.summary-row.total span:last-child {
font-size: 20px;
font-weight: 700;
letter-spacing: -0.02em;
}
/* =============================================================
EXISTING list
============================================================= */
.existing-list {
flex: 1;
overflow-y: auto;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
background: var(--canvas);
min-height: 120px;
}
.existing-item {
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-bottom: 1px solid var(--hairline-soft);
}
.existing-item:last-child { border-bottom: none; }
.existing-app {
flex: 1;
font-size: 12.5px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
color: var(--ink);
}
.existing-flags { display: flex; gap: 4px; flex-shrink: 0; }
.exist-flag {
font-size: 9px;
font-weight: 700;
padding: 2px 6px;
border-radius: var(--r-xs);
letter-spacing: 0.3px;
}
.exist-flag.a { background: var(--accent-soft); color: var(--brand-accent); }
.exist-flag.r { background: var(--pink-soft); color: var(--pink); }
.exist-flag.n { background: var(--surface-card); color: var(--muted); }
/* =============================================================
EMPTY STATE
============================================================= */
.empty-state {
text-align: center;
padding: 40px 20px;
color: var(--muted);
font-size: 13px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.empty-state.small { padding: 24px 16px; font-size: 12px; }
.empty-ico { font-size: 28px; opacity: 0.5; }
.empty-title {
color: var(--ink);
font-weight: 600;
font-size: 14px;
letter-spacing: -0.01em;
}
.empty-text {
font-size: 13px;
color: var(--muted);
max-width: 280px;
line-height: 1.55;
}
/* =============================================================
ONBOARDING — Device-Code Login
============================================================= */
.onboarding {
flex: 1;
display: flex;
align-items: flex-start;
justify-content: center;
padding: 80px 24px 40px;
background: var(--canvas);
}
.onboarding.hidden { display: none; }
.onboarding-card {
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-xl);
padding: 56px 56px 48px;
max-width: 540px;
width: 100%;
text-align: center;
box-shadow: var(--shadow-md);
}
.onboarding-icon {
width: 64px;
height: 64px;
margin: 0 auto 20px;
display: grid;
place-items: center;
background: var(--ink);
color: var(--on-primary);
border-radius: var(--r-lg);
}
.onboarding-icon-error {
background: var(--error-soft);
color: var(--error);
}
.onboarding-title {
font-size: 28px;
font-weight: 600;
letter-spacing: -0.025em;
color: var(--ink);
margin-bottom: 12px;
line-height: 1.2;
}
.onboarding-text {
color: var(--body);
font-size: 15px;
line-height: 1.55;
margin-bottom: 24px;
max-width: 400px;
margin-left: auto;
margin-right: auto;
}
.onboarding-meta {
margin-top: 24px;
font-size: 12px;
color: var(--muted);
line-height: 1.55;
padding-top: 24px;
border-top: 1px solid var(--hairline-soft);
}
/* Device-Code-Block */
.dc-step {
font-size: 12px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 8px;
}
.dc-code-block {
display: flex;
align-items: center;
gap: 12px;
justify-content: center;
margin: 8px 0 16px;
}
.dc-code {
font-family: var(--font-mono);
font-size: 28px;
font-weight: 600;
letter-spacing: 0.15em;
background: var(--surface-soft);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
padding: 14px 22px;
color: var(--ink);
user-select: all;
}
.dc-copy { flex-shrink: 0; }
.dc-open-btn {
margin: 4px 0 8px;
text-decoration: none;
}
.dc-open-btn:hover { text-decoration: none; }
.dc-waiting {
display: inline-flex;
align-items: center;
gap: 10px;
margin-top: 16px;
padding: 10px 16px;
background: var(--surface-soft);
border-radius: var(--r-pill);
font-size: 13px;
color: var(--muted);
font-weight: 500;
}
.dc-spinner-wrap { display: flex; justify-content: center; margin-bottom: 24px; }
/* =============================================================
TOASTS
============================================================= */
.toasts {
position: fixed;
bottom: 24px;
right: 24px;
display: flex;
flex-direction: column;
gap: 10px;
z-index: 3000;
pointer-events: none;
}
.toast {
pointer-events: auto;
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
padding: 12px 14px;
font-size: 13px;
display: flex;
align-items: flex-start;
gap: 10px;
min-width: 280px;
max-width: 420px;
box-shadow: var(--shadow-md);
animation: slide-in 280ms cubic-bezier(0.2, 0.8, 0.2, 1);
border-left: 3px solid var(--ink);
}
.toast.ok { border-left-color: var(--success); }
.toast.warn { border-left-color: var(--warning); }
.toast.err { border-left-color: var(--error); }
.toast-ico {
flex-shrink: 0;
width: 22px; height: 22px;
border-radius: 50%;
display: grid; place-items: center;
font-size: 12px;
font-weight: 700;
background: var(--surface-card);
color: var(--ink);
}
.toast.ok .toast-ico { background: var(--success-soft); color: var(--success); }
.toast.warn .toast-ico { background: var(--warning-soft); color: var(--warning); }
.toast.err .toast-ico { background: var(--error-soft); color: var(--error); }
.toast-content { flex: 1; min-width: 0; }
.toast-title { font-weight: 600; margin-bottom: 2px; color: var(--ink); }
.toast-msg { font-size: 12.5px; color: var(--body); word-wrap: break-word; }
@keyframes slide-in {
from { transform: translateX(420px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
/* =============================================================
LOADING OVERLAY
============================================================= */
.loading {
position: fixed;
inset: 0;
background: rgba(255,255,255,0.7);
backdrop-filter: blur(4px);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
animation: fade-in 200ms ease-out;
}
.loading-card {
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-lg);
padding: 28px 32px;
display: flex;
align-items: center;
gap: 14px;
box-shadow: var(--shadow-lg);
min-width: 260px;
}
.spinner {
width: 24px; height: 24px;
border-radius: 50%;
border: 2.5px solid var(--surface-strong);
border-top-color: var(--ink);
animation: spin 800ms linear infinite;
flex-shrink: 0;
}
.spinner-sm {
width: 14px; height: 14px;
border-width: 2px;
}
.loading-text {
font-size: 14px;
color: var(--ink);
font-weight: 500;
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
/* Skeleton */
.skeleton {
padding: 12px 16px;
display: flex;
flex-direction: column;
gap: 8px;
}
.sk-line {
height: 12px;
background: linear-gradient(90deg, var(--surface-soft) 0%, var(--surface-card) 50%, var(--surface-soft) 100%);
background-size: 200% 100%;
animation: shimmer 1.4s infinite;
border-radius: var(--r-xs);
}
.sk-line.short { width: 40%; }
.sk-line.med { width: 70%; }
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* =============================================================
MODALS
============================================================= */
.modal {
position: fixed;
inset: 0;
z-index: 1500;
display: flex;
align-items: center;
justify-content: center;
animation: fade-in 200ms ease-out;
}
.modal-backdrop {
position: absolute;
inset: 0;
background: rgba(17,17,17,0.4);
backdrop-filter: blur(4px);
}
.modal-box {
position: relative;
background: var(--canvas);
border-radius: var(--r-lg);
width: 92%;
max-width: 500px;
box-shadow: var(--shadow-lg);
animation: modal-in 240ms cubic-bezier(0.2, 0.8, 0.3, 1);
overflow: hidden;
}
.modal-box.modal-lg { max-width: 720px; }
.modal-box.modal-xl { max-width: 1320px; }
@keyframes modal-in {
from { transform: scale(0.96) translateY(-8px); opacity: 0; }
to { transform: scale(1) translateY(0); opacity: 1; }
}
.modal-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 24px;
border-bottom: 1px solid var(--hairline);
}
.modal-head h3 {
font-size: 17px;
font-weight: 600;
letter-spacing: -0.015em;
color: var(--ink);
}
.modal-close {
background: transparent;
border: none;
color: var(--muted);
font-size: 22px;
width: 32px; height: 32px;
border-radius: var(--r-sm);
transition: all var(--tx);
display: grid; place-items: center;
line-height: 1;
}
.modal-close:hover { background: var(--surface-soft); color: var(--ink); }
.modal-body {
padding: 24px;
/* Hoch genug damit gaengige Modal-Inhalte (Settings, Create-Assignment)
ohne Scrollen passen. Bei extrem langen Inhalten oder kleinen Displays
greift der Scroll als Fallback. */
max-height: 85vh;
overflow-y: auto;
}
.modal-foot {
display: flex;
justify-content: flex-end;
gap: 10px;
padding: 16px 24px;
border-top: 1px solid var(--hairline);
background: var(--surface-soft);
}
.form-group { margin-bottom: 16px; }
.form-group .lbl {
display: block;
font-size: 12px;
color: var(--muted);
margin-bottom: 6px;
font-weight: 600;
letter-spacing: -0.005em;
}
.form-group .input { width: 100%; }
.form-hint {
font-size: 12px;
margin-top: 6px;
color: var(--muted);
font-weight: 500;
}
.form-hint.ok { color: var(--success); }
.form-hint.err { color: var(--error); }
.confirm-text {
font-size: 15px;
margin-bottom: 16px;
line-height: 1.55;
color: var(--body);
}
.confirm-text strong { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.confirm-warn {
font-size: 13px;
color: var(--body);
background: var(--surface-soft);
border: 1px solid var(--hairline);
border-left: 3px solid var(--warning);
border-radius: var(--r-md);
padding: 12px 14px;
}
/* Result Modal */
.res-banner {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-radius: var(--r-md);
font-size: 14px;
font-weight: 600;
margin-bottom: 16px;
border: 1px solid;
}
.res-banner-ok { background: var(--success-soft); border-color: var(--success-shadow); color: var(--success); }
.res-banner-warn { background: var(--warning-soft); border-color: var(--warning-border); color: var(--warning); }
.res-banner-err { background: var(--error-soft); border-color: var(--error-border); color: var(--error); }
.res-banner-ico {
display: inline-grid;
place-items: center;
width: 28px; height: 28px;
border-radius: 50%;
font-size: 16px;
font-weight: 800;
color: #fff;
flex-shrink: 0;
line-height: 1;
}
.res-banner-ok .res-banner-ico { background: var(--success); }
.res-banner-warn .res-banner-ico { background: var(--warning); }
.res-banner-err .res-banner-ico { background: var(--error); }
.result-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-bottom: 18px;
}
.rstat {
background: var(--surface-card);
border-radius: var(--r-md);
padding: 16px 12px;
text-align: center;
display: flex;
flex-direction: column;
gap: 4px;
}
.rstat .num {
font-size: 32px;
font-weight: 700;
font-variant-numeric: tabular-nums;
letter-spacing: -0.025em;
line-height: 1;
color: var(--ink);
}
.rstat .lbl {
font-size: 11px;
text-transform: uppercase;
color: var(--muted);
letter-spacing: 0.5px;
font-weight: 600;
}
.rstat.ok .num { color: var(--success); }
.rstat.warn .num { color: var(--warning); }
.rstat.err .num { color: var(--error); }
.rstat.tot .num { color: var(--ink); }
/* Detail-Liste */
.res-details { margin-bottom: 16px; }
.res-details-head {
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--muted);
margin-bottom: 8px;
padding: 0 2px;
}
.res-details-list {
border: 1px solid var(--hairline);
border-radius: var(--r-md);
max-height: 320px;
overflow-y: auto;
background: var(--canvas);
}
.res-row {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 12px;
border-bottom: 1px solid var(--hairline-soft);
}
.res-row:last-child { border-bottom: none; }
.res-row-ico {
display: inline-grid;
place-items: center;
width: 20px; height: 20px;
border-radius: 50%;
font-size: 12px;
font-weight: 800;
flex-shrink: 0;
margin-top: 1px;
}
.res-row-ok .res-row-ico { background: var(--success-soft); color: var(--success); }
.res-row-warn .res-row-ico { background: var(--warning-soft); color: var(--warning); }
.res-row-err .res-row-ico { background: var(--error-soft); color: var(--error); }
.res-row-main { flex: 1; min-width: 0; }
.res-row-line1 {
font-size: 13.5px;
color: var(--ink);
word-break: break-word;
}
.res-row-line1 strong { font-weight: 700; }
.res-row-line2 {
font-size: 11.5px;
color: var(--muted);
font-family: var(--font-mono);
margin-top: 2px;
word-break: break-all;
}
.res-row-type {
font-family: var(--font-body);
font-size: 9.5px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
padding: 1px 6px;
border-radius: var(--r-xs);
background: var(--surface-card);
margin-left: 4px;
vertical-align: middle;
}
.res-row-msg {
font-size: 11.5px;
color: var(--body);
margin-top: 4px;
font-style: italic;
}
.report-link {
text-align: center;
padding: 8px;
}
.report-link .btn {
text-decoration: none;
display: inline-flex;
}
.res-debug { margin-top: 12px; }
.res-debug details {
background: var(--surface-soft);
border: 1px solid var(--hairline);
border-radius: var(--r-md);
padding: 8px 12px;
}
.res-debug summary {
font-size: 11px;
color: var(--muted);
cursor: pointer;
user-select: none;
font-weight: 500;
}
.res-debug pre {
margin-top: 8px;
font-family: var(--font-mono);
font-size: 11px;
background: var(--canvas);
border: 1px solid var(--hairline);
border-radius: var(--r-sm);
padding: 10px;
overflow-x: auto;
color: var(--ink);
}
/* =============================================================
RESPONSIVE
============================================================= */
@media (max-width: 1280px) {
.stepper { display: none; }
.topbar { grid-template-columns: auto 1fr auto; }
}
@media (max-width: 1100px) {
.layout { grid-template-columns: 1fr; }
.panel { position: static; max-height: none; }
.panel-side { order: 99; }
}
@media (max-width: 640px) {
.topbar { padding: 0 14px; height: auto; flex-wrap: wrap; gap: 12px; padding-block: 12px; }
.layout { padding: 12px; }
.mode-segment { grid-template-columns: 1fr; }
.result-stats { grid-template-columns: 1fr 1fr; }
.apps-toolbar { flex-direction: column; }
.apps-toolbar .select { width: 100%; }
.onboarding-card { padding: 32px 24px; }
.dc-code { font-size: 22px; padding: 12px 16px; }
}
/* =============================================================
Erweiterungen 2026-05-18:
- dezente Link-Icons neben Namen
- App-Delete-Button
- Picker mit Side-Actions (Entra, Members-Tab, Delete-Assignment)
- Standalone Members-Seite
============================================================= */
/* Name-Spalten: nicht mehr klickbar, kleines Icon daneben */
.target-name .target-text {
display: inline;
color: inherit;
}
.target-link-icons {
display: inline-flex;
align-items: center;
gap: 2px;
flex-shrink: 0;
margin-left: 4px;
}
.target-row .col-create { /* (no-op, just keeps cascade clean) */ }
.app-name-line .entra-link {
margin-left: 2px;
}
.ex-member-name .entra-link {
margin-left: 4px;
}
/* App-Delete-Button (Spalte ganz rechts) */
.col-delete { justify-content: center; }
.app-delete-btn {
width: 24px;
height: 24px;
display: inline-grid;
place-items: center;
background: transparent;
border: 1px solid transparent;
border-radius: var(--r-sm);
color: var(--muted);
cursor: pointer;
opacity: 0;
transition: all var(--tx);
padding: 0;
flex-shrink: 0;
}
.app-row:hover .app-delete-btn { opacity: 0.7; }
.app-delete-btn:hover {
opacity: 1;
color: var(--error);
background: var(--error-soft, rgba(220, 38, 38, 0.12));
border-color: var(--error);
}
.app-delete-btn.app-delete-locked {
cursor: not-allowed;
opacity: 0.35;
}
.app-row:hover .app-delete-btn.app-delete-locked { opacity: 0.55; }
.app-delete-btn.app-delete-locked:hover {
color: var(--muted);
background: var(--surface-soft);
border-color: var(--hairline);
}
/* Inline-Edit-Icon neben dem App-Namen (Pencil). PMPC-Apps: passives Lock. */
.app-rename-btn {
background: transparent;
border: 1px solid transparent;
padding: 0;
cursor: pointer;
display: inline-grid;
place-items: center;
width: 22px;
height: 22px;
border-radius: var(--r-sm);
color: var(--muted);
opacity: 0;
transition: all var(--tx);
flex-shrink: 0;
}
.app-row:hover .app-rename-btn { opacity: 0.65; }
.app-rename-btn:hover {
opacity: 1;
color: var(--brand-accent);
background: var(--surface-soft);
border-color: var(--hairline);
}
.app-rename-locked {
display: inline-grid;
place-items: center;
width: 22px;
height: 22px;
border-radius: var(--r-sm);
color: var(--muted);
flex-shrink: 0;
opacity: 0;
cursor: not-allowed;
}
.app-row:hover .app-rename-locked { opacity: 0.4; }
/* Rename-Modal */
.ra-old-name {
font-size: 13px;
color: var(--muted);
padding: 6px 0;
word-break: break-word;
font-style: italic;
}
.form-hint-err {
color: var(--error);
font-weight: 500;
min-height: 1.2em;
margin-top: 4px;
}
/* Group-Picker: jede Zeile bekommt Side-Actions rechts */
.picker-row {
display: flex;
align-items: stretch;
gap: 2px;
border-bottom: 1px solid var(--hairline-soft);
}
.picker-row:last-child { border-bottom: none; }
.picker-row.queued { background: rgba(17, 17, 17, 0.04); font-weight: 600; }
.picker-row .picker-item { border-bottom: none; flex: 1; }
.picker-actions {
display: inline-flex;
align-items: center;
gap: 2px;
padding-right: 8px;
flex-shrink: 0;
}
.picker-actions .entra-link {
opacity: 0.55;
}
.picker-row:hover .picker-actions .entra-link { opacity: 1; }
.picker-del {
width: 22px;
height: 22px;
display: inline-grid;
place-items: center;
background: transparent;
border: 1px solid transparent;
border-radius: var(--r-sm);
color: var(--muted);
cursor: pointer;
opacity: 0.55;
transition: all var(--tx);
padding: 0;
}
.picker-row:hover .picker-del { opacity: 0.85; }
.picker-del:hover {
opacity: 1;
color: var(--error);
background: var(--error-soft, rgba(220, 38, 38, 0.12));
border-color: var(--error);
}
/* Members-Standalone-Seite */
body.members-page {
background: var(--canvas);
}
.members-page .topbar .brand-name { font-weight: 600; }
.members-main {
max-width: 980px;
margin: 28px auto;
padding: 0 16px 80px 16px;
}
.members-card {
background: var(--surface);
border: 1px solid var(--hairline);
border-radius: var(--r-lg);
overflow: hidden;
box-shadow: var(--shadow-soft, 0 1px 3px rgba(0,0,0,0.04));
}
.members-head {
padding: 18px 22px 14px 22px;
display: flex;
flex-direction: column;
gap: 6px;
border-bottom: 1px solid var(--hairline-soft);
}
.members-title {
font-size: 18px;
font-weight: 700;
letter-spacing: -0.015em;
margin: 0;
color: var(--ink);
word-break: break-word;
}
.members-meta {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.meta-mono {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
font-size: 11.5px;
background: var(--surface-soft);
color: var(--muted);
padding: 2px 8px;
border-radius: var(--r-xs);
border: 1px solid var(--hairline);
}
.members-toolbar {
display: flex;
gap: 8px;
align-items: center;
padding: 12px 22px;
border-bottom: 1px solid var(--hairline-soft);
background: var(--surface-soft);
}
.members-toolbar .search-wrap { flex: 1; }
.members-list {
max-height: 70vh;
overflow-y: auto;
}
.m-row {
padding: 10px 22px;
border-bottom: 1px solid var(--hairline-soft);
transition: background var(--tx);
}
.m-row:last-child { border-bottom: none; }
.m-row:hover { background: var(--surface-soft); }
.m-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.m-name {
font-size: 13.5px;
color: var(--ink);
font-weight: 500;
display: inline-flex;
align-items: center;
gap: 6px;
}
.m-name .entra-link { opacity: 0.5; }
.m-row:hover .m-name .entra-link { opacity: 1; }
.m-upn {
font-size: 12px;
color: var(--muted);
}
.m-loading {
padding: 32px 22px;
display: flex;
align-items: center;
gap: 10px;
color: var(--muted);
font-size: 13px;
justify-content: center;
}
/* Picker-Item soll innerhalb der Row keinen Rand-Radius brechen */
.picker-row .picker-item { border-radius: 0; }
.picker-row:first-child .picker-item { border-top-left-radius: var(--r-md); }
.picker-row:last-child .picker-item { border-bottom-left-radius: var(--r-md); }
/* Zuweisungen-Sektion im aufgeklappten App-Detail */
.asg-section .asg-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
margin-top: 8px;
}
@media (max-width: 900px) { .asg-section .asg-grid { grid-template-columns: 1fr; } }
.asg-col {
background: var(--surface);
border: 1px solid var(--hairline);
border-radius: var(--r-sm);
overflow: hidden;
}
.asg-col-head {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
background: var(--surface-soft);
border-bottom: 1px solid var(--hairline-soft);
}
.asg-badge {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.4px;
text-transform: uppercase;
padding: 2px 7px;
border-radius: var(--r-xs);
}
.asg-badge.avail { background: var(--accent-soft, rgba(99,102,241,0.15)); color: var(--brand-accent); }
.asg-badge.req { background: var(--pink-soft, rgba(236,72,153,0.15)); color: var(--pink, #ec4899); }
.asg-count {
font-size: 11px;
color: var(--muted);
font-variant-numeric: tabular-nums;
margin-left: auto;
}
.asg-list {
list-style: none;
margin: 0;
padding: 0;
}
.asg-row {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border-bottom: 1px solid var(--hairline-soft);
transition: background var(--tx);
}
.asg-row:last-child { border-bottom: none; }
.asg-row:hover { background: var(--surface-soft); }
.asg-name {
flex: 1;
min-width: 0;
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
font-size: 11.5px;
color: var(--ink);
/* nicht buchstabenweise brechen — overflow-wrap erlaubt nur Notbruch */
overflow-wrap: anywhere;
word-break: normal;
line-height: 1.45;
}
.asg-row.native .asg-name { color: var(--muted); font-style: italic; }
.asg-native-tag {
font-size: 9.5px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.4px;
padding: 1px 6px;
border-radius: var(--r-xs);
background: var(--surface-soft);
color: var(--muted);
border: 1px solid var(--hairline);
}
.asg-mb {
font-size: 10px;
font-weight: 700;
padding: 1px 6px;
border-radius: var(--r-xs);
letter-spacing: 0.3px;
flex-shrink: 0;
}
.asg-mb.full { background: var(--success-soft); color: var(--success); }
.asg-mb.partial { background: var(--warning-soft, rgba(245,158,11,0.15)); color: var(--warning, #f59e0b); }
.asg-actions {
display: inline-flex;
align-items: center;
gap: 2px;
flex-shrink: 0;
}
.asg-actions .entra-link { opacity: 0.55; }
.asg-row:hover .asg-actions .entra-link { opacity: 1; }
.asg-del {
width: 22px;
height: 22px;
display: inline-grid;
place-items: center;
background: transparent;
border: 1px solid transparent;
border-radius: var(--r-sm);
color: var(--muted);
cursor: pointer;
opacity: 0.55;
transition: all var(--tx);
padding: 0;
}
.asg-row:hover .asg-del { opacity: 0.85; }
.asg-del:hover {
opacity: 1;
color: var(--error);
background: var(--error-soft, rgba(220,38,38,0.12));
border-color: var(--error);
}
.asg-empty {
padding: 10px 12px;
font-size: 12px;
color: var(--muted);
font-style: italic;
}
/* =============================================================
Einstellungen-Modal
============================================================= */
.icon-btn-header {
width: 32px;
height: 32px;
border-radius: var(--r-sm);
}
.icon-btn-header svg { display: block; }
/* Disconnect-Button: Hover-Akzent in Fehlerfarbe damit "Trennen" als
destruktive Aktion sofort erkennbar ist. */
#btnDisconnect:hover {
color: var(--error);
background: var(--error-bg);
border-color: transparent;
}
.settings-form { display: flex; flex-direction: column; gap: 18px; }
.settings-sec {
border: 1px solid var(--hairline);
background: var(--surface);
border-radius: var(--r-md);
padding: 14px 16px;
}
.settings-sec.settings-sec-meta { background: var(--surface-soft); }
/* First-Run / Setup-Required-Banner — wird im Settings-Modal-Body und im
Onboarding-Panel verwendet. Optisch warnend, aber dezent (kein rot). */
.banner-warning {
border: 1px solid var(--warning, #f59e0b);
background: color-mix(in srgb, var(--warning, #f59e0b) 12%, var(--surface));
color: var(--ink);
border-radius: var(--r-md);
padding: 10px 14px;
margin: 0 0 14px 0;
font-size: 12.5px;
line-height: 1.45;
}
.banner-warning strong { font-weight: 700; }
.banner-warning a { color: var(--accent); font-weight: 600; }
.banner-warning a:hover { text-decoration: underline; }
/* Setup-Datei aktualisieren */
.content-update-row { display: flex; flex-direction: column; gap: 6px; }
.uc-path-row { display: flex; gap: 8px; align-items: stretch; }
.uc-path-row .input { flex: 1; min-width: 0; }
.uc-path-row .btn { flex-shrink: 0; white-space: nowrap; }
.content-update-progress {
display: flex;
align-items: center;
gap: 8px;
margin-top: 10px;
padding: 8px 12px;
border-radius: var(--r-md);
background: var(--surface-soft);
border: 1px solid var(--hairline-soft);
font-size: 12.5px;
color: var(--ink);
}
/* Konfig-Test-Ergebnisse im Settings-Modal — eine Zeile pro Pruefung,
farbliche Statuspille links. */
.settings-test-result {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
}
.set-test-line {
font-size: 12.5px;
line-height: 1.5;
color: var(--ink);
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 6px;
}
.set-test-line code { font-size: 11.5px; }
.set-test-icon {
display: inline-block;
min-width: 36px;
padding: 1px 6px;
border-radius: var(--r-sm);
font-size: 10.5px;
font-weight: 700;
text-align: center;
letter-spacing: 0.04em;
}
.set-test-icon.ok { background: color-mix(in srgb, var(--success, #10b981) 18%, var(--surface)); color: var(--success, #10b981); }
.set-test-icon.fail { background: color-mix(in srgb, var(--error, #ef4444) 18%, var(--surface)); color: var(--error, #ef4444); }
.set-test-icon.warn { background: color-mix(in srgb, var(--warning, #f59e0b) 18%, var(--surface)); color: var(--warning, #f59e0b); }
.set-test-line.set-test-pending { color: var(--ink-muted); }
.set-test-line.set-test-warn { color: var(--ink-muted); }
.set-test-sample { color: var(--ink-muted); font-size: 11.5px; }
.settings-sec-head { margin-bottom: 10px; }
.settings-sec-head-row {
display: flex;
align-items: flex-start;
gap: 12px;
justify-content: space-between;
}
.settings-sec-head-row > div:first-child { flex: 1; min-width: 0; }
.settings-sec-head-row .btn { flex-shrink: 0; white-space: nowrap; }
.settings-sec-head h4 {
margin: 0 0 2px 0;
font-size: 13px;
font-weight: 700;
letter-spacing: -0.005em;
color: var(--ink);
text-transform: none;
}
.settings-sec-sub {
font-size: 11.5px;
color: var(--muted);
line-height: 1.45;
}
.settings-sec-sub code {
font-family: var(--font-mono);
font-size: 11px;
background: var(--surface-soft);
padding: 1px 5px;
border-radius: var(--r-xs);
color: var(--body);
}
.settings-form .form-group { margin-top: 8px; }
.settings-form .form-group:first-child { margin-top: 0; }
.settings-form .lbl {
display: block;
font-size: 11px;
font-weight: 600;
color: var(--muted);
margin-bottom: 4px;
text-transform: uppercase;
letter-spacing: 0.4px;
}
.settings-form .input {
width: 100%;
padding: 8px 10px;
font-size: 13px;
}
.settings-form textarea.input {
resize: vertical;
min-height: 80px;
line-height: 1.5;
}
.settings-form .input.mono {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
font-size: 12.5px;
}
.settings-form .form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
@media (max-width: 600px) {
.settings-form .form-row { grid-template-columns: 1fr; }
}
.settings-form .form-check-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 6px;
}
.settings-form .form-hint {
font-size: 11.5px;
color: var(--muted);
margin-top: 6px;
}
.settings-form .set-preview {
font-family: var(--font-mono);
font-size: 12px;
background: var(--surface-soft);
padding: 2px 7px;
border-radius: var(--r-xs);
color: var(--ink);
border: 1px solid var(--hairline);
}
.settings-form .set-path {
font-family: var(--font-mono);
font-size: 11px;
color: var(--muted);
word-break: break-all;
}
.modal-foot-spacer { flex: 1; }
/* Branding: Logo-Auswahl */
.logo-row {
display: flex;
align-items: center;
gap: 16px;
}
.logo-preview {
width: 56px; height: 56px;
border-radius: var(--r-md);
background: var(--brand-primary);
color: var(--on-primary);
display: grid; place-items: center;
font-weight: 700;
font-size: 22px;
overflow: hidden;
flex-shrink: 0;
border: 1px solid var(--hairline);
}
.logo-preview:has(.logo-preview-img) { background: var(--surface-soft); }
.logo-preview-img {
width: 100%; height: 100%;
object-fit: contain;
display: block;
}
.logo-actions {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.logo-actions .btn { white-space: nowrap; }
.input.hidden { display: none; }
/* Farben-Grid */
.color-grid { display: flex; flex-direction: column; gap: 6px; }
.color-row {
display: grid;
grid-template-columns: 22px 1fr 36px 92px 28px;
align-items: center;
gap: 10px;
padding: 8px 10px;
border: 1px solid var(--hairline);
border-radius: var(--r-sm);
background: var(--surface);
transition: border-color var(--tx);
}
.color-row:hover { border-color: var(--surface-strong); }
.color-swatch {
width: 22px; height: 22px;
border-radius: var(--r-xs);
border: 1px solid var(--hairline);
display: block;
background: var(--ink);
}
.color-meta { min-width: 0; }
.color-name {
font-size: 12.5px;
font-weight: 600;
color: var(--ink);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.color-desc {
font-size: 11px;
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.color-picker {
width: 36px;
height: 28px;
padding: 0;
border: 1px solid var(--hairline);
border-radius: var(--r-xs);
background: transparent;
cursor: pointer;
}
.color-picker::-webkit-color-swatch-wrapper { padding: 2px; }
.color-picker::-webkit-color-swatch { border: none; border-radius: 3px; }
.color-hex {
font-size: 12px !important;
padding: 4px 8px !important;
text-align: center;
width: 92px;
}
.color-row .link-btn {
font-size: 16px;
line-height: 1;
color: var(--muted);
background: transparent;
border: none;
cursor: pointer;
padding: 4px 6px;
border-radius: var(--r-xs);
}
.color-row .link-btn:hover { color: var(--ink); background: var(--surface-soft); }
@media (max-width: 640px) {
.color-row {
grid-template-columns: 22px 1fr 36px;
grid-template-rows: auto auto;
gap: 6px 10px;
}
.color-row .color-hex { grid-column: 1 / 4; width: 100%; }
.color-row .link-btn { grid-column: 1 / 4; justify-self: flex-end; }
}
/* Statische entra-Links (z.B. in der Members-Seite, der App-Zeile,
im Group-Picker). */
.entra-link-static,
.app-name-line .entra-link,
.picker-actions .entra-link,
.m-name .entra-link {
opacity: 0.55;
}
.app-row:hover .app-name-line .entra-link {
opacity: 1;
}
/* Empfaenger-Liste (links): Icons sind IMMER voll sichtbar — egal ob
Abteilung, RPA-Gruppe oder Einzel-User. Vorher hover-only -> verwirrend. */
.target-link-icons .entra-link {
opacity: 1;
}
/* =============================================================
Help-Modal — TOC-Sidebar links, gerenderter Markdown-Content rechts
============================================================= */
.help-body {
display: grid;
grid-template-columns: 260px 1fr;
gap: 28px;
padding: 32px 28px 24px 28px;
max-height: 80vh;
overflow: hidden;
}
@media (max-width: 800px) {
.help-body { grid-template-columns: 1fr; }
.help-toc { display: none; }
}
.help-toc {
position: sticky;
top: 0;
align-self: start;
max-height: 80vh;
overflow-y: auto;
padding: 0 12px 0 4px;
border-right: 1px solid var(--hairline-soft);
}
.help-toc-title {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
margin-bottom: 16px;
}
.help-toc ul {
list-style: none;
margin: 0;
padding: 0;
}
.help-toc li {
margin: 2px 0;
}
.help-toc a {
display: block;
padding: 6px 12px;
border-radius: var(--r-sm);
font-size: 12.5px;
color: var(--body);
text-decoration: none;
transition: background var(--tx), color var(--tx);
}
.help-toc a:hover {
background: var(--surface-soft);
color: var(--ink);
}
.help-toc a.active {
background: var(--accent-soft);
color: var(--brand-accent);
font-weight: 600;
}
.help-toc a.active:hover {
background: var(--accent-soft);
color: var(--brand-accent);
}
.help-content {
overflow-y: auto;
max-height: 80vh;
padding-right: 12px;
}
.help-content h1:first-child {
margin-top: 0;
margin-bottom: 14px;
}
.help-content h2 {
padding-top: 14px;
border-top: 1px solid var(--hairline-soft);
transition: background var(--tx);
border-radius: var(--r-sm);
}
.help-content h2:first-of-type {
border-top: none;
padding-top: 0;
}
/* Flash beim TOC-Klick */
.help-h-flash {
background: var(--accent-soft);
padding-left: 8px;
padding-right: 8px;
margin-left: -8px;
margin-right: -8px;
animation: helpHFlash 1.2s ease-out;
}
@keyframes helpHFlash {
0%, 100% { background: var(--accent-soft); }
50% { background: transparent; }
}
.help-loading {
padding: 40px 20px;
text-align: center;
color: var(--muted);
font-size: 13px;
}
.help-error {
padding: 16px 20px;
background: var(--error-soft);
color: var(--error);
border: 1px solid var(--error-border);
border-radius: var(--r-md);
}
.help-version-badge {
font-family: var(--font-mono);
font-size: 11px;
color: var(--muted);
padding: 4px 10px;
background: var(--surface-soft);
border: 1px solid var(--hairline-soft);
border-radius: var(--r-pill);
}
/* Help-Modal: padding kommt komplett aus .help-body. KEINE eigene Regel
fuer #modalHelp .modal-body — die wuerde wegen ID-Specificity das
.help-body-Padding aushebeln. */
/* WICHTIG: das Help-Modal-Content-Div hat BEIDE Klassen am selben Element
(<div class="help-content md-content">), deshalb COMPOUND-Selector
(.help-content.md-content) — Descendant-Selector mit Leerzeichen wuerde
NICHT matchen. --detail-text wird global gesetzt (helle Panel-Farbe ->
dunkler readableForeground) und macht die md-content-Headings im Dark
Mode unlesbar. Wir overriden hier mit den Basis-Vars. !important
forciert Sieg gegen die generische .md-content-Regel — Specificity
alleine reicht nicht, weil die Help-/Detail-Regeln gemischt liegen. */
.help-content.md-content { color: var(--ink) !important; }
.help-content.md-content h1,
.help-content.md-content h2,
.help-content.md-content h4 { color: var(--ink) !important; }
.help-content.md-content h3,
.help-content.md-content h5,
.help-content.md-content h6 { color: var(--muted) !important; }
.help-content.md-content p,
.help-content.md-content li,
.help-content.md-content td { color: var(--ink) !important; }
.help-content.md-content del { color: var(--muted) !important; }
.help-content.md-content blockquote {
color: var(--muted) !important;
border-left-color: var(--hairline) !important;
background: var(--surface-soft) !important;
}
.help-content.md-content code {
background: var(--surface-soft) !important;
border-color: var(--hairline-soft) !important;
color: var(--ink) !important;
}
.help-content.md-content pre,
.help-content.md-content th {
background: var(--surface-soft) !important;
border-color: var(--hairline-soft) !important;
color: var(--ink) !important;
}
.help-content.md-content th,
.help-content.md-content td { border-color: var(--hairline-soft) !important; }
.help-content.md-content tr:nth-child(even) td { background: var(--surface-soft) !important; }
.help-content.md-content hr { border-top-color: var(--hairline-soft) !important; }
/* =============================================================
Create-Assignment Modal — zwei Intent-Spalten (Required + Available)
mit je drei Optionen (Neue Gruppe / All Users / All Devices).
Farbliche Unterscheidung via cg-intent-required/-available.
============================================================= */
.cg-intent-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-top: 6px;
}
@media (max-width: 600px) { .cg-intent-grid { grid-template-columns: 1fr; } }
.cg-intent-col {
display: flex;
flex-direction: column;
gap: 6px;
padding: 10px;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
background: var(--surface);
}
/* Intent-Faerbung: Required = pink-ton, Available = accent-blau */
.cg-intent-required { border-top: 3px solid var(--pink); }
.cg-intent-available { border-top: 3px solid var(--brand-accent); }
.cg-intent-head {
display: flex;
flex-direction: column;
gap: 2px;
padding: 0 2px 4px;
}
.cg-intent-badge {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.06em;
padding: 3px 8px;
border-radius: var(--r-xs);
align-self: flex-start;
}
.cg-intent-badge.req { background: var(--pink-soft); color: var(--pink); }
.cg-intent-badge.avail { background: var(--accent-soft); color: var(--brand-accent); }
.cg-intent-sub {
font-size: 11px;
color: var(--muted);
}
.cg-mode {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 12px;
border: 1px solid var(--hairline-soft);
border-radius: var(--r-md);
background: var(--canvas);
cursor: pointer;
transition: all var(--tx);
}
.cg-mode:hover { background: var(--surface-soft); border-color: var(--surface-strong); }
.cg-mode input[type="radio"] {
margin-top: 2px;
flex-shrink: 0;
}
.cg-intent-required .cg-mode input[type="radio"] { accent-color: var(--pink); }
.cg-intent-available .cg-mode input[type="radio"] { accent-color: var(--brand-accent); }
.cg-intent-required .cg-mode:has(input:checked) {
border-color: var(--pink);
background: var(--pink-soft);
}
.cg-intent-available .cg-mode:has(input:checked) {
border-color: var(--brand-accent);
background: var(--accent-soft);
}
.cg-mode-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cg-mode-title {
font-size: 12.5px;
font-weight: 600;
color: var(--ink);
}
.cg-mode-desc {
font-size: 11.5px;
color: var(--muted);
line-height: 1.4;
}
/* Disabled-Card: Option bereits zugewiesen, keine zweite Zuweisung moeglich.
pointer-events: none verhindert Klicks ohne JS-Logik dafuer schreiben zu
muessen. Strike-Through im Title macht visuell sofort klar dass die
Option nicht waehlbar ist. */
.cg-mode--disabled {
opacity: 0.5;
pointer-events: none;
background: var(--surface-soft);
border-color: var(--hairline-soft) !important;
}
.cg-mode--disabled .cg-mode-title {
text-decoration: line-through;
color: var(--muted);
}
.cg-mode--disabled .cg-mode-title::after {
content: ' ✓ aktiv';
font-size: 10px;
font-weight: 600;
letter-spacing: 0.03em;
color: var(--success);
margin-left: 4px;
text-decoration: none;
display: inline-block;
}
.cg-mode--disabled .cg-mode-desc {
font-style: italic;
}
/* =============================================================
App-Detail — Installations-Statistik (Erfolge/Fehler je User/Device)
============================================================= */
.install-stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
margin-top: 6px;
}
@media (max-width: 900px) { .install-stats { grid-template-columns: 1fr; } }
.install-axis {
border: 1px solid var(--detail-border-soft, var(--hairline));
border-radius: var(--r-md);
background: var(--detail-surface, var(--surface));
padding: 10px 12px;
}
.install-axis-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 10px;
margin-bottom: 8px;
}
.install-axis-title {
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--detail-text-muted, var(--muted));
}
.install-axis-rate {
font-size: 11px;
font-weight: 600;
padding: 2px 8px;
border-radius: var(--r-pill);
}
.install-axis-rate.good { background: var(--success-soft); color: var(--success); }
.install-axis-rate.mid { background: var(--warning-soft); color: var(--warning); }
.install-axis-rate.bad { background: var(--error-soft); color: var(--error); }
.install-stats-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 6px;
}
.stat-cell {
text-align: center;
padding: 8px 4px;
border-radius: var(--r-sm);
background: var(--canvas);
border: 1px solid var(--detail-border-soft, var(--hairline-soft));
}
.stat-num {
font-size: 18px;
font-weight: 700;
line-height: 1.1;
font-variant-numeric: tabular-nums;
color: var(--detail-text, var(--ink));
}
.stat-lbl {
font-size: 10px;
color: var(--detail-text-faint, var(--muted));
text-transform: uppercase;
letter-spacing: 0.04em;
margin-top: 2px;
}
.stat-ok .stat-num { color: var(--success); }
.stat-err .stat-num { color: var(--error); }
.stat-pend .stat-num { color: var(--warning); }
.stat-not .stat-num { color: var(--muted); }
.stat-na .stat-num { color: var(--muted-soft); }
/* Stacked-Balken */
.install-bar {
display: flex;
height: 10px;
border-radius: var(--r-pill);
overflow: hidden;
background: var(--hairline);
margin-bottom: 6px;
gap: 1px;
}
.install-bar-seg { height: 100%; min-width: 2px; transition: opacity .15s; }
.install-bar-seg:hover { opacity: .75; }
.install-bar-ok { background: var(--success); }
.install-bar-err { background: var(--error); }
.install-bar-pend { background: var(--warning); }
.install-bar-not { background: var(--muted); }
.install-bar-na { background: var(--hairline-soft); }
/* Balken-Legende */
.install-bar-legend {
display: flex;
flex-wrap: wrap;
gap: 4px 10px;
margin-bottom: 10px;
}
.ibl {
font-size: 10.5px;
color: var(--muted);
display: flex;
align-items: center;
gap: 4px;
}
.ibl::before {
content: '';
display: inline-block;
width: 9px; height: 9px;
border-radius: 2px;
}
.ibl-ok::before { background: var(--success); }
.ibl-err::before { background: var(--error); }
.ibl-pend::before { background: var(--warning); }
.ibl-not::before { background: var(--muted); }
.ibl-na::before { background: var(--hairline-soft); border: 1px solid var(--hairline); }
/* =============================================================
App-Detail — Flow-Visualisierung (Dependencies + Supersedence)
============================================================= */
.flow-subtitle {
font-size: 12px;
color: var(--detail-text-muted, var(--muted));
margin: -2px 0 8px;
}
.flow-container {
width: 100%;
overflow-x: auto;
padding: 4px 0;
}
.flow-svg {
display: block;
color: var(--detail-text-faint, var(--muted));
min-width: 640px;
}
.flow-arrow {
fill: none;
stroke: currentColor;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
opacity: 0.7;
}
.flow-arrow-label {
font-size: 10.5px;
font-family: var(--font-mono);
fill: var(--detail-text-muted, var(--muted));
pointer-events: none;
font-weight: 600;
}
/* Label-Hintergrund — damit der Text nicht in die Linie reinlaeuft */
.flow-arrow-label-bg {
fill: var(--detail-surface, var(--canvas));
stroke: var(--detail-border-soft, var(--hairline-soft));
stroke-width: 1;
}
.flow-node-wrap {
width: 100%;
height: 100%;
display: block;
}
.flow-node {
width: 100%;
height: 100%;
border: 1.5px solid var(--detail-border, var(--hairline));
border-radius: var(--r-md);
background: var(--canvas);
padding: 8px 12px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 1px;
overflow: hidden;
box-sizing: border-box;
transition: all var(--tx);
}
.flow-node-name {
font-size: 12.5px;
font-weight: 600;
color: var(--detail-text, var(--ink));
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.flow-node-meta {
font-size: 10.5px;
color: var(--detail-text-faint, var(--muted));
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.flow-node-center {
border-color: var(--brand-accent);
background: var(--accent-soft);
}
.flow-node-center .flow-node-name { color: var(--brand-accent); }
.flow-node-known {
cursor: pointer;
}
.flow-node-known:hover {
border-color: var(--brand-accent);
box-shadow: 0 2px 8px -2px var(--accent-soft);
}
.flow-node-known:focus-visible {
outline: 2px solid var(--brand-accent);
outline-offset: 1px;
}
/* Klartext-Erklaerungen unter dem Flow-Diagramm — beschreibt was die
Visualisierung in der UI tatsaechlich bedeutet (in welcher Reihenfolge
Intune installiert, was bei Supersedence passiert, etc.). */
.flow-explanations {
margin-top: 14px;
padding: 12px 16px 14px;
background: var(--detail-surface, var(--surface-soft));
border: 1px solid var(--detail-border-soft, var(--hairline-soft));
border-radius: var(--r-md);
border-left: 3px solid var(--brand-accent);
}
.flow-explanations-title {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--detail-text-muted, var(--muted));
margin-bottom: 6px;
}
.flow-explanations ul {
margin: 0;
padding: 0;
list-style: none;
}
.flow-explanations li {
padding: 4px 0;
font-size: 13px;
color: var(--detail-text, var(--ink));
line-height: 1.55;
}
.flow-explanations li + li {
border-top: 1px dashed var(--detail-border-soft, var(--hairline-soft));
margin-top: 4px;
padding-top: 8px;
}
.flow-explanations strong {
font-weight: 600;
color: var(--detail-text, var(--ink));
}
/* Flash-Animation wenn man via Flow-Klick zu einer App springt */
.app-row-wrap--flash {
animation: rowFlash 1.2s ease-out;
}
@keyframes rowFlash {
0%, 100% { box-shadow: none; }
30% { box-shadow: 0 0 0 3px var(--brand-accent); }
}
/* =============================================================
Markdown-Content (App-Beschreibung). Wird in renderMarkdown
per marked.js zu HTML. Styling so, dass es sich in das
App-Detail-Panel einfuegt — keine grossen Headings, alles dezent.
============================================================= */
.md-content { line-height: 1.55; }
.md-content > *:first-child { margin-top: 0; }
.md-content > *:last-child { margin-bottom: 0; }
.md-content p { margin: 0 0 8px 0; }
.md-content h1, .md-content h2, .md-content h3,
.md-content h4, .md-content h5, .md-content h6 {
margin: 14px 0 6px;
font-weight: 700;
line-height: 1.25;
color: var(--detail-text, var(--ink));
letter-spacing: -0.005em;
}
.md-content h1 { font-size: 15px; }
.md-content h2 { font-size: 14px; }
.md-content h3 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--detail-text-muted, var(--muted)); }
.md-content h4 { font-size: 12.5px; }
.md-content h5, .md-content h6 { font-size: 12px; color: var(--detail-text-muted, var(--muted)); }
.md-content strong { font-weight: 700; }
.md-content em { font-style: italic; }
.md-content del { text-decoration: line-through; color: var(--detail-text-muted, var(--muted)); }
.md-content a {
color: var(--brand-accent);
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color var(--tx);
}
.md-content a:hover { border-bottom-color: var(--brand-accent); }
.md-content ul, .md-content ol {
margin: 0 0 8px 0;
padding-left: 22px;
}
.md-content li { padding: 1px 0; }
.md-content li > p { margin: 0; }
.md-content blockquote {
margin: 0 0 8px 0;
padding: 4px 12px;
border-left: 3px solid var(--detail-border, var(--hairline));
color: var(--detail-text-muted, var(--muted));
font-style: italic;
background: var(--detail-surface, var(--surface-soft));
border-radius: 0 var(--r-xs) var(--r-xs) 0;
}
.md-content code {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 11.5px;
padding: 1px 5px;
border-radius: var(--r-xs);
background: var(--detail-surface, var(--surface-soft));
border: 1px solid var(--detail-border-soft, var(--hairline-soft));
color: var(--detail-text, var(--ink));
word-break: break-all;
}
.md-content pre {
margin: 0 0 8px 0;
padding: 10px 12px;
border-radius: var(--r-sm);
background: var(--detail-surface, var(--surface-soft));
border: 1px solid var(--detail-border-soft, var(--hairline-soft));
overflow-x: auto;
line-height: 1.45;
}
.md-content pre code {
background: transparent;
border: none;
padding: 0;
font-size: 11.5px;
white-space: pre;
word-break: normal;
}
.md-content table {
width: 100%;
border-collapse: collapse;
margin: 0 0 8px 0;
font-size: 12px;
}
.md-content th, .md-content td {
border: 1px solid var(--detail-border-soft, var(--hairline-soft));
padding: 5px 8px;
text-align: left;
vertical-align: top;
}
.md-content th {
background: var(--detail-surface, var(--surface-soft));
font-weight: 700;
color: var(--detail-text, var(--ink));
font-size: 11.5px;
}
.md-content tr:nth-child(even) td {
background: var(--detail-surface, transparent);
}
.md-content hr {
border: none;
border-top: 1px solid var(--detail-border-soft, var(--hairline-soft));
margin: 12px 0;
}
.md-content img {
max-width: 100%;
height: auto;
border-radius: var(--r-xs);
}
/* =============================================================
flatpickr (Date-Picker Popup) — Dark-Mode-Theming
Light-Mode nutzt den Default des Pakets, im Dark-Mode passen wir
die wichtigsten Tokens an unsere Surface-/Ink-Vars an.
============================================================= */
html[data-theme="dark"] .flatpickr-calendar {
background: var(--surface-soft);
color: var(--ink);
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
border: 1px solid var(--hairline);
}
html[data-theme="dark"] .flatpickr-calendar.arrowTop:before,
html[data-theme="dark"] .flatpickr-calendar.arrowBottom:before {
border-bottom-color: var(--hairline);
border-top-color: var(--hairline);
}
html[data-theme="dark"] .flatpickr-calendar.arrowTop:after,
html[data-theme="dark"] .flatpickr-calendar.arrowBottom:after {
border-bottom-color: var(--surface-soft);
border-top-color: var(--surface-soft);
}
html[data-theme="dark"] .flatpickr-months,
html[data-theme="dark"] .flatpickr-month {
color: var(--ink);
fill: var(--ink);
background: transparent;
}
html[data-theme="dark"] .flatpickr-current-month input.cur-year,
html[data-theme="dark"] .flatpickr-current-month .cur-month {
color: var(--ink);
}
html[data-theme="dark"] .flatpickr-monthDropdown-months {
background: var(--surface-soft);
color: var(--ink);
}
html[data-theme="dark"] .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month {
background: var(--surface-soft);
}
html[data-theme="dark"] .flatpickr-weekdays,
html[data-theme="dark"] span.flatpickr-weekday {
color: var(--muted);
background: transparent;
}
html[data-theme="dark"] .flatpickr-day {
color: var(--body);
}
html[data-theme="dark"] .flatpickr-day:hover,
html[data-theme="dark"] .flatpickr-day:focus {
background: var(--surface-strong);
border-color: var(--surface-strong);
color: var(--ink);
}
html[data-theme="dark"] .flatpickr-day.today {
border-color: var(--brand-accent);
color: var(--brand-accent);
}
html[data-theme="dark"] .flatpickr-day.today:hover {
background: var(--brand-accent);
color: var(--on-primary);
}
html[data-theme="dark"] .flatpickr-day.selected,
html[data-theme="dark"] .flatpickr-day.startRange,
html[data-theme="dark"] .flatpickr-day.endRange {
background: var(--brand-accent);
border-color: var(--brand-accent);
color: var(--on-primary);
}
html[data-theme="dark"] .flatpickr-day.flatpickr-disabled,
html[data-theme="dark"] .flatpickr-day.prevMonthDay,
html[data-theme="dark"] .flatpickr-day.nextMonthDay {
color: var(--muted-soft);
}
html[data-theme="dark"] .flatpickr-prev-month,
html[data-theme="dark"] .flatpickr-next-month {
color: var(--ink);
fill: var(--ink);
}
html[data-theme="dark"] .flatpickr-prev-month:hover svg,
html[data-theme="dark"] .flatpickr-next-month:hover svg {
fill: var(--brand-accent);
}
html[data-theme="dark"] .numInputWrapper:hover,
html[data-theme="dark"] .numInputWrapper span.arrowUp,
html[data-theme="dark"] .numInputWrapper span.arrowDown {
background: transparent;
border-color: var(--hairline);
}
/* =============================================================
Gruppen-Export Modal
============================================================= */
.gex-body {
display: flex;
flex-direction: column;
min-height: 420px;
padding: 0 !important;
overflow: hidden;
}
.gex-tab-bar {
display: flex;
border-bottom: 1px solid var(--hairline);
background: var(--surface-soft);
flex-shrink: 0;
}
.gex-tab {
padding: 10px 18px;
font-size: 13px;
font-weight: 500;
color: var(--muted);
background: none;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
margin-bottom: -1px;
transition: color var(--tx), border-color var(--tx);
}
.gex-tab:hover { color: var(--text); }
.gex-tab.active {
color: var(--text);
border-bottom-color: var(--ink);
font-weight: 600;
}
.gex-columns {
display: flex;
flex: 1;
overflow: hidden;
min-height: 0;
}
.gex-left {
width: 300px;
flex-shrink: 0;
border-right: 1px solid var(--hairline);
padding: 16px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.gex-right {
flex: 1;
padding: 16px;
display: flex;
flex-direction: column;
overflow: hidden;
min-width: 0;
}
.gex-section-title {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .06em;
color: var(--muted);
margin-bottom: 8px;
}
.gex-results {
flex: 1;
overflow-y: auto;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
}
.gex-group-item {
padding: 9px 12px;
border-bottom: 1px solid var(--hairline-soft);
cursor: pointer;
transition: background var(--tx);
}
.gex-group-item:last-child { border-bottom: none; }
.gex-group-item:hover { background: var(--surface-soft); }
.gex-group-item.selected {
background: var(--surface-soft);
border-left: 3px solid var(--ink);
padding-left: 9px;
}
.gex-group-name {
font-size: 13px;
font-weight: 500;
color: var(--text);
}
.gex-group-desc {
font-size: 11.5px;
color: var(--muted);
margin-top: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.gex-members-area {
flex: 1;
overflow-y: auto;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
}
.gex-summary {
padding: 8px 12px;
font-size: 12px;
color: var(--muted);
border-bottom: 1px solid var(--hairline-soft);
background: var(--surface-soft);
}
.gex-path-group {
border-bottom: 1px solid var(--hairline-soft);
}
.gex-path-group:last-child { border-bottom: none; }
.gex-path-head {
display: flex;
align-items: center;
gap: 6px;
padding: 7px 12px;
font-size: 12px;
font-weight: 600;
background: var(--surface-soft);
border-bottom: 1px solid var(--hairline-soft);
color: var(--muted);
position: sticky;
top: 0;
z-index: 1;
}
.gex-user-list { }
.gex-user-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-bottom: 1px solid var(--hairline-soft);
font-size: 13px;
cursor: default;
}
.gex-user-item input[type="checkbox"] {
flex-shrink: 0;
cursor: pointer;
}
.gex-user-item input[type="checkbox"] + .gex-user-name { cursor: pointer; }
.gex-user-item:last-child { border-bottom: none; }
.gex-user-item.hidden-filter { display: none; }
.gex-user-name {
font-weight: 500;
color: var(--text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 120px;
max-width: 220px;
}
.gex-user-upn {
font-size: 11.5px;
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.gex-group-row {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-bottom: 1px solid var(--hairline-soft);
font-size: 13px;
}
.gex-group-row:last-child { border-bottom: none; }
.gex-group-row.hidden-filter { display: none; }
.gex-group-row .gex-user-name { min-width: 140px; max-width: none; flex: 1; }
.gex-group-row .gex-user-upn { flex: 1; }
.gex-type-badge {
font-size: 10px;
font-weight: 600;
padding: 2px 6px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
background: var(--hairline-soft);
color: var(--muted);
}
.gex-loading {
display: flex;
align-items: center;
gap: 10px;
padding: 20px 16px;
font-size: 13px;
color: var(--muted);
}
.gex-hint, .gex-empty, .gex-error {
padding: 16px;
font-size: 13px;
color: var(--muted);
text-align: center;
}
.gex-error { color: var(--error); }
.gex-add-results {
max-height: 180px;
flex-shrink: 0;
}
.gex-user-result-item {
display: flex;
align-items: baseline;
gap: 8px;
padding: 7px 12px;
border-bottom: 1px solid var(--hairline-soft);
cursor: pointer;
transition: background var(--tx);
font-size: 13px;
}
.gex-user-result-item:last-child { border-bottom: none; }
.gex-user-result-item:hover { background: var(--surface-soft); }
.gex-user-result-item.selected {
opacity: 0.45;
cursor: default;
}
.gex-user-added {
margin-left: auto;
font-size: 11px;
color: var(--success);
font-weight: 600;
}
.gex-selected-area {
flex: 1;
overflow-y: auto;
border: 1px solid var(--hairline);
border-radius: var(--r-md);
min-height: 60px;
}
.gex-selected-chip {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px 6px 12px;
border-bottom: 1px solid var(--hairline-soft);
font-size: 13px;
}
.gex-selected-chip:last-child { border-bottom: none; }
.gex-selected-chip-name {
font-weight: 500;
color: var(--text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 100px;
max-width: 200px;
}
.gex-selected-chip-upn {
flex: 1;
font-size: 11.5px;
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.gex-selected-chip-remove {
background: none;
border: none;
cursor: pointer;
color: var(--muted);
font-size: 17px;
line-height: 1;
padding: 0 3px;
flex-shrink: 0;
transition: color var(--tx);
}
.gex-selected-chip-remove:hover { color: var(--error); }
/* Kompakte Optik fuer beide Themes — passt besser zum Tool */
.flatpickr-calendar {
font-family: inherit;
font-size: 12.5px;
}
.flatpickr-day {
font-size: 12px;
}
/* =============================================================
READ-ONLY MODUS
Alle Schreib-Buttons/-Elemente ausblenden wenn body.read-only
============================================================= */
/* Read-Only Indikator in der Topbar */
body.read-only #connStatus::after {
content: 'Read Only';
font-size: 10px;
font-weight: 700;
letter-spacing: 0.04em;
color: var(--warning);
background: var(--warning-soft);
border-radius: var(--r-pill);
padding: 1px 6px;
margin-left: 5px;
}
/* Schreib-Buttons ausblenden */
body.read-only .type-create,
body.read-only .type-remove,
body.read-only .col-create,
body.read-only .col-remove-req,
body.read-only .col-remove-avail,
body.read-only .app-delete-btn,
body.read-only .app-rename-btn,
body.read-only .asg-del,
body.read-only [data-update-content],
body.read-only #btnApply,
body.read-only .gex-add-pane,
body.read-only .gex-tab[data-tab="add"],
body.read-only .gex-tab[data-tab="import"],
body.read-only #gexPaneImport {
display: none !important;
}
/* Grid anpassen wenn Schreib-Spalten weg sind */
body.read-only .app-row {
grid-template-columns:
22px
minmax(200px, 1fr)
24px
58px
92px
98px
98px
26px; /* nur delete-spalte bleibt als spacing, ebenfalls versteckt */
}
/* =============================================================
APP REPORT VIEW
============================================================= */
.app-report-view {
display: flex;
flex-direction: column;
gap: 12px;
padding: 16px 20px;
height: calc(100vh - var(--topbar-h, 52px) - 32px);
box-sizing: border-box;
}
.app-report-toolbar {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
.app-report-toolbar input[type="search"] {
flex: 1;
max-width: 320px;
padding: 5px 10px;
border: 1px solid var(--border);
border-radius: 4px;
background: var(--bg-input, var(--bg2));
color: var(--text);
font-size: 13px;
}
.app-report-table-wrap {
flex: 1;
overflow: auto;
border: 1px solid var(--border);
border-radius: 6px;
}
.app-report-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.app-report-table thead {
position: sticky;
top: 0;
z-index: 2;
background: var(--bg2);
}
.app-report-table th {
padding: 8px 10px;
text-align: left;
font-weight: 600;
font-size: 12px;
color: var(--text-dim, #888);
border-bottom: 1px solid var(--border);
white-space: nowrap;
user-select: none;
}
.app-report-table th.sortable {
cursor: pointer;
}
.app-report-table th.sortable:hover {
color: var(--text);
background: var(--bg3, var(--hover));
}
.sort-ico {
font-size: 10px;
opacity: 0.8;
}
.app-report-table td {
padding: 6px 10px;
border-bottom: 1px solid var(--border);
vertical-align: middle;
}
.app-report-table tbody tr:last-child td { border-bottom: none; }
.app-report-table tbody tr:hover { background: var(--hover, rgba(255,255,255,0.03)); }
.app-report-table td.report-name {
max-width: 280px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 500;
}
.app-report-table td.report-pub {
max-width: 180px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text-dim, #999);
font-size: 12px;
}
.app-report-table td.num {
text-align: right;
font-variant-numeric: tabular-nums;
min-width: 60px;
}
.report-ok { color: #4ade80; }
.report-pending { color: #facc15; }
.report-fail { color: var(--error, #f87171); font-weight: 600; }
.report-hint {
text-align: center;
padding: 24px;
color: var(--text-dim, #888);
font-size: 13px;
}
/* Per-App Gerätestatus-Export */
.report-th-export {
width: 130px;
min-width: 130px;
font-size: 11px;
color: var(--text-dim, #888);
text-align: center;
}
.report-export-cell {
text-align: center;
padding: 3px 8px;
}
.btn-report-device-export {
display: inline-flex;
align-items: center;
gap: 5px;
background: var(--bg2);
border: 1px solid var(--accent, #60a5fa);
border-radius: 5px;
color: var(--accent, #60a5fa);
cursor: pointer;
font-size: 12px;
font-weight: 500;
padding: 4px 10px;
white-space: nowrap;
transition: background 0.15s, color 0.15s;
}
.btn-report-device-export::before {
content: '⬇';
font-size: 11px;
}
.btn-report-device-export:hover:not(:disabled) {
background: var(--accent, #60a5fa);
color: #fff;
}
.btn-report-device-export:disabled {
opacity: 0.35;
cursor: default;
border-color: var(--border);
color: var(--text-dim, #888);
}
/* =============================================================
CSV-IMPORT
============================================================= */
.csv-import-input-row {
display: flex;
gap: 8px;
align-items: flex-start;
}
.csv-import-textarea {
flex: 1;
height: 130px;
resize: vertical;
padding: 8px 10px;
border: 1px solid var(--border);
border-radius: 5px;
background: var(--bg2);
color: var(--text);
font-size: 12px;
font-family: 'Consolas', 'Menlo', monospace;
line-height: 1.5;
}
.csv-import-textarea:focus {
outline: none;
border-color: var(--accent, #60a5fa);
}
.csv-upload-label {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 8px 12px;
border: 1px dashed var(--border);
border-radius: 5px;
cursor: pointer;
font-size: 11px;
color: var(--text-dim, #888);
white-space: nowrap;
transition: border-color 0.15s, color 0.15s;
}
.csv-upload-label:hover {
border-color: var(--accent, #60a5fa);
color: var(--accent, #60a5fa);
}
.csv-import-actions {
display: flex;
align-items: center;
gap: 10px;
margin-top: 8px;
}
.csv-preview-wrap { margin-top: 4px; }
.csv-preview-table-wrap {
max-height: 220px;
overflow-y: auto;
border: 1px solid var(--border);
border-radius: 5px;
margin-top: 6px;
}
.csv-preview-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.csv-preview-table thead {
position: sticky;
top: 0;
background: var(--bg2);
}
.csv-preview-table th {
padding: 5px 8px;
text-align: left;
font-weight: 600;
font-size: 11px;
color: var(--text-dim, #888);
border-bottom: 1px solid var(--border);
}
.csv-preview-table td {
padding: 4px 8px;
border-bottom: 1px solid var(--border);
vertical-align: middle;
}
.csv-preview-table tbody tr:last-child td { border-bottom: none; }
.csv-ico-ok { color: var(--success, #4ade80); font-weight: 700; width: 20px; text-align: center; }
.csv-ico-err { color: var(--error, #f87171); font-weight: 700; width: 20px; text-align: center; }
.csv-ico-done { color: #34d399; font-weight: 700; width: 20px; text-align: center; }
.csv-ico-warn { color: #facc15; font-weight: 700; width: 20px; text-align: center; }
.csv-row-err { opacity: 0.6; }
.csv-upn { font-family: 'Consolas','Menlo',monospace; font-size: 11px; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.csv-name { font-weight: 500; }
.csv-status { color: var(--text-dim, #999); font-size: 11px; }
/* CSV-Import Ergebnis-Banner */
.csv-result-banner {
margin-top: 10px;
padding: 10px 12px;
border-radius: 6px;
background: var(--bg2);
border: 1px solid var(--border);
}
.csv-result-stats {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.csv-res-chip {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 4px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.csv-res-ok { background: rgba(74,222,128,.15); color: #4ade80; border: 1px solid rgba(74,222,128,.4); }
.csv-res-warn { background: rgba(250,204, 21,.12); color: #facc15; border: 1px solid rgba(250,204,21,.35); }
.csv-res-err { background: rgba(248,113,113,.15); color: #f87171; border: 1px solid rgba(248,113,113,.4); }
.csv-res-dim { background: var(--bg3,rgba(255,255,255,.05)); color: var(--text-dim,#888); border: 1px solid var(--border); }
.csv-row-done { background: rgba(74,222,128,.05); }
.csv-row-warn { background: rgba(250,204,21,.06); opacity: 0.85; }
/* ============================================================
Geräte-View
============================================================ */
.dev-view {
display: flex;
flex-direction: column;
height: calc(100vh - 52px);
overflow: hidden;
}
.dev-toolbar {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
border-bottom: 1px solid var(--hairline-soft);
flex-shrink: 0;
}
.dev-search-wrap {
position: relative;
display: flex;
align-items: center;
flex: 1;
max-width: 600px;
min-width: 0;
}
.dev-search-wrap .search-ico {
position: absolute;
left: 12px;
color: var(--muted);
pointer-events: none;
}
.dev-search-input {
width: 100%;
box-sizing: border-box;
padding-left: 36px !important;
padding-right: 14px !important;
}
.input-select {
padding: 5px 8px;
border: 1px solid var(--hairline);
border-radius: 6px;
background: var(--bg2);
color: var(--text);
font-size: 12.5px;
cursor: pointer;
}
.dev-layout {
display: flex;
flex: 1;
overflow: hidden;
}
/* Tabelle */
.dev-list-wrap {
flex: 1;
overflow-y: auto;
border-right: 1px solid var(--hairline-soft);
}
.dev-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.dev-table thead th {
position: sticky;
top: 0;
background: var(--bg2);
padding: 8px 12px;
text-align: left;
font-weight: 600;
font-size: 12px;
color: var(--muted);
border-bottom: 1px solid var(--hairline-soft);
white-space: nowrap;
user-select: none;
}
.dev-table thead th.sortable { cursor: pointer; }
.dev-table thead th.sortable:hover { color: var(--text); }
.dev-table tbody tr {
cursor: pointer;
border-bottom: 1px solid var(--hairline-soft);
transition: background 0.1s;
}
.dev-table tbody tr:hover { background: var(--bg2); }
.dev-table tbody tr.dev-row-selected { background: var(--accent-faint, rgba(59,130,246,.12)); }
.dev-table tbody td {
padding: 7px 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 220px;
}
.dev-empty, .dev-loading {
padding: 32px;
text-align: center;
color: var(--muted);
font-size: 13px;
}
.dev-loading { display: flex; align-items: center; justify-content: center; gap: 10px; }
.dev-badge {
display: inline-block;
font-size: 11px;
font-weight: 600;
padding: 2px 7px;
border-radius: 10px;
}
.dev-badge-ok { background: rgba(74,222,128,.15); color: #4ade80; }
.dev-badge-err { background: rgba(248,113,113,.15); color: #f87171; }
.dev-badge-unk { background: var(--hairline-soft); color: var(--muted); }
/* Detail-Panel */
.dev-detail {
width: 320px;
flex-shrink: 0;
display: flex;
flex-direction: column;
overflow-y: auto;
background: var(--bg2);
}
.dev-detail-header {
padding: 14px 16px 10px;
border-bottom: 1px solid var(--hairline-soft);
}
.dev-detail-name { font-weight: 700; font-size: 15px; }
.dev-detail-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.dev-detail-body { padding: 12px 16px; flex: 1; }
.dev-info-grid {
display: grid;
grid-template-columns: auto 1fr;
gap: 4px 12px;
font-size: 12.5px;
}
.dev-info-grid dt { color: var(--muted); white-space: nowrap; }
.dev-info-grid dd { margin: 0; word-break: break-all; }
.dev-actions { padding: 12px 16px; border-top: 1px solid var(--hairline-soft); }
.dev-actions-title { font-size: 11px; font-weight: 600; color: var(--muted); margin-bottom: 8px; text-transform: uppercase; letter-spacing: .04em; }
.dev-action-btns { display: flex; flex-wrap: wrap; gap: 6px; }
.dev-action-btn { display: inline-flex; align-items: center; gap: 5px; }