@import url('../vendor/fonts/inter.css');

/* Portal-Hub — angeglichen an das Design-System des Projektmanagements. */
:root {
  /* AmtPlus.digital — Markenfarben (Logo, siehe /logos). Ausschließlich als
     Akzent verwendet (Fokusringe, Links, generische Bedienelemente wie
     Rollen-Chips) — Kartenhintergründe und der Seitenhintergrund selbst
     bleiben bewusst weiß/neutral, um die Oberfläche nicht zu verfärben. */
  --brand-ink: #084734;
  --brand-ink-strong: #052e21;
  --brand-lime: #cef17b;
  --brand-pale: #ceedb2;
  --up-bg: #ffffff;
  --up-bg-deep: #ffffff;
  --up-card: rgba(255, 255, 255, .82);
  --up-card-strong: rgba(255, 255, 255, .95);
  --up-border: rgba(15, 23, 42, .09);
  --up-hairline: rgba(15, 23, 42, .07);
  --up-text: #14161a;
  --up-text-soft: #3a3d45;
  --up-muted: #6b7280;
  --up-faint: #9aa0ab;
  --up-blue: var(--brand-ink);
  --up-blue-strong: var(--brand-ink-strong);
  /* Semantische Status-/Radius-/Bewegungs-Tokens — 1:1 aus
     pm/public/assets/css/app.css übernommen (Werte identisch, keine neue
     Palette), damit Portal & Admin (lädt diese Datei ebenfalls) Zugriff auf
     dasselbe Vokabular haben wie PM/Prozesse. */
  --up-indigo: #5b5bd6;
  --up-violet: #7c3aed;
  --up-green: #1f9d57;
  --up-amber: #d98500;
  --up-red: #e0322b;
  --up-ink: #14161a;
  --up-r-sm: 12px;
  --up-r-md: 18px;
  --up-r-lg: 24px;
  --up-r-xl: 30px;
  --up-radius: 24px;
  --up-e1: 0 1px 2px rgba(15, 23, 42, .05), 0 4px 14px rgba(15, 23, 42, .05);
  --up-e2: 0 2px 6px rgba(15, 23, 42, .06), 0 14px 38px rgba(15, 23, 42, .08);
  --up-e3: 0 6px 18px rgba(15, 23, 42, .08), 0 28px 70px rgba(15, 23, 42, .12);
  --up-inset: inset 0 1px 0 rgba(255, 255, 255, .7);
  --up-ease: cubic-bezier(.22, .61, .36, 1);
  --up-ease-out: cubic-bezier(.16, 1, .3, 1);
  --up-spring: cubic-bezier(.34, 1.56, .64, 1);
  --up-ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --up-dur-1: .14s;
  --up-dur-2: .22s;
  --up-dur-3: .4s;
}

* { font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
html { scroll-behavior: smooth; }
body {
  /* AmtPlus.digital: Seitenhintergrund bleibt durchgängig weiß — die
     Markenfarben wirken ausschließlich als Akzent (Logo, Fokusringe, Links),
     nie als Flächenfarbe, damit sie das UI/UX nicht stören. */
  background: #ffffff !important;
  color: var(--up-text);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.011em;
}
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  /* Gefundener Bootstrap-Modal-Fehler ("Kachel-Bearbeitung defekt", B1):
     main.container hatte vorher selbst position:relative + z-index:1, nur um
     VOR diesem dekorativen Rasterhintergrund zu liegen. Das erzeugt aber
     einen eigenen Stacking-Context für main — jeder darin verschachtelte
     Bootstrap-Modal-Dialog (immer als Kind von main gerendert, nur der
     .modal-backdrop wird von Bootstrap als eigenes <body>-Kind erzeugt)
     bleibt dadurch UNTER dem Backdrop gefangen, unabhängig vom eigenen
     z-index:1055 — sichtbar als "Seite ausgegraut, nichts bedienbar" (per
     Browser-Reproduktion mit den echten Projektdateien nachgewiesen und
     durch Entfernen der main-Regel bestätigt behoben). Der KORREKTE, den
     Stacking-Context von main unangetastet lassende Weg, denselben visuellen
     Effekt (Rasterhintergrund hinter dem Inhalt) zu erreichen: das dekorative
     Element selbst bekommt ein negatives z-index, main bleibt unangetastet
     (position:static, kein eigener Stacking-Context, siehe unten). */
  z-index: -1;
  background-image:
    linear-gradient(rgba(15, 23, 42, .025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(15, 23, 42, .025) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, .5), transparent 38%);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, .5), transparent 38%);
}

/* main.container hat bewusst KEIN eigenes position/z-index mehr (siehe
   Kommentar bei body::before) — jeder Bootstrap-Modal-Dialog, der als Kind
   von main gerendert wird (Admin, PM, Prozesse, Portal), kann so korrekt vor
   dem von Bootstrap separat an <body> gehängten .modal-backdrop erscheinen. */

/* Skip-Link für Tastaturnutzung — jetzt Teil des gemeinsamen Navbar-Partials
   (portal/templates/navbar.php), gilt dadurch für alle vier Module. */
.up-skip {
  position: fixed;
  left: 1rem;
  top: -100px;
  z-index: 2000;
  background: var(--up-text);
  color: #fff;
  padding: .65rem 1.1rem;
  border-radius: 999px;
  font-weight: 700;
  box-shadow: var(--up-e2);
  transition: top .2s var(--up-ease);
}
.up-skip:focus { top: 1rem; }

/* Notfall-Sperre-Banner + gemeinsamer Sticky-Header (Banner+Navbar) —
   Bugfix: vormals style="..."-Inline-Styles über eine CSP-Hash-Allowlist
   freigegeben; trat trotz vollständigem Datei-Austausch weiterhin als
   unstyled Text auf. Auf Klassen umgestellt: robust auch dann, wenn ein
   Server-/Proxy-seitiger CSP-Header 'unsafe-hashes' nicht kennt oder die
   Hash-Liste aus anderen Gründen nicht greift — reguläre, verlinkte
   Stylesheets sind über style-src 'self' ohnehin erlaubt. Identisch in
   portal/pm/prozesse, da der Banner+Header in allen vier Modulen erscheint. */
.up-sticky-header { position: sticky; top: 0; z-index: 2000; }
.up-emergency-banner {
  display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; justify-content: center;
  background: var(--up-red); color: #fff; padding: .85rem 1.5rem; font-weight: 600; font-size: .95rem;
  text-align: center; box-shadow: 0 4px 16px rgba(0, 0, 0, .3);
}
.up-emergency-banner .eb-icon { font-size: 1.1rem; }
.up-emergency-banner .eb-cta {
  background: #fff; color: var(--up-red); border-radius: 999px; padding: .25rem .9rem;
  font-weight: 700; text-decoration: none; white-space: nowrap;
}

/* Eyebrow + Titel */
.up-eyebrow {
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: .72rem;
  font-weight: 700;
  color: var(--up-faint);
}
h2.text-center, .portal-title {
  font-size: clamp(2rem, 4vw, 3.2rem);
  line-height: 1.02;
  letter-spacing: -.035em;
  font-weight: 800;
  margin-bottom: 1.5rem !important;
}
/* Kleinere Titel-Stufe (z.B. Dashboard-Unterseiten) — ersetzt vormals
   wiederholte Inline-Style-Overrides von .portal-title. */
.portal-title-sm { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }

/* Karten */
.card, .modal-content {
  border: 1px solid rgba(255, 255, 255, .8) !important;
  border-radius: var(--up-radius) !important;
  background: linear-gradient(180deg, var(--up-card-strong), var(--up-card)) !important;
  box-shadow: var(--up-e2), var(--up-inset) !important;
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
}
.card-tile {
  cursor: pointer;
  transition: transform .22s var(--up-ease), box-shadow .22s var(--up-ease), border-color .22s var(--up-ease);
  overflow: hidden;
  position: relative;
}
.card-tile::after {
  content: "\F138"; /* bi-arrow-right-circle */
  font-family: "bootstrap-icons";
  position: absolute;
  top: 1rem; right: 1.1rem;
  font-size: 1.05rem;
  color: var(--up-faint);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity .22s var(--up-ease), transform .22s var(--up-ease), color .22s var(--up-ease);
}
.card-tile:hover::after { opacity: 1; transform: translateX(0); color: var(--up-blue); }
.card-tile:hover {
  transform: translateY(-6px);
  box-shadow: var(--up-e3), var(--up-inset) !important;
  border-color: rgba(255, 255, 255, .96) !important;
}
.card-body { position: relative; z-index: 1; }
.card-title { font-weight: 750; letter-spacing: -.02em; }
.card-text { color: var(--up-muted); }

/* Tile-Icon-Orb */
.tile-orb {
  width: 3.4rem; height: 3.4rem; border-radius: 18px;
  display: inline-grid; place-items: center; font-size: 1.5rem; color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 12px 26px rgba(15, 23, 42, .16);
}
/* Kachel-Farbvarianten — ausschließlich Tints/Shades der Markenpalette
   (--brand-ink/--brand-lime/--brand-pale), damit alle Kacheln optisch
   unterscheidbar bleiben, aber nie eine Fremdfarbe außerhalb des CI zeigen.
   "is-brand" ist die neue Standardvariante (siehe portal_tile_save()). */
.tile-orb.is-brand { background: linear-gradient(145deg, var(--brand-ink-strong), var(--brand-ink) 60%, #3f8f66); }
.tile-orb.is-blue { background: linear-gradient(145deg, var(--brand-ink), #2f7a52 55%, var(--brand-lime)); }
.tile-orb.is-green { background: linear-gradient(145deg, #0d3a2a, #1f6b4d 55%, var(--brand-pale)); }
.tile-orb.is-amber { background: linear-gradient(145deg, #4a5c1f, #8a9b3a 55%, var(--brand-lime)); }
.tile-orb.is-violet { background: linear-gradient(145deg, #3d5c52, var(--brand-ink-strong) 55%, #9db8a8); }
.tile-orb.is-teal { background: linear-gradient(145deg, #0a3d38, #1a6b5c 55%, var(--brand-pale)); }
/* Kleinere Größenstufe für Kontexte außerhalb der Hub-Kacheln (z. B.
   KPI-Zeilen) — dieselben Farbvarianten, nur kompakter. */
.tile-orb.is-sm { width: 2.625rem; height: 2.625rem; border-radius: 13px; font-size: 1.15rem; }
.display-4 { filter: drop-shadow(0 12px 22px rgba(15, 23, 42, .12)); }

/* Buttons */
.btn { font-weight: 650; border-radius: 999px; box-shadow: var(--up-e1); transition: transform .16s var(--up-ease); }
.btn:hover { transform: translateY(-1px); }
/* Fokusring analog zu pm/app.css, aber mit dem Portal-eigenen Markenakzent
   (statt pm's Blau) — deckt sich mit dem bereits vorhandenen
   .form-control:focus-Ring weiter unten, damit Buttons und Formularfelder
   denselben Fokus-Akzent verwenden. */
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(8, 71, 52, .32); }
.btn-primary, .btn-success {
  background: linear-gradient(180deg, #2a2d34, #0c0d10) !important;
  border-color: #0c0d10 !important;
  box-shadow: 0 10px 24px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .16) !important;
}
.btn-secondary { border: 0; background: rgba(255, 255, 255, .8); color: var(--up-text); }
.form-control, .form-select {
  border-radius: 14px;
  padding: .72rem .9rem;
  border-color: var(--up-border);
  background-color: rgba(255, 255, 255, .85);
  box-shadow: inset 0 1px 2px rgba(15, 23, 42, .04);
}
.form-control:focus, .form-select:focus { border-color: rgba(8, 71, 52, .55); box-shadow: 0 0 0 .22rem rgba(8, 71, 52, .16), inset 0 1px 2px rgba(15, 23, 42, .04); }
/* Bugfix: die .form-control/.form-select-Regel oben überschreibt (gleiche
   Spezifität, späterer Ladeort) Bootstraps eigenes .form-control-sm/
   .form-select-sm-Padding vollständig — "-sm"-Felder waren dadurch nie
   wirklich kleiner als normale, während .btn-sm unverändert kompakt blieb.
   Sichtbar als Höhenunterschied, wenn ein .form-select-sm neben einem
   .btn-sm steht. Nur die vertikale Polsterung wird zurückgesetzt (horizontal
   bleibt unverändert für den Dropdown-Pfeil). */
.form-control-sm, .form-select-sm { padding-top: .25rem; padding-bottom: .25rem; }
/* Bugfix (Einzel-Rechte, exakt nachgemessen): dieselbe Ursache wie oben, nur
   für die reguläre Größe statt "-sm" — .form-control/.form-select sind durch
   die Regel oben 49,03px hoch, ein normaler .btn bleibt bei Bootstraps
   Standardpolsterung 38px. Nebeneinander in derselben Zeile (z. B. "Rolle"/
   "Ebene"-Auswahl + "Hinzufügen"-Button) sitzen beide Böden zwar korrekt auf
   gleicher Höhe (siehe align-items-end), der Button wirkt aber sichtbar
   kürzer/eingesunken. Bewusst NICHT die globale .btn-Regel geändert — das
   würde jeden Button der gesamten Plattform betreffen und träfe (gleiche
   Ladereihenfolge/Spezifitätsproblem wie beim .form-control-sm-Bugfix oben)
   auch .btn-sm/.btn-lg ungewollt mit. Stattdessen eine eigene, bewusst nur
   dort angewendete Klasse.*/
.btn-field-height { padding-top: .72rem; padding-bottom: .72rem; }
.form-label { font-weight: 600; color: var(--up-text-soft); }
.table { --bs-table-bg: transparent; }
.table thead th { font-size: .74rem; text-transform: uppercase; letter-spacing: .08em; color: var(--up-muted); font-weight: 700; }
.alert { border-radius: 18px; border: 1px solid var(--up-border); box-shadow: var(--up-e1); }
.badge { border-radius: 999px; font-weight: 650; }
.modal-header, .modal-footer { border-color: var(--up-hairline); }

/* Navigation (PM-konforme Glasleiste) */
body.pm-portal-shell { padding-top: 0 !important; }
.glass-nav {
  backdrop-filter: blur(22px) saturate(180%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  background: linear-gradient(180deg, rgba(255, 255, 255, .88), rgba(255, 255, 255, .7)) !important;
  border-bottom: 1px solid rgba(255, 255, 255, .7);
  box-shadow: 0 1px 0 var(--up-hairline), 0 10px 30px rgba(15, 23, 42, .05) !important;
}
.navbar-brand { font-weight: 800; letter-spacing: -.02em; }
.portal-nav .navbar-brand { color: var(--up-text) !important; }
.portal-nav .navbar-toggler { border-color: var(--up-border); }
.portal-nav .navbar-toggler-icon { filter: invert(1) grayscale(1); opacity: .72; }
.brand-orb {
  width: 38px; height: 38px; display: inline-grid; place-items: center; border-radius: 13px;
  color: #fff; background: linear-gradient(145deg, #0b0b0d, #2c2f36 56%, #5b6472);
  box-shadow: 0 10px 24px rgba(0, 0, 0, .24), inset 0 1px 0 rgba(255, 255, 255, .26);
}
/* Modul-Akzente — ausschließlich aus der Markenpalette (--brand-*) abgeleitet,
   damit jedes Modul in der vereinheitlichten Navbar (siehe
   portal/templates/navbar.php) einen eigenen, aber CI-konformen Farbton
   bekommt statt beliebiger Fremdfarben. */
.brand-orb-portal {
  background: linear-gradient(145deg, var(--brand-ink-strong) 0%, var(--brand-ink) 55%, #3f8f66 100%);
  box-shadow: 0 10px 24px rgba(8, 71, 52, .32), inset 0 1px 0 rgba(255, 255, 255, .28);
}
.brand-orb-blue {
  background: linear-gradient(145deg, var(--brand-ink) 0%, #2f7a52 55%, var(--brand-lime) 100%);
  box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3);
}
.brand-orb-teal {
  background: linear-gradient(145deg, var(--brand-ink-strong) 0%, #1f6b4d 55%, var(--brand-pale) 100%);
  box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3);
}
/* Global-Admin-gesteuerte Modul-Farbe im Navbar-Orb (Nachsteuerung "Kacheln:
   globale Modul-Darstellung", siehe admin/README.md) — dieselben sechs
   Farbnamen wie .tile-orb.is-* (Hub-Kacheln) und wie die Farbauswahl in
   landing/betrieb/modules.php, nur mit der kompakten .brand-orb-Größe. So
   zeigt der Navbar-Orb jedes Moduls immer dieselbe Farbe wie dessen
   Hub-Kachel, ohne eine zweite, unabhängige Farbpalette zu brauchen. */
.brand-orb.is-brand { background: linear-gradient(145deg, var(--brand-ink-strong), var(--brand-ink) 60%, #3f8f66); box-shadow: 0 10px 24px rgba(8, 71, 52, .32), inset 0 1px 0 rgba(255, 255, 255, .28); }
.brand-orb.is-blue { background: linear-gradient(145deg, var(--brand-ink), #2f7a52 55%, var(--brand-lime)); box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3); }
.brand-orb.is-green { background: linear-gradient(145deg, #0d3a2a, #1f6b4d 55%, var(--brand-pale)); box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3); }
.brand-orb.is-amber { background: linear-gradient(145deg, #4a5c1f, #8a9b3a 55%, var(--brand-lime)); box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3); }
.brand-orb.is-violet { background: linear-gradient(145deg, #3d5c52, var(--brand-ink-strong) 55%, #9db8a8); box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3); }
.brand-orb.is-teal { background: linear-gradient(145deg, #0a3d38, #1a6b5c 55%, var(--brand-pale)); box-shadow: 0 10px 24px rgba(8, 71, 52, .28), inset 0 1px 0 rgba(255, 255, 255, .3); }

/* AmtPlus.digital — echtes Logo statt Icon-Orb für den Marken-/Hub-Link.
   Feste Höhe statt Breite: das Logo ist kein Quadrat wie die Icon-Orbs
   darunter, soll aber dieselbe vertikale Taktung der Navigationsleiste
   einhalten. Höhe = Größe von .brand-orb (38px), damit logo_klein optisch
   genauso groß wirkt wie die Bootstrap-Icons neben "Projektmanagement" &co. */
.brand-logo { height: 38px; width: auto; display: block; }
/* Größere Logo-Stufe (Hub-Startseite) — ersetzt vormals einen Inline-Style-
   Override direkt neben .brand-logo. */
.brand-logo-lg { height: 48px; width: auto; display: block; }
.pm-user-chip {
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .9), rgba(255, 255, 255, .68));
  border: 1px solid var(--up-border);
  box-shadow: var(--up-e1), var(--up-inset);
  padding: .42rem .8rem;
  line-height: 1.05;
  color: var(--up-text);
}
.portal-nav .btn-light {
  background: rgba(255, 255, 255, .8);
  border-color: var(--up-border);
  box-shadow: var(--up-e1);
}
.portal-nav .btn-outline-dark { background: rgba(255, 255, 255, .55); border-color: var(--up-border); }
/* Bugfix: .portal-nav .btn-outline-dark (Spezifität 0,2,0) überschreibt
   Bootstraps generische .btn:hover-Regel (0,1,1) auch beim Hovern — der
   Hintergrund blieb dadurch hell, während Bootstrap die Schrift trotzdem auf
   Weiß setzte ("Abmelden" beim Hovern unlesbar). Eigene Hover-Regel mit noch
   höherer Spezifität ergänzt, Farben aus dem bestehenden System. */
.portal-nav .btn-outline-dark:hover { background: var(--brand-ink-strong); color: #fff; border-color: var(--brand-ink-strong); }

/* Sitzungs-Pille + Avatar in der Navigation */
.pm-session-pill {
  border-radius: 999px;
  background: rgba(255, 255, 255, .6);
  border: 1px solid var(--up-border);
  box-shadow: var(--up-e1);
  padding: .42rem .8rem;
  color: var(--up-text-soft);
  font-size: .9rem;
}
.pm-session-pill i { color: var(--up-muted); }
.pm-ava {
  /* Bugfix: 30px trieb die Gesamthöhe von .pm-user-chip auf ~45px, spürbar
     höher als .pm-session-pill/Buttons (~37-38px) in derselben Zeile — nicht
     die zweizeilige Beschriftung war die Ursache (bereits vereinfacht),
     sondern der fest hohe Avatar. 22px bringt die Chip-Gesamthöhe auf
     denselben Wert wie ihre Nachbarn. */
  width: 22px; height: 22px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: .62rem; font-weight: 700; color: #fff;
  background: linear-gradient(145deg, #2c2f36, #0c0d10);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 4px 10px rgba(15, 23, 42, .18);
}

/* Admin: Kennzahl-Karten — Icons nutzen seit Runde 2 die markenabgeleiteten
   .tile-orb.is-sm-Varianten (dieselben Farben wie die Hub-Kacheln) statt
   einer eigenen, CI-fremden Blau/Violett-Palette. */
.stat-card { background: #fff; border: .5px solid var(--up-border); border-radius: var(--up-radius); padding: 18px 20px; box-shadow: var(--up-e1); }
.stat-card .lbl { font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--up-faint); font-weight: 500; }
.stat-card .val { font-size: 30px; font-weight: 800; letter-spacing: -.03em; color: var(--up-text); line-height: 1.1; margin-top: 4px; }

/* Admin: Avatare und Rollen-Chips in Tabellen */
.admin-ava {
  width: 38px; height: 38px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: .8rem; font-weight: 700; color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 4px 10px rgba(15, 23, 42, .15);
}
.role-chip {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 500;
  padding: 3px 10px; border-radius: 999px; background: rgba(8, 71, 52, .09);
  color: var(--brand-ink); border: .5px solid rgba(8, 71, 52, .18);
}
.role-chip.muted { background: rgba(15, 23, 42, .05); color: var(--up-muted); border-color: var(--up-hairline); }

/* Admin: Zugriffsmatrix */
.access-matrix { width: 100%; border-collapse: collapse; }
.access-matrix th, .access-matrix td { padding: 12px 10px; border-bottom: .5px solid var(--up-hairline); }
.access-matrix thead th { font-size: 12px; color: var(--up-muted); font-weight: 500; text-align: center; vertical-align: bottom; }
.access-matrix thead th:first-child { text-align: left; }
.access-matrix tbody th { text-align: left; font-weight: 500; color: var(--up-text); white-space: nowrap; }
.access-matrix td { text-align: center; }
.access-matrix .pg-ic {
  width: 34px; height: 34px; border-radius: 10px; display: inline-grid; place-items: center; color: #fff; font-size: 16px; margin-bottom: 6px;
  /* Vormals identisch als Inline-Style an 2 Stellen dupliziert (admin/index.php,
     admin/templates/tiles.php) — hier einmal zentral definiert. */
  background: linear-gradient(145deg, #2c2f36, #5b6472);
}
.access-matrix .form-check-input { width: 1.3rem; height: 1.3rem; cursor: pointer; margin: 0; }
.access-row:hover { background: rgba(15, 23, 42, .025); }

.admin-table tbody tr:hover { background: rgba(15, 23, 42, .025); }
.admin-table td, .admin-table th { vertical-align: middle; }
.search-box { max-width: 320px; }

/* Sicherheitsfix (CSP-Härtung): ersetzt vormals inline style="border:1px
   solid <?= $cond ? '#f3c6c6' : '#e5e7eb' ?>" im Admin-Dashboard — zwei feste
   Zustände, dafür reicht eine Klassenumschaltung statt eines dynamischen
   Inline-Styles. */
.up-card-border-alert { border: 1px solid #f3c6c6; }
.up-card-border-neutral { border: 1px solid #e5e7eb; }
/* Amber-getönter Rahmen für "Sonderregel, aber keine Gefahr"-Bereiche —
   exakt analog zu .up-card-border-alert/-neutral, nur aus der Amber- statt
   Rot-Familie (--up-amber: #d98500). */
.up-card-border-notice { border: 1px solid rgba(217, 133, 0, .35); }
/* Leicht getönter Sub-Panel-Container (z. B. "Neue Einschränkung
   hinzufügen") — ersetzt einen sonst nötigen Inline-Style samt CSP-Hash. */
.up-subpanel { background: rgba(15, 23, 42, .02); border: 1px solid var(--up-hairline); border-radius: var(--up-r-md); }
/* Begrenzte Breite für Einzelfeld-Zeilen (z. B. Objekt-Auswahl mit
   potenziell langen Namen) — verhindert einen weiteren Inline-Style samt
   CSP-Hash für einen simplen max-width-Wert. */
.up-input-md { max-width: 28rem; }

/* Ampel-/Health-Status — 1:1 aus pm/app.css übernommen, ersetzt die vormals
   in dashboard.php per Inline-Style/PHP-Farbtabelle nachgebaute Variante. */
.health-dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; flex: 0 0 auto; background: var(--up-faint); }
.health-green { background: var(--up-green); box-shadow: 0 0 0 4px rgba(31, 157, 87, .14); }
.health-amber { background: var(--up-amber); box-shadow: 0 0 0 4px rgba(217, 133, 0, .15); }
.health-red { background: var(--up-red); box-shadow: 0 0 0 4px rgba(224, 50, 43, .14); }
.health-red.is-pulsing { animation: up-pulse 2s var(--up-ease) infinite; }
@keyframes up-pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(224, 50, 43, .14); }
  50% { box-shadow: 0 0 0 7px rgba(224, 50, 43, .05); }
}

/* Klickbare Listenzeilen (Suchergebnisse/"Zuletzt bearbeitet") — ersetzt
   vormals 4x identisch wiederholte Inline-Styles und ergänzt einen bislang
   fehlenden Hover-Zustand. Tint dezenter als pm's .project-row, da Portal
   einen weißen statt getönten Seitenhintergrund hat. */
.list-row {
  border: 1px solid var(--up-hairline);
  border-radius: var(--up-r-md);
  transition: background var(--up-dur-2) var(--up-ease), border-color var(--up-dur-2) var(--up-ease);
}
.list-row:hover { background: rgba(15, 23, 42, .035); border-color: var(--up-border); }

/* Leerzustand — 1:1 aus pm/app.css übernommen. */
.up-empty { text-align: center; padding: 2.4rem 1rem; color: var(--up-muted); }
.up-empty .ei {
  width: 3.4rem; height: 3.4rem; border-radius: var(--up-r-md); display: inline-grid; place-items: center;
  margin-bottom: .85rem; font-size: 1.5rem; color: var(--up-faint);
  background: rgba(15, 23, 42, .04); border: 1px solid var(--up-hairline);
}
.up-empty h3 { font-size: 1.02rem; font-weight: 700; color: var(--up-text); margin-bottom: .25rem; }

/* Overlay für den "Zugriff verweigert"-Hinweis (portal/index.php) — ersetzt
   vormals zwei Inline-Styles durch benannte Klassen, Werte unverändert. */
.up-overlay-scrim { background: rgba(0, 0, 0, .5); z-index: 1050; }
.up-overlay-card { width: 90%; max-width: 400px; }
/* Bugfix (per Nutzer-Meldung: "Zugriff verweigert"-Karte erschien weiß statt
   rot): das globale Glasmorphism-Kartendesign oben (".card, .modal-content")
   setzt background per !important und lädt in dieser Datei später als
   Bootstrap — das überschreibt .bg-danger auf JEDER Karte, unabhängig vom
   Kontext. .card-text hat außerdem eine eigene, nicht-!important Textfarbe,
   die die von .text-white geerbte weiße Farbe auf der eigenen Ebene schlägt
   (eine direkt zutreffende Regel gewinnt immer gegen eine nur geerbte). Fix
   gezielt nur für diese eine Fehlerkarte, ohne das normale Kartendesign
   anzutasten. */
.up-overlay-card.bg-danger { background: var(--up-red) !important; }
.up-overlay-card.bg-danger .card-text { color: #fff !important; }

/* Mitteilungen und Benachrichtigungen (Glocke in der geteilten Navbar,
   portal/templates/navbar.php) — appübergreifend identisch in allen drei
   Stylesheets (portal/pm/prozesse), weil jede App ihr eigenes CSS lädt (siehe
   .portal-nav .btn-outline-dark:hover für dieselbe, bereits einmal real
   aufgetretene Lücke). Admin bezieht portal/css/style.css direkt, ist damit
   automatisch mit abgedeckt. */
.up-notif-bell { width: 2.4rem; height: 2.4rem; padding: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem; }
.up-notif-badge { font-size: .62rem; padding: .3em .45em; background: var(--up-red); }
.up-notif-panel { width: 340px; max-width: calc(100vw - 2rem); padding: 0; border-radius: 16px; overflow: hidden; box-shadow: var(--up-e3); border: 1px solid var(--up-hairline); }
.up-notif-panel-head { border-bottom: 1px solid var(--up-hairline); background: rgba(15, 23, 42, .02); }
.up-notif-list { max-height: 360px; overflow-y: auto; }
.up-notif-item { color: inherit; border-bottom: 1px solid var(--up-hairline); transition: background .15s ease; }
.up-notif-item:last-child { border-bottom: 0; }
.up-notif-item:hover { background: rgba(15, 23, 42, .035); }
.up-notif-body { min-width: 0; }
.up-notif-dot { width: .5rem; height: .5rem; border-radius: 50%; margin-top: .4rem; background: transparent; flex: 0 0 auto; }
.up-notif-item.is-unread { background: rgba(11, 107, 219, .04); }
.up-notif-item.is-unread .up-notif-dot { background: var(--brand-ink-strong); }
.up-notif-time { font-size: .72rem; color: var(--up-faint); margin-top: .15rem; }
.up-notif-msg { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .001ms !important; animation-duration: .001ms !important; }
}
