/* ============================================================
   corsten · Design-System
   ============================================================
   Aufbau:
     1. Schriften — self-hosted woff2 (assets/fonts/, DSGVO-konform)
     2. Tokens     — Farb-, Typo-, Radius-, Schatten-Skala (:root)
     3. Bootstrap  — Variablen-Mapping auf die Tokens
     4. Basis      — body, Headings, Links, Code, Fokus, Auswahl
     5. App-Shell  — Header/Navigation, Footer
     6. Page-Head  — einheitlicher Seitenkopf (Eyebrow, Titel, Aktionen)
     7. Komponenten— Card, Tabelle, Buttons, Formular, Status,
                     Tabs, Modal, Alerts, Dashboard-Kacheln
     8. Login

   Bootstrap-CSS wird in assets/app.js VOR dieser Datei importiert;
   die Regeln hier verfeinern die Bootstrap-Defaults.
   Editorial-Pairing: Spectral (Serife, Überschriften) +
   IBM Plex Sans (UI/Fließtext) + IBM Plex Mono (Code/IDs).
   ============================================================ */

/* ── 1. Schriften ─────────────────────────────────────────── */
@font-face { font-family:'IBM Plex Sans'; font-style:normal; font-weight:400; font-display:swap; src:url("../fonts/ibm-plex-sans-400-dCzU-sz.woff2") format('woff2'); }
@font-face { font-family:'IBM Plex Sans'; font-style:normal; font-weight:500; font-display:swap; src:url("../fonts/ibm-plex-sans-500-mSIWrNY.woff2") format('woff2'); }
@font-face { font-family:'IBM Plex Sans'; font-style:normal; font-weight:600; font-display:swap; src:url("../fonts/ibm-plex-sans-600-pA5FLX3.woff2") format('woff2'); }
@font-face { font-family:'IBM Plex Sans'; font-style:normal; font-weight:700; font-display:swap; src:url("../fonts/ibm-plex-sans-700-zdWo2v5.woff2") format('woff2'); }
@font-face { font-family:'IBM Plex Mono'; font-style:normal; font-weight:400; font-display:swap; src:url("../fonts/ibm-plex-mono-400-78NWkmx.woff2") format('woff2'); }
@font-face { font-family:'IBM Plex Mono'; font-style:normal; font-weight:500; font-display:swap; src:url("../fonts/ibm-plex-mono-500-QJNNIVc.woff2") format('woff2'); }
@font-face { font-family:'Spectral'; font-style:normal; font-weight:500; font-display:swap; src:url("../fonts/spectral-500-ocLd0d2.woff2") format('woff2'); }
@font-face { font-family:'Spectral'; font-style:normal; font-weight:600; font-display:swap; src:url("../fonts/spectral-600-Aw-mq3l.woff2") format('woff2'); }
@font-face { font-family:'Spectral'; font-style:normal; font-weight:700; font-display:swap; src:url("../fonts/spectral-700-LWg_Trq.woff2") format('woff2'); }

/* ── 2. Tokens ────────────────────────────────────────────── */
:root {
    /* Neutralpalette (Zinc) */
    --zinc-50:#fafafa;  --zinc-100:#f4f4f5; --zinc-200:#e4e4e7;
    --zinc-300:#d4d4d8; --zinc-400:#a1a1aa; --zinc-500:#71717a;
    --zinc-600:#52525b; --zinc-700:#3f3f46; --zinc-800:#27272a;
    --zinc-900:#18181b; --zinc-950:#09090b;

    /* Akzent — HCS-Blau (aus dem Logo, #266c9b) */
    --hcs-50:#eef4f9;   --hcs-100:#d5e4ef; --hcs-200:#a9c8dd;
    --hcs-300:#74a3c4;  --hcs-500:#2f7fb2; --hcs-600:#266c9b;
    --hcs-700:#1f5a81;  --hcs-800:#1a4a6b;

    /* Akzent-Gelb — nur als Fläche/Markierung, nie als Text (Kontrast ~1,6:1).
       Seit dem Alt-Paritäts-Header in Gebrauch: Blau→Gold-Verlauf im Header +
       goldener Unterstrich des aktiven Menüpunkts. */
    --hcs-gold:#fdc91e; --hcs-gold-soft:#fef6dc; --hcs-gold-ink:#6b5200;

    /* Semantische Flächen & Text */
    --bg:#f2f2f0;
    --surface:#ffffff;
    --surface-sunken:#f6f6f5;
    --ink:var(--zinc-900);
    --ink-soft:var(--zinc-600);
    --ink-faint:var(--zinc-400);
    --line:var(--zinc-200);
    --line-strong:var(--zinc-300);

    --accent:var(--hcs-600);
    --accent-hover:var(--hcs-700);
    --accent-ink:var(--hcs-800);
    --accent-soft:var(--hcs-50);
    --accent-line:var(--hcs-200);

    --success:#3d7a52;
    --success-soft:#eef3ee;
    --danger:#b04437;
    --danger-soft:#fbf0ef;

    /* Typografie */
    --font-sans:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',sans-serif;
    --font-serif:'Spectral','Iowan Old Style',Georgia,'Times New Roman',serif;
    --font-mono:'IBM Plex Mono','SFMono-Regular',Consolas,monospace;

    /* Radius & Schatten */
    --radius-sm:6px; --radius:9px; --radius-lg:13px;
    --shadow-xs:0 1px 2px rgba(24,24,27,.05);
    --shadow-sm:0 1px 3px rgba(24,24,27,.07),0 1px 2px rgba(24,24,27,.04);
    --shadow-md:0 6px 16px rgba(24,24,27,.09),0 2px 5px rgba(24,24,27,.05);
    --shadow-pop:0 14px 40px rgba(24,24,27,.16),0 4px 12px rgba(24,24,27,.08);
}

/* ── 3. Bootstrap-Variablen-Mapping ───────────────────────── */
:root {
    --bs-body-bg:var(--bg);
    --bs-body-color:var(--ink);
    --bs-body-font-family:var(--font-sans);
    --bs-body-font-size:.9375rem;
    --bs-body-line-height:1.6;
    --bs-emphasis-color:var(--zinc-950);
    --bs-secondary-color:var(--ink-soft);
    --bs-tertiary-color:var(--ink-faint);
    --bs-border-color:var(--line);
    --bs-border-radius:var(--radius);
    --bs-border-radius-sm:var(--radius-sm);
    --bs-border-radius-lg:var(--radius-lg);
    --bs-link-color:var(--accent-ink);
    --bs-link-color-rgb:26,74,107;         /* #1a4a6b = --hcs-800 */
    --bs-link-hover-color:var(--accent-hover);
    --bs-link-hover-color-rgb:31,90,129;   /* #1f5a81 = --hcs-700 */
    --bs-primary:var(--zinc-900);
    --bs-primary-rgb:24,24,27;
    --bs-font-monospace:var(--font-mono);
}

/* ── 4. Basis ─────────────────────────────────────────────── */
body {
    font-family:var(--font-sans);
    font-size:.9375rem;
    line-height:1.6;
    color:var(--ink);
    background-color:var(--bg);
    margin:0;
    min-height:100vh;
    display:flex;
    flex-direction:column;
    -webkit-font-smoothing:antialiased;
    -moz-osx-font-smoothing:grayscale;
    text-rendering:optimizeLegibility;
}
body > main { flex:1 0 auto; }

h1,h2,h3,h4,h5,h6,
.h1,.h2,.h3,.h4,.h5,.h6 {
    font-family:var(--font-serif);
    font-weight:600;
    color:var(--ink);
    letter-spacing:-.006em;
}
h1,.h1 { font-weight:700; }

a { color:var(--accent-ink); text-underline-offset:.16em; transition:color .12s ease; }
a:hover { color:var(--accent-hover); }

code,kbd,samp,pre,.text-mono {
    font-family:var(--font-mono);
}
code {
    font-size:.84em;
    background:var(--surface-sunken);
    border:1px solid var(--line);
    color:var(--accent-ink);
    padding:.08em .4em;
    border-radius:5px;
}

::selection { background:var(--hcs-200); color:var(--accent-ink); }

:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.form-control:focus,.form-select:focus,.form-check-input:focus {
    border-color:var(--accent);
    box-shadow:0 0 0 .2rem rgba(38,108,155,.18);
}
.btn:focus-visible { box-shadow:0 0 0 .2rem rgba(38,108,155,.3); }

/* dezente Scrollbar */
* { scrollbar-color:var(--zinc-300) transparent; }

/* ── 5. App-Shell ─────────────────────────────────────────── */
/* Blauer „Breathing"-Header aus dem Altsystem: Blau→Gold-Verlauf (45°),
   auf 120% vergrössert, dessen Position über 30s langsam hin- und
   herwandert — das Gold wabert weich in der unteren rechten Ecke. */
.app-header {
    position:sticky; top:0; z-index:1030;
    background:linear-gradient(45deg,
        var(--hcs-600) 0%,
        var(--hcs-500) 75%,
        var(--hcs-gold) 100%);
    background-size:120% 120%;
    box-shadow:inset 0 -2px 0 rgba(0,0,0,.2),
               inset 0 2px 0 rgba(255,255,255,.15);
    animation:header-breathe 30s ease infinite;
}
@keyframes header-breathe {
    0%   { background-position:8% 32%; }
    50%  { background-position:82% 68%; }
    100% { background-position:8% 32%; }
}
@media (prefers-reduced-motion:reduce) {
    .app-header { animation:none; }
}
.app-bar {
    display:flex; align-items:stretch;
    gap:1.5rem; height:60px;
}

.app-brand {
    display:flex; align-items:center; gap:.6rem;
    text-decoration:none; color:#fff; flex:none;
}
.app-brand:hover { color:#fff; }
/* Als gerahmte Plakette statt aufgeklebtem Rechteck: etwas Luft, weiche
   Ecken, feine Kante + Schatten heben die weisse Marke sichtbar auf die
   blaue Leiste, statt sie „draufzukleben". */
.app-brand__logo {
    height:44px; width:auto; flex:none; display:block;
    box-sizing:border-box;
    padding:5px 8px;
    background:#fff;
    border-radius:var(--radius-sm);
    border:1px solid rgba(0,0,0,.08);
    box-shadow:0 2px 6px rgba(0,0,0,.2);
}
.app-brand__name {
    font-family:var(--font-serif); font-weight:600;
    font-size:1.2rem; letter-spacing:-.015em;
    color:#fff;
}

.app-menu { display:flex; align-items:stretch; gap:.1rem; }
.app-menu__link {
    display:flex; align-items:center; gap:.4rem;
    padding:0 .85rem;
    font-size:.9rem; font-weight:500;
    color:rgba(255,255,255,.85); text-decoration:none;
    background:none; border:0;
    border-bottom:2px solid transparent;
    margin-bottom:-1px;
    white-space:nowrap;
    transition:color .12s ease,border-color .12s ease;
}
.app-menu__link:hover { color:#fff; }
.app-menu__link.is-active {
    color:#fff; font-weight:600;
    border-bottom-color:var(--hcs-gold);
}
.app-menu__link .app-menu__caret { font-size:.7rem; opacity:.7; }

.app-user { display:flex; align-items:center; margin-left:auto; }
.app-user__btn {
    display:flex; align-items:center; gap:.55rem;
    background:none; border:0;
    padding:.3rem .45rem; border-radius:var(--radius-sm);
    color:#fff; font-size:.9rem; font-weight:500;
    cursor:pointer; transition:background .12s ease;
}
.app-user__btn:hover { background:rgba(255,255,255,.15); }
.app-user__avatar {
    width:31px; height:31px; flex:none;
    display:grid; place-items:center;
    background:var(--surface); color:var(--accent-ink);
    border-radius:50%;
    font-weight:600; font-size:.78rem;
    /* Kein text-transform: Der Buchstabe kommt bereits als Grossbuchstabe aus
       dem Template (`app.user.name|first|upper`). Ein Monogramm ist keine
       Versalienschrift -- die Regel hier war ohnehin wirkungslos. */
}
.app-user__caret { font-size:.7rem; color:rgba(255,255,255,.7); }

/* Verlaufsleiste — die zuletzt besuchten Seiten, neueste links. Sie sitzt
   zwischen Kopfzeile und Inhalt und muss dort NEBENSACHE bleiben: schmal,
   ruhig, ohne eigene Flaechenwirkung. Sie waechst nie in die Hoehe --
   `overflow-x:auto` schiebt aeltere Eintraege seitlich weg, statt eine zweite
   Zeile aufzumachen und den Inhalt nach unten zu druecken. */
.app-history {
    background:var(--surface);
    border-bottom:1px solid var(--line);
}
.app-history__inner {
    display:flex; align-items:center; gap:.5rem;
    padding:.4rem 0;
    overflow-x:auto;
    scrollbar-width:none;
}
.app-history__inner::-webkit-scrollbar { display:none; }
.app-history__label {
    font-family:var(--font-sans);
    font-size:.72rem; font-weight:600;
    color:var(--ink-faint);
    flex:none;
}
.app-history__item {
    flex:none; max-width:15rem;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
    font-size:.78rem;
    color:var(--ink-soft); text-decoration:none;
    padding:.15rem .5rem;
    border:1px solid var(--line);
    border-radius:100px;
    transition:color .12s ease, border-color .12s ease;
}
.app-history__item:hover {
    color:var(--accent-ink);
    border-color:var(--accent-line);
}

.app-footer {
    flex:none;
    border-top:1px solid var(--line);
    color:var(--ink-faint);
    font-size:.8rem;
    padding:1.15rem 0;
    margin-top:3rem;
}
.app-footer__inner { display:flex; gap:.5rem; align-items:center; }

/* ── 6. Page-Head ─────────────────────────────────────────── */
.page-head {
    display:flex; align-items:flex-start; justify-content:space-between;
    gap:1.25rem; margin-bottom:1.6rem;
}
.page-head__titles { min-width:0; }
/* Kleine Marker-Zeilen (Eyebrow, Werkzeug- und Abschnitts-Labels, Tabellen-
   koepfe) trugen ihre Rolle bisher ueber VERSALIEN + weite Laufweite. Beides
   ist raus. Was die Rolle jetzt traegt: etwas mehr Schriftgrad, ruhige
   Laufweite, unveraendert halbfett -- und dort, wo Versalien die einzige
   Betonung waren, eine Stufe kraeftigere Farbe (ink-faint -> ink-soft).
   Ohne diese Nachjustierung saehen dieselben Zeilen in Kleinschreibung nur
   noch nach beilaeufigem Kleingedrucktem aus. */
.page-head__eyebrow {
    font-family:var(--font-sans);
    font-size:.78rem; font-weight:600;
    letter-spacing:.01em;
    color:var(--accent);
    margin-bottom:.35rem;
}
.page-head__title {
    font-size:1.7rem; line-height:1.18; margin:0;
}
.page-head__subtitle {
    color:var(--ink-soft); font-size:.9rem;
    margin:.4rem 0 0;
}
.page-head__actions { display:flex; gap:.5rem; flex:none; flex-wrap:wrap; }
.page-head--bordered {
    border-bottom:1px solid var(--line);
    padding-bottom:1.3rem;
}

/* ── 6a. Ladezustand eines Listen-Frames ──────────────────────
   Turbo setzt am <turbo-frame> waehrend jedes Abrufs selbst `busy` (plus
   aria-busy) und nimmt es danach wieder weg -- daran haengt der Ladezustand,
   ohne eine Zeile JavaScript. Noetig ist er, weil Turbo seinen gelben
   Fortschrittsbalken NUR bei Vollseiten-Navigationen zeigt: Filtern, Sortieren,
   Blaettern und das Neuladen nach dem Speichern einer Schnellbearbeitung liefen
   bisher voellig ohne Rueckmeldung -- die Tabelle stand einfach still und
   sprang dann um.

   Der Selektor haengt an der id-Konvention `data-list-<entityKey>` aus
   _data_list.html.twig (festgehalten in DataListBusyStateTest). Das
   Schnellbearbeitungs-Modal hat einen eigenen Frame (`quick-edit-…`) und
   bleibt bewusst aussen vor -- es zeigt sein Formular ohnehin erst, wenn es
   geladen ist. */
turbo-frame[id^="data-list-"] { display:block; position:relative; }
turbo-frame[id^="data-list-"][busy]::before {
    content:""; position:absolute; inset:0; z-index:5;
    background:rgba(255,255,255,.6);
}
turbo-frame[id^="data-list-"][busy]::after {
    content:""; position:absolute; z-index:6;
    top:4.5rem; left:50%; margin-left:-1rem;
    width:2rem; height:2rem; border-radius:50%;
    border:3px solid var(--line-strong);
    border-top-color:var(--accent);
    animation:dl-spin .7s linear infinite;
}
@keyframes dl-spin { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce) {
    /* Der Schleier allein sagt „es passiert etwas" auch ohne Drehung. */
    turbo-frame[id^="data-list-"][busy]::after { animation:none; }
}

/* ── 6b. DataList-Werkzeugleiste ──────────────────────────── */
/* Zeile 1: Suche | Filter-Anzeige | Spalten — drei Blöcke nebeneinander,
   umbrechend auf schmalen Viewports. */
.dl-toolbar {
    display:flex; flex-wrap:wrap; gap:.75rem;
    margin-bottom:.9rem;
}
/* Das gemeinsame Such-/Filter-Formular ist selbst kein sichtbarer Block,
   sondern reicht seine beiden Tools direkt in die Flex-Leiste durch. */
.dl-toolbar__form { display:contents; }
.dl-tool {
    flex:1 1 15rem; min-width:0;
    display:flex; flex-direction:column; gap:.4rem;
    padding:.7rem .8rem;
    background:var(--surface);
    border:1px solid var(--line);
    border-radius:var(--radius-sm);
}
.dl-tool--columns { flex:1 1 12rem; }
.dl-tool__label {
    font-family:var(--font-sans);
    font-size:.76rem; font-weight:600;
    letter-spacing:0;
    color:var(--ink-soft);
}
.dl-tool__body { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem; }
.dl-tool--search .dl-tool__body { flex-wrap:nowrap; }
.dl-tool--search .form-control { flex:1 1 auto; min-width:0; }
.dl-tool__actions { display:flex; gap:.4rem; margin-left:auto; }

/* Filter-/Spalten-Chips (aktiver Zustand, mehrzeilig umbrechend) */
.dl-chips { display:flex; flex-wrap:wrap; gap:.35rem; min-width:0; }
.dl-chips__empty { color:var(--ink-faint); font-size:.82rem; }
.dl-chip {
    display:inline-flex; align-items:baseline; gap:.3rem;
    padding:.18rem .5rem;
    background:var(--accent-soft); color:var(--accent-ink);
    border-radius:999px;
    font-size:.78rem; line-height:1.3;
}
.dl-chip--muted { background:var(--surface-sunken); color:var(--ink-soft); }
.dl-chip__field { font-weight:600; }
.dl-chip__op { color:var(--ink-faint); font-size:.72rem; }

/* Zeile 2: Werkzeug-Buttons, gruppiert */
.dl-tools {
    display:flex; flex-wrap:wrap; align-items:center; gap:.6rem 1rem;
    margin-bottom:1rem;
}
.dl-tools__label {
    font-family:var(--font-sans);
    font-size:.76rem; font-weight:600;
    letter-spacing:0;
    color:var(--ink-soft);
}
.dl-tools__group { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem; }
.dl-tools__group + .dl-tools__group {
    padding-left:1rem; border-left:1px solid var(--line);
}
.dl-tools__group--dummy { margin-left:auto; opacity:.55; }

/* Spaltenwahl im Modal: Zeilen mit Ziehgriff */
.cc-row {
    display:flex; align-items:center; gap:.55rem;
    padding:.3rem .1rem;
    border-bottom:1px solid var(--line);
}
.cc-row:last-child { border-bottom:0; }
.cc-row label { display:flex; align-items:center; gap:.45rem; margin:0; cursor:pointer; }
.cc-handle { cursor:grab; color:var(--ink-faint); user-select:none; }
.cc-handle:active { cursor:grabbing; }

/* ── 7. Komponenten ───────────────────────────────────────── */

/* Card */
.card {
    --bs-card-bg:var(--surface);
    --bs-card-border-color:var(--line);
    --bs-card-border-radius:var(--radius-lg);
    --bs-card-inner-border-radius:calc(var(--radius-lg) - 1px);
    box-shadow:var(--shadow-sm);
}
.card-body { padding:1.6rem; }

/* Tabellen-Card: Tabelle randlos eingebettet, Ecken sauber geklippt.
   overflow-x:auto -> breite Tabellen (viele Spalten) sind horizontal scrollbar,
   statt abgeschnitten zu werden; klippt die abgerundeten Ecken weiterhin. */
.table-card {
    background:var(--surface);
    border:1px solid var(--line);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-sm);
    overflow-x:auto;
}
.table-card .table { margin:0; }
/* Titel-Kopfzeile INNERHALB der Karte -- getoente Leiste mit dunklem Text, damit
   der Widget-Titel klar ueber den blassen Spaltenkoepfen (thead) sitzt, statt
   sich als loses <h2> darueber zu verlieren. */
.table-card__head {
    margin:0;
    padding:.72rem 1.15rem;
    border-bottom:1px solid var(--line-strong);
    background:var(--surface-sunken);
    font-family:var(--font-sans);
    font-size:.88rem; font-weight:600;
    letter-spacing:0;
    color:var(--ink);
}
.table-card__foot {
    padding:.7rem 1rem;
    border-top:1px solid var(--line);
    background:var(--surface-sunken);
    color:var(--ink-faint);
    font-size:.78rem;
}
/* Zeilen-Markierungen der Dashboard-Listen (Alt-Paritaet, MA-Geburtstage):
   runder Geburtstag blau, noCongrats rot. */
.table > tbody > tr.row-special > td { background:var(--accent-soft); }
.table > tbody > tr.row-nocongrats > td,
.table > tbody > tr.row-danger > td { background:var(--danger-soft); }

/* Umschalt-Fuss der ein-/ausklappbaren Liste (collapsible-list-Controller):
   der Knopf fuellt den Fuss als volle, klickbare Leiste. */
.table-card__foot--toggle { padding:0; background:none; }
.collapsible-list__toggle {
    display:block; width:100%;
    padding:.6rem 1rem;
    background:var(--surface-sunken); border:0;
    color:var(--accent-ink);
    font-size:.8rem; font-weight:600;
    text-align:center; cursor:pointer;
    transition:background .12s ease,color .12s ease;
}
.collapsible-list__toggle:hover {
    background:var(--hcs-50); color:var(--accent-hover);
}

/* Tabelle */
.table {
    --bs-table-bg:transparent;
    --bs-table-hover-bg:var(--surface-sunken);
    color:var(--ink);
}
.table > thead > tr > th {
    padding:.7rem .95rem;
    font-size:.78rem; font-weight:600;
    letter-spacing:.01em;
    color:var(--ink-soft);
    border-bottom:1px solid var(--line-strong);
    white-space:nowrap;
}
.table > tbody > tr > td {
    padding:.72rem .95rem;
    border-bottom:1px solid var(--line);
    vertical-align:middle;
    font-variant-numeric:tabular-nums;
}
.table > tbody > tr:last-child > td { border-bottom:0; }
.table-hover > tbody > tr { transition:background .1s ease; }
.table-card .table > thead > tr > th:first-child,
.table-card .table > tbody > tr > td:first-child { padding-left:1.15rem; }
.table-card .table > thead > tr > th:last-child,
.table-card .table > tbody > tr > td:last-child { padding-right:1.15rem; }
.col-actions { width:1%; white-space:nowrap; text-align:right; }
.cell-strong { font-weight:600; }
.cell-faint { color:var(--ink-faint); }

/* ── DataList: Schnellbearbeitung ──────────────────────────────
   Der Stift ist ein eigenes Klickziel; die Zelle bleibt lesbar und
   markierbar. Auf Touch-Geraeten (kein Hover) ist er dauerhaft sichtbar. */
.dl-cell--editable {
    position: relative;
    padding-right: 2rem;
}
.dl-cell--editable::after {
    content: "";
    position: absolute;
    inset: .15rem .15rem .15rem 0;
    border: 1px dashed transparent;
    border-radius: .25rem;
    pointer-events: none;
}
.dl-cell--editable:hover::after {
    border-color: var(--line);
}
.dl-cell__pencil {
    position: absolute;
    top: 50%;
    right: .35rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    border: 0;
    border-radius: .25rem;
    background: none;
    color: var(--ink-soft);
    opacity: 0;
    cursor: pointer;
}
.dl-cell--editable:hover .dl-cell__pencil,
.dl-cell__pencil:focus-visible {
    opacity: 1;
}
.dl-cell__pencil:hover {
    /* Wie .icon-btn:hover (strukturell dieselbe Komponente): Projekt-Tokens
       statt bs-tertiary-bg -- die Variable ist im Bootstrap-Mapping oben NICHT
       auf ein Projekt-Token umgelegt und faellt sonst auf Bootstraps nativen
       Grauton zurueck statt auf --surface-sunken (Fund 7, Abschluss-Review). */
    background: var(--surface-sunken);
    color: var(--ink);
}
@media (hover: none) {
    .dl-cell__pencil { opacity: 1; }
}

/* Status-Indikator (aktiv / inaktiv) */
.status {
    display:inline-flex; align-items:center; gap:.45em;
    font-size:.8rem; font-weight:500;
}
.status::before {
    content:""; width:.5em; height:.5em; border-radius:50%;
    background:currentColor; flex:none;
}
.status--active { color:var(--success); }
.status--inactive { color:var(--ink-faint); }
.status--inactive::before { background:var(--zinc-300); }

/* Buttons */
.btn {
    --bs-btn-font-size:.9rem;
    --bs-btn-font-weight:500;
    --bs-btn-border-radius:var(--radius-sm);
    --bs-btn-padding-y:.5rem;
    --bs-btn-padding-x:.95rem;
    display:inline-flex; align-items:center; gap:.4rem;
    transition:background .12s ease,border-color .12s ease,transform .04s ease;
}
.btn:active { transform:translateY(.5px); }
.btn-sm { --bs-btn-font-size:.82rem; --bs-btn-padding-y:.32rem; --bs-btn-padding-x:.65rem; }
.btn-primary {
    --bs-btn-bg:var(--zinc-900); --bs-btn-border-color:var(--zinc-900);
    --bs-btn-hover-bg:var(--zinc-800); --bs-btn-hover-border-color:var(--zinc-800);
    --bs-btn-active-bg:var(--zinc-950); --bs-btn-active-border-color:var(--zinc-950);
    --bs-btn-disabled-bg:var(--zinc-400); --bs-btn-disabled-border-color:var(--zinc-400);
}
.btn-accent {
    --bs-btn-color:#fff; --bs-btn-hover-color:#fff; --bs-btn-active-color:#fff;
    --bs-btn-bg:var(--accent); --bs-btn-border-color:var(--accent);
    --bs-btn-hover-bg:var(--accent-hover); --bs-btn-hover-border-color:var(--accent-hover);
    --bs-btn-active-bg:var(--hcs-800); --bs-btn-active-border-color:var(--hcs-800);
}
.btn-outline-secondary {
    --bs-btn-color:var(--ink-soft); --bs-btn-border-color:var(--line-strong);
    --bs-btn-hover-bg:var(--surface-sunken); --bs-btn-hover-border-color:var(--line-strong);
    --bs-btn-hover-color:var(--ink);
    --bs-btn-active-bg:var(--zinc-100); --bs-btn-active-border-color:var(--line-strong);
    --bs-btn-active-color:var(--ink);
}
.btn-outline-primary {
    --bs-btn-color:var(--ink); --bs-btn-border-color:var(--line-strong);
    --bs-btn-hover-bg:var(--zinc-900); --bs-btn-hover-border-color:var(--zinc-900);
    --bs-btn-hover-color:#fff;
    --bs-btn-active-bg:var(--zinc-950); --bs-btn-active-border-color:var(--zinc-950);
}

/* Icon-Button (Tabellen-Aktionen) */
.icon-btn {
    display:inline-grid; place-items:center;
    width:32px; height:32px;
    border-radius:var(--radius-sm);
    color:var(--ink-faint); text-decoration:none;
    transition:background .12s ease,color .12s ease;
}
.icon-btn:hover { background:var(--surface-sunken); color:var(--accent-ink); }

/* Formular */
.form-label {
    font-size:.82rem; font-weight:600;
    color:var(--ink-soft); margin-bottom:.32rem;
}
.form-control,.form-select {
    border-color:var(--line-strong);
    border-radius:var(--radius-sm);
    font-size:.9rem;
    padding:.5rem .7rem;
    color:var(--ink);
}
.form-control::placeholder { color:var(--ink-faint); }
.form-text { font-size:.78rem; color:var(--ink-faint); }
.form-check-input { border-color:var(--line-strong); }
.form-check-input:checked {
    background-color:var(--accent); border-color:var(--accent);
}

/* Abhaengige Felder (AP-F4): Zielfelder (.toggle-group__target) erst zeigen, wenn
   ihr Schalter (.toggle-group__switch) gesetzt ist. Alt-Paritaet ohne JavaScript
   (Alt: Form/fields.html.twig) -- stimmt beim Laden und nach jedem Live-Re-Render.
   Nur AUSblenden: versteckte Felder werden weiter mitgeschickt, kein Wert geht verloren.
   input[type="checkbox"] ist Absicht: ein geschwaerzter Schalter (kein Leserecht) ist
   ein gesperrtes Textfeld und blendet NICHT aus -- sonst saehe man Zielfelder nie,
   die man lesen darf. !important, weil Zielspalten Bootstrap-Utilities wie .d-flex
   tragen (display:flex!important). Browser ohne :has() ignorieren die Regel;
   dann bleibt alles sichtbar wie vorher. */
.toggle-group:has(.toggle-group__switch input[type="checkbox"]:not(:checked)) .toggle-group__target {
    display:none !important;
}

/* Info-Symbol der Feldbeschreibungen — an Formular-Beschriftungen UND an
   Spaltenköpfen der Übersichten. Bewusst zurückhaltend: es steht auf fast
   jeder Seite und darf die Beschriftung daneben nie überstimmen.
   cursor:help statt pointer — es ist keine Schaltfläche, ein Klick tut nichts. */
.field-info {
    display:inline-flex; align-items:center;
    margin-left:.3rem;
    vertical-align:-.125em;
    font-size:.9em; line-height:1;
    color:var(--ink-faint);
    cursor:help;
}
.field-info:hover { color:var(--accent); }

/* Tabs (Edit-Seiten) */
.nav-tabs {
    --bs-nav-tabs-border-color:var(--line-strong);
    border-bottom:1px solid var(--line-strong);
    gap:.15rem;
}
.nav-tabs .nav-link {
    border:0; border-bottom:2px solid transparent;
    margin-bottom:-1px; border-radius:0;
    padding:.6rem .95rem;
    font-size:.9rem; font-weight:500;
    color:var(--ink-soft);
}
.nav-tabs .nav-link:hover {
    border-color:transparent transparent var(--line-strong);
    color:var(--ink); isolation:isolate;
}
.nav-tabs .nav-link.active {
    background:transparent; color:var(--accent-ink); font-weight:600;
    border-color:transparent transparent var(--accent);
}
.nav-tabs .nav-link .badge { font-size:.66rem; }
.tab-content.border {
    border-color:var(--line) !important;
    border-radius:0 0 var(--radius-lg) var(--radius-lg);
}

/* Modal */
.modal-content {
    border:1px solid var(--line);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-pop);
}
.modal-header,.modal-footer { border-color:var(--line); }
.modal-title { font-size:1.1rem; }

/* Badges */
.badge {
    font-weight:500; font-size:.72rem;
    letter-spacing:.01em; padding:.34em .62em;
    border-radius:999px;
}
.badge.bg-secondary { background:var(--zinc-200) !important; color:var(--ink-soft); }
.badge.bg-success { background:var(--success-soft) !important; color:var(--success); }

/* Alerts */
.alert {
    border:1px solid; border-radius:var(--radius);
    font-size:.9rem; padding:.8rem 1rem;
}
.alert-success { background:var(--success-soft); border-color:#cfe0d2; color:#2d5c3e; }
.alert-danger,.alert-error { background:var(--danger-soft); border-color:#e6c3bf; color:#8f342a; }
.alert-info { background:var(--accent-soft); border-color:var(--accent-line); color:var(--accent-ink); }
.alert-warning { background:#fbf4e6; border-color:#ecd9ad; color:#8a6516; }

/* Empty-State */
.empty-state {
    text-align:center;
    padding:2.75rem 1rem;
    color:var(--ink-faint);
}
.empty-state__icon { font-size:1.6rem; opacity:.55; margin-bottom:.5rem; }

/* Dashboard-Zweispalter: Feature-Landkarte links, Live-Widgets rechts.
   Die DOM-Reihenfolge ist Rail-dann-Main (Widgets zuerst im Quelltext, damit
   sie „oben"/zuerst bleiben); die explizite grid-column-Zuordnung setzt die
   Landkarte optisch nach links (Spalte 1) und die Leiste nach rechts (Spalte 2).
   ~60/40, damit die 2-3-spaltigen Widget-Tabellen rechts lesbar bleiben. */
/* Turbo-Ladebalken (oberer Seitenrand) in HCS-Gold statt Browser-Blau --
   sichtbar auf dem blauen Header. */
.turbo-progress-bar { background:var(--hcs-gold); height:3px; }

/* Dashboard-Bereichs-Reiter (HCS / REC / Personal / System) -- gleiche Optik
   wie die App-Menü-Reiter: randlos, aktiver Reiter mit blauem Unterstrich. */
.dashboard-tabs {
    border-bottom:1px solid var(--line);
    gap:.25rem;
    margin-bottom:1.6rem;
    flex-wrap:wrap;
}
.dashboard-tabs .nav-link {
    border:0;
    border-bottom:2px solid transparent;
    margin-bottom:-1px;
    padding:.6rem .95rem;
    color:var(--ink-soft);
    font-weight:500; font-size:.92rem;
    background:none;
}
.dashboard-tabs .nav-link:hover { color:var(--ink); border-bottom-color:var(--line-strong); }
.dashboard-tabs .nav-link.active {
    color:var(--accent-ink); font-weight:600;
    border-bottom-color:var(--accent);
    background:none;
}

.dashboard-layout {
    display:grid;
    grid-template-columns:1.55fr 1fr;
    grid-template-areas:"main rail";
    gap:1.75rem;
    align-items:start;
}
.dashboard-main { grid-area:main; min-width:0; }
.dashboard-rail { grid-area:rail; min-width:0; }
.dashboard-layout--no-rail {
    grid-template-columns:1fr;
    grid-template-areas:"main";
}

/* In der schmaleren linken Spalte die Kachel-Mindestbreite senken, damit die
   Kacheln 3-spaltig bleiben statt auf 2 zu fallen (Voll-Breite bleibt 232px). */
.dashboard-main .module-grid {
    grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
}
/* Ohne Widget-Leiste (Reiter ohne Listen) laufen die Kacheln ueber die volle
   Breite -- dort groessere Mindestbreite, damit es 4-5 pro Reihe werden statt 6
   schmaler Streifen (notes.md). */
.dashboard-layout--no-rail .dashboard-main .module-grid {
    grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
}

/* Unter ~992px stapeln: eine Spalte, Widgets oben, dann Landkarte -- wie das
   bisherige „Inhalt oben". Die --no-rail-Regel steht bewusst NACH der Basis-
   Regel, damit sie deren Leiste-Zeile ueberschreibt (kein leerer rail-Track). */
@media (max-width:991.98px) {
    .dashboard-layout {
        grid-template-columns:1fr;
        grid-template-areas:"rail" "main";
    }
    .dashboard-layout--no-rail { grid-template-areas:"main"; }
}

/* Dashboard-Kacheln */
.module-section + .module-section { margin-top:2rem; }
.module-section__title {
    font-family:var(--font-sans);
    font-size:.8rem; font-weight:600;
    letter-spacing:.01em;
    color:var(--ink-soft);
    margin-bottom:.85rem;
}
.module-grid {
    display:grid;
    grid-template-columns:repeat(auto-fill,minmax(232px,1fr));
    gap:.85rem;
}
/* Dashboard-Charts (Rechnungs-Auswertung). Chart.js braucht einen hoehen-
   definierten, relativ positionierten Canvas-Container (maintainAspectRatio:false). */
/* Zwei Charts nebeneinander im Verhältnis 70/30 (Balken breiter als der
   Doughnut). Auf schmalen Viewports gestapelt. minmax(0,…) verhindert, dass die
   Canvas-Breite die fr-Aufteilung sprengt. */
.chart-grid { display:grid; grid-template-columns:minmax(0,7fr) minmax(0,3fr); gap:1rem; }
@media (max-width:575.98px) { .chart-grid { grid-template-columns:1fr; } }
.chart-card {
    background:var(--surface);
    border:1px solid var(--line);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-sm);
    padding:1.1rem 1.25rem 1.25rem;
}
.chart-card__title {
    font-family:var(--font-sans);
    font-size:.88rem; font-weight:600;
    letter-spacing:0;
    color:var(--ink-soft);
    margin:0 0 .9rem;
}
.chart-card__canvas { position:relative; height:240px; }
/* Kennzahl über einem Chart (z. B. Gesamt-Gehaltslast). */
.chart-card__kpi {
    font-family:var(--font-serif); font-weight:600;
    font-size:1.7rem; letter-spacing:-.01em;
    color:var(--ink); margin:0 0 1rem;
}
.chart-card__kpi-unit {
    font-family:var(--font-sans); font-weight:500;
    font-size:.8rem; letter-spacing:0;
    color:var(--ink-soft); margin-left:.5rem;
}
/* Bezugsmenge UNTER einem Chart („Berücksichtigt: 1.234 Rechnungen"). Bewusst
   recessiv: die Flaeche traegt die Aussage, die Fallzahl nur ihre Belastbarkeit. */
.chart-card__note {
    font-family:var(--font-sans); font-size:.78rem;
    color:var(--ink-faint);
    margin:.9rem 0 0; padding-top:.7rem;
    border-top:1px solid var(--line);
}
.module-tile {
    display:flex; align-items:center; gap:.85rem;
    padding:1.05rem 1.15rem;
    background:var(--surface);
    border:1px solid var(--line);
    border-radius:var(--radius);
    text-decoration:none; color:var(--ink);
    box-shadow:var(--shadow-xs);
    transition:border-color .14s ease,box-shadow .14s ease,transform .14s ease;
}
.module-tile:hover {
    color:var(--ink);
    border-color:var(--accent-line);
    box-shadow:var(--shadow-md);
    transform:translateY(-2px);
}
.module-tile__icon {
    width:40px; height:40px; flex:none;
    display:grid; place-items:center;
    background:var(--accent-soft); color:var(--accent);
    border-radius:9px; font-size:1.15rem;
    transition:background .14s ease,color .14s ease;
}
.module-tile:hover .module-tile__icon {
    background:var(--accent); color:#fff;
}
.module-tile__label { font-weight:600; font-size:.92rem; line-height:1.25; }

/* Geplante Kachel: sichtbar, aber tot. `.module-tile:hover` greift auch auf
   einem <span>, deshalb müssen die Hover-Effekte hier gezielt zurückgenommen
   werden — sonst hebt sich eine tote Kachel wie eine lebende. Selektor bewusst
   verdoppelt (`.module-tile.module-tile--planned`, nicht nur `.module-tile--planned`):
   so gewinnt die Regel unabhängig von der Reihenfolge im Stylesheet über die
   höhere Spezifität gegen `.module-tile:hover` (beide sonst 0-2-0 / 0-3-0 und
   damit von der Reihenfolge abhängig). */
.module-tile.module-tile--planned:hover {
    border-color:var(--line);
    box-shadow:none;
    transform:none;
}
.module-tile--planned {
    cursor:default;
    background:var(--surface-sunken);
    border-style:dashed;
    box-shadow:none;
}
.module-tile--planned .module-tile__label { color:var(--ink-soft); font-weight:500; }
.module-tile--planned .module-tile__icon,
.module-tile.module-tile--planned:hover .module-tile__icon {
    background:var(--zinc-100);
    color:var(--ink-faint);
}

/* ── 8. Login ─────────────────────────────────────────────── */
.auth-wrap {
    min-height:100vh;
    display:grid; place-items:center;
    padding:3rem 1rem;
}
.auth-card {
    width:100%; max-width:392px;
    background:var(--surface);
    border:1px solid var(--line);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-md);
    padding:2.4rem;
}
/* Logo zentriert ueber die volle Kartenbreite. Die Plaketten-Optik der
   Header-Klasse (weisse Flaeche/Rand/Schatten) wird hier neutralisiert --
   auf der hellen Karte braucht das Logo keine Plakette. */
.auth-brand { text-align:center; margin-bottom:1.9rem; }
.auth-brand .app-brand__logo {
    height:64px; margin:0 auto;
    background:none; padding:0;
    border:0; border-radius:0; box-shadow:none;
}
.auth-card__title { font-size:1.3rem; margin:0 0 .3rem; }
.auth-card__lead { color:var(--ink-soft); font-size:.88rem; margin:0 0 1.6rem; }
.auth-field { margin-bottom:1.1rem; }
.auth-card .btn { width:100%; justify-content:center; }

/* -------- Salarytable Tarif-Matrix-Editor ------------------------------- */
.salarytable-matrix { margin:0; }
.salarytable-matrix th,
.salarytable-matrix td {
    padding:.35rem .45rem;
    border:1px solid var(--line);
    text-align:center;
    vertical-align:middle;
    background:var(--surface);
}
.salarytable-matrix th {
    background:var(--surface-sunken);
    font-weight:600;
    color:var(--ink-soft);
    font-size:.82rem;
}
.salarytable-matrix__labels td {
    background:var(--surface-sunken);
    color:var(--ink-soft);
    font-size:.78rem;
    font-style:italic;
}
.salarytable-matrix__note td {
    background:transparent;
    border:none;
    color:var(--ink-soft);
    font-size:.82rem;
    font-style:italic;
    text-align:left;
    padding-top:.6rem;
}
.salarytable-matrix input.form-control-sm {
    text-align:right;
    min-width:5.2rem;
    font-variant-numeric: tabular-nums;
}

/* ── 10. Zugangsprofile: Editor-Sektionen + Profil-Vergleich ──
   Der Editor gliedert die Rechte in Bereichs-Reiter; jede Sektion darin
   (Funktionen, Widgets, Entity-Aktionen, Felder) ist ein eigener Block mit
   Kopfzeile und „Alle markieren". */
.rbac-section { margin-bottom:1.75rem; }
.rbac-section__head {
    display:flex; align-items:center; justify-content:space-between;
    gap:1rem; margin-bottom:.7rem;
    padding-bottom:.4rem; border-bottom:1px solid var(--line);
}
.rbac-section__title {
    font-family:var(--font-sans);
    font-size:.88rem; font-weight:600;
    color:var(--ink); margin:0;
}
/* Funktions-/Widget-Häkchen in Spalten statt untereinander: 19 Funktionen als
   Einzelliste wären eine sehr lange, sehr schmale Spalte. */
.rbac-checks {
    display:grid; gap:.25rem .9rem;
    grid-template-columns:repeat(auto-fill, minmax(19rem, 1fr));
}
.rbac-actions td:first-child, .rbac-actions th:first-child { white-space:nowrap; }

/* ── Profil-Vergleich (Matrix) ──────────────────────────────
   Zeilen = Rechte, Spalten = Profile. Die Tabelle ist naturgemäß breiter als
   der Bildschirm: die Zeilenköpfe bleiben deshalb beim Querscrollen stehen,
   sonst weiß man nach drei Spalten nicht mehr, welches Recht man anhakt. */
.matrix-tools {
    display:flex; flex-wrap:wrap; gap:1.25rem;
    padding:.8rem 1rem; margin-bottom:1rem;
    background:var(--surface); border:1px solid var(--line);
    border-radius:var(--radius);
}
.matrix-tools__group { display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; }
.matrix-tools__label {
    font-family:var(--font-sans); font-size:.76rem; font-weight:600;
    color:var(--ink-soft); flex:none;
}
.matrix-chips { display:flex; flex-wrap:wrap; gap:.35rem; }
.matrix-chip {
    font-size:.78rem; line-height:1.4;
    padding:.15rem .6rem;
    border:1px solid var(--line-strong); border-radius:100px;
    background:var(--surface-sunken); color:var(--ink-faint);
    cursor:pointer;
}
.matrix-chip.is-on { background:var(--accent-soft); border-color:var(--accent-line); color:var(--accent-ink); }
.matrix-legend { display:flex; flex-wrap:wrap; gap:1rem; font-size:.78rem; color:var(--ink-soft); }
.matrix-legend span { display:flex; align-items:center; gap:.35rem; }

.matrix-status { min-height:1.3rem; margin:0 0 .6rem; font-size:.8rem; color:var(--ink-faint); }
.matrix-status.is-error { color:var(--danger); font-weight:600; }

.matrix-block__title {
    font-family:var(--font-sans); font-size:.88rem; font-weight:600;
    color:var(--ink); margin:1.5rem 0 .6rem;
}
.matrix-scroll { max-height:70vh; overflow:auto; border:1px solid var(--line); border-radius:var(--radius-sm); }
.matrix-table { margin:0; font-size:.82rem; }
.matrix-table__rowhead {
    position:sticky; left:0; z-index:2;
    background:var(--surface);
    text-align:left; font-weight:500;
    white-space:nowrap;
    box-shadow:1px 0 0 var(--line);
}
.matrix-table thead th { position:sticky; top:0; z-index:3; background:var(--surface-sunken); }
.matrix-table thead .matrix-table__rowhead { z-index:4; }
.matrix-group th { background:var(--surface-sunken); font-weight:600; color:var(--ink-soft); }
.matrix-cell { text-align:center; white-space:nowrap; }
.matrix-cell--sub { font-size:.7rem; color:var(--ink-faint); font-weight:600; }
.matrix-cell--locked { color:var(--ink-faint); }
/* Ausgeblendete Profil-Spalte — der Filter oben schaltet sie. */
.matrix-cell.is-hidden { display:none; }

/* Lesen und Schreiben müssen auf einen Blick unterscheidbar sein: gleiche
   Häkchen nebeneinander liest man sonst als eine Spalte. Schreiben ist das
   schwerwiegendere Recht und bekommt deshalb die kräftige Farbe. */
.matrix-box { width:1rem; height:1rem; cursor:pointer; }
.matrix-box--write { accent-color:var(--accent); }
.matrix-box--read { accent-color:var(--ink-faint); }
.matrix-box:disabled { cursor:progress; opacity:.5; }

/* Belegungsübersicht: Bereichs- und Beschulungsfarben aus dem Altsystem. */
.occupancy-area--type-teilstationaer { border-left: 6px solid #00FF00; padding-left: .5rem; }
.occupancy-area--type-stationaer-train { border-left: 6px solid #99CC00; padding-left: .5rem; }
.occupancy-area--type-full { border-left: 6px solid #FFA500; padding-left: .5rem; }
.occupancy-area--type-7t { border-left: 6px solid #FFFF00; padding-left: .5rem; }
.occupancy-area--type-5t { border-left: 6px solid #00CCFF; padding-left: .5rem; }

.occupancy-table .occupancy-row--i > td { background-color: #FCD5B4; }
.occupancy-table .occupancy-row--i_plus > td { background-color: #FD7BF7; }
.occupancy-table .occupancy-row--ext > td { background-color: #DDDDDD; }
.occupancy-table .occupancy-cell--special { background-color: #bd3a28; color: #fff; }
