/* ==========================================================================
   WiLo App — Design-System 2.0 (Override-Schicht über Bootstrap)
   Professionell, ruhig, flach. Hell + Dunkel. Marke: Wald-Grün + W-Logo.
   ========================================================================== */

:root {
  /* Marke */
  --brand: #2f6b41;
  --brand-hover: #255836;
  --brand-strong: #1d4a2c;
  --brand-soft: #e8f1ea;
  --brand-softer: #f3f8f4;

  /* Flächen & Text (kühle, ruhige Neutraltöne) */
  --bg: #f6f7f8;
  --surface: #ffffff;
  --surface-2: #fafbfc;
  --border: #e7e9ec;
  --border-strong: #d6dade;
  --text: #18211c;
  --text-muted: #687268;
  --text-faint: #9aa39c;

  --sidebar-w: 248px;

  --radius: 12px;
  --radius-sm: 9px;
  --radius-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow: 0 8px 24px -6px rgba(16, 24, 40, .14);

  /* Statusfarben (Lastenheft 3.6 — Semantik fest) */
  --status-rot: #d64545;
  --status-gelb: #c47d10;
  --status-blau: #2f6bd6;
  --status-lila: #7c4ddb;
  --status-gruen: #2f9e57;
  --status-rot-soft: #fbecec;
  --status-gelb-soft: #fbf2e2;
  --status-blau-soft: #eaf1fc;
  --status-lila-soft: #f1ebfc;
  --status-gruen-soft: #e6f4ec;
  --status-rot-ink: #9a2a2a;
  --status-gelb-ink: #8a5807;
  --status-blau-ink: #1c4a9e;
  --status-lila-ink: #5a32a6;
  --status-gruen-ink: #1c7040;

  --sperre: #79817b;
  --focus-ring: 0 0 0 3px rgba(47, 107, 65, .22);
}

:root[data-theme="dark"] {
  --brand: #56b079;
  --brand-hover: #66bd87;
  --brand-strong: #7cc99a;
  --brand-soft: #1b2922;
  --brand-softer: #161f19;

  --bg: #0e1311;
  --surface: #151c18;
  --surface-2: #121814;
  --border: #283129;
  --border-strong: #344036;
  --text: #e8ede9;
  --text-muted: #99a69d;
  --text-faint: #6f7a72;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow: 0 10px 26px -6px rgba(0, 0, 0, .55);

  --status-rot-soft: #3a1f1f;
  --status-gelb-soft: #392c14;
  --status-blau-soft: #16233d;
  --status-lila-soft: #271a3a;
  --status-gruen-soft: #16301f;
  --status-rot-ink: #f1a9a9;
  --status-gelb-ink: #ecc479;
  --status-blau-ink: #9cc0ef;
  --status-lila-ink: #c3a9ee;
  --status-gruen-ink: #8fd3ab;

  --focus-ring: 0 0 0 3px rgba(86, 176, 121, .28);
}

/* --- Basis ---------------------------------------------------------------- */
* { scrollbar-color: var(--border-strong) transparent; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  font-size: 14.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5, .h1, .h2, .h3, .h4, .h5 {
  color: var(--text);
  font-weight: 600;
  letter-spacing: -.012em;
  line-height: 1.25;
}
.text-muted { color: var(--text-muted) !important; }
a { color: var(--brand); text-decoration-color: color-mix(in srgb, var(--brand) 35%, transparent); text-underline-offset: 2px; }
a:hover { color: var(--brand-hover); }
hr { border-color: var(--border); opacity: 1; }
code { color: var(--brand-hover); background: var(--brand-soft); padding: .08em .4em; border-radius: 5px; font-size: .86em; }

/* --- W-Logo & Icons -------------------------------------------------------- */
.wilo-logo { display: block; width: 26px; height: 26px; color: currentColor; }
.ic { width: 1em; height: 1em; display: inline-block; vertical-align: -0.125em; }

/* --- App-Shell: Sidebar + Inhalt ------------------------------------------ */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}
.sidebar-brand {
  display: flex; align-items: center; gap: 11px;
  padding: 17px 18px 16px;
  text-decoration: none;
}
.sidebar-brand:hover { background: var(--surface-2); }
.sidebar-brand .logo-tile {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--brand); color: #fff;
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 36px;
}
.sidebar-brand .logo-tile .wilo-logo { width: 22px; height: 22px; }
.sidebar-brand .brand-text { font-size: 1.04rem; font-weight: 600; color: var(--text); letter-spacing: -.01em; }
.sidebar-brand .brand-text span { font-weight: 400; color: var(--text-muted); }

.sidebar-nav { padding: 10px 12px; flex: 1 1 auto; overflow-y: auto; }
.sidebar-nav .nav-label {
  font-size: .67rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-faint); font-weight: 600; padding: 10px 10px 4px;
}
.sidebar-nav .nav-label:first-child { padding-top: 4px; }
.sidebar-nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 11px; border-radius: var(--radius-sm);
  color: var(--text-muted); text-decoration: none;
  font-weight: 500; font-size: .875rem; margin-bottom: 1px;
  position: relative; transition: background .12s, color .12s;
}
.sidebar-nav a .ico { width: 18px; flex: 0 0 18px; font-size: 1.08rem; display: inline-flex; align-items: center; justify-content: center; }
.sidebar-nav a:hover { background: var(--surface-2); color: var(--text); }
.sidebar-nav a.active { background: var(--brand-soft); color: var(--brand-hover); font-weight: 600; }
.sidebar-nav a.active::before {
  content: ""; position: absolute; left: -12px; top: 8px; bottom: 8px;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--brand);
}

.sidebar-user {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; border-top: 1px solid var(--border);
}
.sidebar-user .avatar {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-hover);
  display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: .85rem; flex: 0 0 34px;
}
/* Seit dem 05.10.2026 traegt der Block nur noch den Namen, und der ist der
   Verweis auf die eigenen Anmeldedaten. Rolle und ausgeschriebener Verweis
   sind weg: zwei Zeilen Kleingedrucktes in der Fusszeile liest niemand. */
.sidebar-user .who {
  line-height: 1.25; min-width: 0;
  display: flex; align-items: center; gap: 10px;
  color: inherit; text-decoration: none; border-radius: 7px;
  padding: 3px 6px; margin: -3px -6px;
}
.sidebar-user .who .name {
  font-weight: 600; font-size: .85rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-user .who:hover { background: var(--brand-soft); color: var(--brand-hover); }
/* Der Name schiebt alles Folgende nach rechts. Frueher stand das margin auf
   der Glocke UND auf dem Abmelden-Formular, dadurch standen die beiden
   Zeichen mit einer Luecke dazwischen an verschiedenen Stellen. Am Namen
   stehend bleiben sie als Paar beieinander, auch wenn eins davon mal
   wegfaellt. */
.sidebar-user .who { margin-right: auto; }
.sidebar-user .logout-btn,
.sidebar-user .icon-btn {
  border: none; background: transparent; color: var(--text-muted);
  cursor: pointer; padding: 5px; border-radius: 7px;
  display: inline-flex; text-decoration: none; line-height: 1;
  /* Mittig, waagerecht wie senkrecht. Ohne diese zwei Zeilen sass das
     Zeichen oben links im Kasten, sobald `@media (pointer: coarse)` ihn
     auf 40x40 aufzog. Am Rechner faellt das nicht auf, auf dem Telefon
     schon (Micha, 19.10.2026). */
  align-items: center; justify-content: center;
}
.sidebar-user .logout-btn { font-size: 1.05rem; }
.sidebar-user .icon-btn .ico { font-size: 1.1rem; }
.sidebar-user .logout-btn:hover,
.sidebar-user .icon-btn:hover { background: var(--brand-soft); color: var(--brand-hover); }
.sidebar-user .notif-btn { position: relative; }
.sidebar-user .notif-badge {
  position: absolute; top: -2px; right: -3px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 8px; background: var(--status-rot); color: #fff;
  font-size: .62rem; font-weight: 600; line-height: 16px; text-align: center;
}

.app-main { flex: 1 1 auto; min-width: 0; padding: 26px 30px; }

/* --- Launcher / Kachelansicht (Alternative zur Sidebar) --- */
.launcher-actions .icon-btn { width: 36px; height: 36px; border: 1px solid var(--border); background: var(--surface); border-radius: 9px; color: var(--text-muted); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; position: relative; }
.launcher-actions .icon-btn:hover { border-color: var(--border-strong); color: var(--text); }
.launcher-section { margin-bottom: 38px; }
.launcher-grouptitle { font-size: .76rem; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted); margin: 0 0 16px; }
.launcher-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 18px; }
.launcher-card { display: flex; flex-direction: column; gap: 11px; padding: 22px 22px 20px; border-radius: var(--radius); background: var(--surface); border: 1px solid var(--border); text-decoration: none; color: var(--text); transition: border-color .12s, box-shadow .12s, transform .12s; }
.launcher-card:hover { border-color: var(--brand); box-shadow: 0 6px 20px rgba(20, 40, 28, .08); transform: translateY(-2px); }
.launcher-ico { width: 46px; height: 46px; border-radius: 13px; background: var(--brand-soft); color: var(--brand-hover); display: flex; align-items: center; justify-content: center; }
.launcher-ico svg { width: 23px; height: 23px; }
.launcher-name { font-weight: 650; font-size: 1.04rem; letter-spacing: -.01em; line-height: 1.2; }
.launcher-desc { font-size: .82rem; color: var(--text-muted); line-height: 1.4; }
:root[data-theme="dark"] .launcher-card:hover { box-shadow: 0 6px 20px rgba(0, 0, 0, .35); }

/* Einheitlicher Zurück-Knopf */
/* --- Brotkrumenpfad ---------------------------------------------------------
   Ersetzt seit 24.08.2026 den einzelnen „Zurück"-Knopf: Er zeigt, wo man ist,
   und lässt jede Stufe darüber direkt anspringen. */
.brotkrumen { margin-bottom: 16px; }
.brotkrumen ol {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  list-style: none; margin: 0; padding: 0;
  font-size: .84rem; color: var(--text-muted);
}
.brotkrumen li + li::before {
  content: "›"; margin-right: 6px; color: var(--text-faint);
}
.brotkrumen a { color: var(--text-muted); text-decoration: none; }
.brotkrumen a:hover { color: var(--brand-hover); text-decoration: underline; }
.brotkrumen [aria-current="page"] { color: var(--text); font-weight: 600; }

/* Der alte Zurück-Knopf, noch für die Druckansicht und Altbestände gebraucht */
.back-bar { margin-bottom: 16px; }
.btn-back {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-muted); font-size: .84rem; font-weight: 500;
  padding: 5px 12px; border-radius: var(--radius-sm); cursor: pointer;
}
.btn-back:hover { background: var(--brand-soft); color: var(--brand-hover); border-color: var(--border-strong); }

/* --- Karten (flach, ruhig) -------------------------------------------------- */
.card { background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: none; }
.card-header { background: transparent; border-bottom: 1px solid var(--border); font-weight: 600; padding: .85rem 1.1rem; }
.card-body { padding: 1.1rem 1.2rem; }
.card .table { border-radius: 0 0 var(--radius) var(--radius); overflow: hidden; }

/* --- Tabellen --------------------------------------------------------------- */
.table { color: var(--text); border-color: var(--border); margin-bottom: 0; }
.table thead th {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .035em;
  color: var(--text-muted); font-weight: 600; border-bottom: 1px solid var(--border);
  padding: .72rem .95rem; background: var(--surface-2); white-space: nowrap;
}
/* Sortierbare Spaltenkoepfe (Liste). Der Pfeil steht auch bei inaktiven
   Spalten im Markup, nur durchsichtig: sonst waechst die Spalte beim
   Ueberfahren und die Tabellenzeile zuckt.

   Wiederhergestellt am 23.09.2026. Am 22.09. habe ich beim Nachtrag fuer das
   Handgeraet eine aeltere Kopie dieser Datei zurueckgeschrieben, damit war
   dieser Block weg und die Koepfe standen als blaue Verweise da. */
.th-sort {
  color: inherit; text-decoration: none; display: inline-flex;
  align-items: center; gap: 4px; white-space: nowrap;
}
.th-sort:hover { color: var(--text); }
.th-sort.is-aktiv { color: var(--text); }
.th-pfeil { font-size: .82em; line-height: 1; }
.th-sort:not(.is-aktiv) .th-pfeil::after { content: "\25B4"; opacity: 0; }
.th-sort:not(.is-aktiv):hover .th-pfeil::after { opacity: .45; }
.table td { padding: .72rem .95rem; border-color: var(--border); vertical-align: middle; }
.table-hover tbody tr { transition: background .12s; }
.table-hover tbody tr:hover { background: var(--surface-2); }
.table-striped > tbody > tr:nth-of-type(odd) > * { background: var(--surface-2); box-shadow: none; }
.detail-table th {
  width: 38%; font-weight: 500; color: var(--text-muted); font-size: .86rem;
  background: transparent; text-transform: none; letter-spacing: 0;
}
.detail-table td { font-weight: 500; }
/* Lange Freitext-Spalten (z. B. Sperrungs-Grund/Notiz) sauber umbrechen statt Tabelle sprengen */
.cell-wrap { white-space: normal; word-break: break-word; overflow-wrap: anywhere; max-width: 22rem; }
/* Kompakter Leerzustand innerhalb einer Card (z. B. Dokumente im Slot-Detail) */
.doc-empty { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 13px 15px; border: 1px dashed var(--border-strong); border-radius: var(--radius-sm); background: var(--surface-2); font-size: .88rem; }

/* --- Listen (Bootstrap list-group, token-basiert für Dunkelmodus) ----------- */
.list-group { border-radius: var(--radius); }
.list-group-item { background: var(--surface); color: var(--text); border-color: var(--border); }
.list-group-item-action:hover, .list-group-item-action:focus { background: var(--surface-2); color: var(--text); }
.list-group-flush > .list-group-item { border-left: 0; border-right: 0; }

/* --- Buttons ---------------------------------------------------------------- */
.btn { border-radius: var(--radius-sm); font-weight: 500; padding: .42rem .9rem; transition: background .12s, border-color .12s, color .12s, box-shadow .12s; }
.btn-sm { padding: .34rem .8rem; border-radius: 8px; font-size: .82rem; }
.btn:disabled, .btn.disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.btn:focus-visible, .form-control:focus, .form-select:focus { box-shadow: var(--focus-ring); border-color: var(--brand); outline: none; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-primary:hover, .btn-primary:active, .btn-primary:focus { background: var(--brand-hover) !important; border-color: var(--brand-hover) !important; color: #fff; }
.btn-outline-primary { color: var(--brand-hover); border-color: var(--border-strong); background: var(--surface); }
.btn-outline-primary:hover { background: var(--brand-soft); color: var(--brand-hover); border-color: var(--brand); }
.btn-outline-secondary { color: var(--text); border-color: var(--border-strong); background: var(--surface); }
.btn-outline-secondary:hover { background: var(--surface-2); color: var(--text); border-color: var(--text-faint); }
.btn-success { background: var(--status-gruen); border-color: var(--status-gruen); color: #fff; }
.btn-success:hover { background: var(--status-gruen-ink); border-color: var(--status-gruen-ink); }
.btn-outline-danger { color: var(--status-rot); border-color: color-mix(in srgb, var(--status-rot) 40%, var(--border)); background: var(--surface); }
.btn-outline-danger:hover { background: var(--status-rot); border-color: var(--status-rot); color: #fff; }
.btn-danger { background: var(--status-rot); border-color: var(--status-rot); }
.btn-danger:hover { background: var(--status-rot-ink); border-color: var(--status-rot-ink); }

/* --- Formulare -------------------------------------------------------------- */
.form-label { font-weight: 500; font-size: .83rem; color: var(--text); margin-bottom: .45rem; }
.form-control, .form-select {
  border-radius: var(--radius-sm); border-color: var(--border);
  color: var(--text); background: var(--surface); font-size: .9rem;
  transition: border-color .14s, box-shadow .14s;
}
.form-control::placeholder { color: var(--text-faint); }
.form-control.is-invalid, .form-select.is-invalid { border-color: var(--status-rot); }
/* Feld mit Validierungsfehler (Wrapper-Variante, ohne Eingriff ins Form-Widget) */
.has-error .form-control, .has-error .form-select { border-color: var(--status-rot); background: var(--status-rot-soft); }
.has-error .form-control:focus, .has-error .form-select:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-rot) 22%, transparent); }
.form-control:disabled, .form-select:disabled, .form-check-input:disabled { opacity: .55; cursor: not-allowed; background: var(--surface-2); }
.form-text, .field-hint { color: var(--text-muted); }
.field-hint { font-size: .73rem; font-weight: 400; }
.check-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 2px 18px; max-height: 240px; overflow-y: auto; padding: 10px 6px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
}
.check-list .form-check { margin-bottom: 2px; }
/* Kopfzeile einer Häkchenliste: Beschriftung links, „Alle auswählen" rechts.
   Ohne den Knopf müsste man bei den Klienten 18 Häkchen einzeln setzen
   (Wunsch 25.08.2026). */
.check-kopf { display: flex; align-items: center; gap: .5rem; margin-bottom: .3rem; }
.check-kopf .form-label { margin-bottom: 0; }
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }
.form-check-input:focus { box-shadow: var(--focus-ring); border-color: var(--brand); }

/* --- Alerts ----------------------------------------------------------------- */
.alert { border-radius: var(--radius); border: 1px solid transparent; padding: .75rem 1rem; }

/* Der Schliessknopf sass nicht oben rechts, sondern spuerbar tiefer, und die
   Meldung wurde dadurch hoeher als noetig. Zwei Ursachen zusammen: Bootstrap
   gibt dem Knopf ein Innenabstandspaket (1.25rem 1rem), und unter
   `pointer: coarse` kommen 40px Mindestgroesse dazu. Gemeldet von Micha am
   16.09.2026 beim Anlegen eines Zeitfensters.
   Jetzt senkrecht mittig statt oben, die Flaeche fuer den Finger bleibt. */
.alert-dismissible { padding-right: 3rem; }
.alert-dismissible .btn-close {
  top: 50%; right: .5rem; transform: translateY(-50%);
  padding: 0; display: inline-flex; align-items: center; justify-content: center;
}

/* --- Seitenkopf: Titel links, Bedienknoepfe rechts --------------------------
   Vorher lagen Titel, Datum und drei Knopfgruppen in einer Flex-Zeile, die
   erste Gruppe mit `ms-auto`. Auf breitem Schirm sah das richtig aus, auf
   einem Telefon wurde daraus ein rechtsbuendiger, ausgefranster Stapel.
   Gemeldet am 16.09.2026. Zwei Gruppen statt sechs Einzelteilen, und unter
   700px nehmen die Knopfgruppen die volle Breite. */
.seiten-kopf { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.seiten-kopf-titel {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; min-width: 0;
}
.seiten-kopf-aktionen {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-left: auto;
}

/* --- Einklappbare Filterkarte ---------------------------------------------- */
.cal-filter > .filter-kopf {
  cursor: pointer; padding: .6rem 1rem; font-size: .86rem; font-weight: 600;
  color: var(--text-muted); list-style: none;
}
.cal-filter > .filter-kopf::-webkit-details-marker { display: none; }
.cal-filter > .filter-kopf::before {
  content: "\25b8"; display: inline-block; margin-right: .5rem;
  transition: transform .12s;
}
.cal-filter[open] > .filter-kopf::before { transform: rotate(90deg); }
.cal-filter > .filter-kopf:hover { color: var(--text); }
.cal-filter[open] > .filter-kopf { border-bottom: 1px solid var(--border); }
.filter-marke {
  background: var(--brand-soft); color: var(--brand-hover);
  border-radius: 7px; padding: 1px 7px; font-size: .74rem; font-weight: 600;
}
.alert-success { background: var(--status-gruen-soft); color: var(--status-gruen-ink); border-color: color-mix(in srgb, var(--status-gruen) 30%, transparent); }
.alert-danger { background: var(--status-rot-soft); color: var(--status-rot-ink); border-color: color-mix(in srgb, var(--status-rot) 30%, transparent); }
.alert-warning { background: var(--status-gelb-soft); color: var(--status-gelb-ink); border-color: color-mix(in srgb, var(--status-gelb) 30%, transparent); }
.alert-info { background: var(--brand-soft); color: var(--brand-hover); border-color: color-mix(in srgb, var(--brand) 25%, transparent); }
:root[data-theme="dark"] .alert-danger { background: #4a2222; color: #ffb4b4; border-color: #6e3030; }

/* --- Wiederverwendbare Muster (Empty-State, Segmented/View-Switch) ---------- */
.empty-state { text-align: center; padding: 42px 22px; color: var(--text-muted); }
.empty-state .ico, .empty-state svg { width: 30px; height: 30px; opacity: .45; margin-bottom: 6px; }
.empty-state h3 { font-size: 1rem; font-weight: 600; color: var(--text); margin: 4px 0 4px; }
.empty-state p { font-size: .88rem; margin: 0 auto; max-width: 380px; }
.view-switch .btn.active, .view-switch .btn.active:hover { background: var(--brand); border-color: var(--brand); color: #fff; }

/* --- Status-Pills (sanft: weicher Grund + farbiger Text + Punkt) ------------ */
.status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 11px 3px 9px; border-radius: var(--radius-pill);
  font-size: .78rem; font-weight: 500; letter-spacing: .005em; border: 1px solid transparent;
}
.status-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 6px; }
.status-pill.status-rot   { background: var(--status-rot-soft);   color: var(--status-rot-ink); }
.status-pill.status-gelb  { background: var(--status-gelb-soft);  color: var(--status-gelb-ink); }
.status-pill.status-blau  { background: var(--status-blau-soft);  color: var(--status-blau-ink); }
.status-pill.status-lila  { background: var(--status-lila-soft);  color: var(--status-lila-ink); }
.status-pill.status-gruen { background: var(--status-gruen-soft); color: var(--status-gruen-ink); }
.status-pill.status-lock  { background: var(--surface-2); color: var(--text-muted); border-color: var(--border); }
/* Sonstiger Eintrag ohne Zeitstempel: dieselbe Optik wie das Schloss.
   Kein Fortschritt, also auch keine Statusfarbe. */
.status-pill.status-neutral { background: var(--surface-2); color: var(--text-muted); border-color: var(--border); }
/* Storniert: grau und durchgestrichen. Die Zeile steht nur in der Liste und
   nur, wenn jemand "Auch stornierte" angehakt hat. Sie muss auf einen Blick
   von einer gueltigen Buchung zu unterscheiden sein. */
.status-pill.status-storniert { background: var(--surface-2); color: var(--text-muted); border-color: var(--border); text-decoration: line-through; }
/* Termin unklar: grau wie neutral, aber ohne Durchstreichen. Bewusst
   nicht rot, denn gegen einen Platzhaltertermin laeuft keine Frist. */
.status-pill.status-unklar { background: var(--surface-2); color: var(--text-muted); border-color: var(--border); }
/* Zähler-Pille in Tab-/View-Switch-Buttons (ersetzt badge bg-light, dark-tauglich) */
.count-pill { display: inline-flex; align-items: center; min-width: 1.25em; justify-content: center;
  padding: 1px 7px; margin-left: 5px; border-radius: var(--radius-pill);
  background: var(--surface-2); color: var(--text-muted); font-size: .72rem; font-weight: 600; }
.view-switch .btn.active .count-pill, .btn.active .count-pill { background: rgba(255,255,255,.24); color: #fff; }
/* Solide Status-Helfer (für Badges/Akzente, z. B. Kalenderbalken, Late-Badge) */
.status-rot   { background: var(--status-rot);   color: #fff; }
.status-gelb  { background: var(--status-gelb);  color: #fff; }
.status-blau  { background: var(--status-blau);  color: #fff; }
.status-lila  { background: var(--status-lila);  color: #fff; }
.status-gruen { background: var(--status-gruen); color: #fff; }
.status-neutral { background: var(--border); color: var(--text-muted); }
.status-border-rot   { border-left: 4px solid var(--status-rot) !important; }
.status-border-gelb  { border-left: 4px solid var(--status-gelb) !important; }
.status-border-blau  { border-left: 4px solid var(--status-blau) !important; }
.status-border-lila  { border-left: 4px solid var(--status-lila) !important; }
.status-border-gruen { border-left: 4px solid var(--status-gruen) !important; }
.status-border-neutral { border-left: 4px solid var(--border) !important; }

/* --- KPI-Metrik-Karten ------------------------------------------------------ */
.kpi-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.3rem 1.45rem; box-shadow: none; transition: border-color .12s, box-shadow .12s; }
.kpi-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.kpi-card .kpi-head { display: flex; align-items: center; justify-content: space-between; }
.kpi-card .kpi-label, .kpi-card .kpi-label { font-size: .8rem; color: var(--text-muted); }
.kpi-card .kpi-icon { width: 34px; height: 34px; border-radius: 9px; background: var(--brand-soft); color: var(--brand-hover); display: flex; align-items: center; justify-content: center; font-size: 1.05rem; }
.kpi-card .kpi-value, .kpi-card .kpi-zahl { font-size: 2.1rem; font-weight: 700; line-height: 1.05; margin: 10px 0 2px; letter-spacing: -.025em; color: var(--text); }
.kpi-card .kpi-sub { font-size: .75rem; color: var(--text-muted); margin-top: 2px; }
.kpi-card.kpi-blau  { border-top: 3px solid var(--status-blau); }
.kpi-card.kpi-rot   { border-top: 3px solid var(--status-rot); }
.kpi-card.kpi-lila  { border-top: 3px solid var(--status-lila); }
.kpi-card.kpi-gruen { border-top: 3px solid var(--status-gruen); }

/* --- Dashboard-Begrüßung + Bereichs-/Tool-Kacheln --------------------------- */
.dash-hero { padding: 1.15rem 1.35rem; border-radius: var(--radius); background: linear-gradient(120deg, var(--brand-soft), var(--surface)); border: 1px solid var(--border); }
.module-tile { transition: transform .12s ease, border-color .12s ease; color: var(--text); }
.module-tile:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.module-tile .tile-icon { width: 44px; height: 44px; border-radius: 11px; background: var(--brand-soft); color: var(--brand-hover); display: flex; align-items: center; justify-content: center; font-size: 1.3rem; margin-bottom: .7rem; }
.module-tile .card-title { color: var(--text); }

/* --- Operatives Hof-Board (Startseite) -------------------------------------- */
.board-lanes { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.board-lane { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; }
.board-lane-head { display: flex; align-items: center; justify-content: space-between; font-size: .74rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint); margin-bottom: 9px; }
.board-lane-head .cnt { color: var(--text-muted); font-weight: 500; }
.board-chip { display: flex; align-items: center; gap: 8px; text-decoration: none; color: var(--text); background: var(--surface-2); border: 1px solid var(--border); border-left: 3px solid var(--border-strong); border-radius: 8px; padding: 6px 9px; margin-bottom: 6px; font-size: .81rem; transition: background .1s, transform .1s; }
.board-chip:hover { background: var(--brand-soft); color: var(--text); transform: translateY(-1px); }
.board-chip .t { font-weight: 600; flex: 0 0 auto; }
.board-chip .k { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Compound-Selektor (0,2,0) gewinnt gegen die generischen Badge-Regeln .status-X,
   damit Chips nie deren soliden Hintergrund/weiße Schrift erben (Dark-Mode-sicher). */
.board-chip.status-rot,
.board-chip.status-gelb,
.board-chip.status-blau,
.board-chip.status-lila,
.board-chip.status-gruen,
.board-chip.status-neutral { background: var(--surface-2); color: var(--text); }
.board-chip.status-rot   { border-left-color: var(--status-rot); }
.board-chip.status-gelb  { border-left-color: var(--status-gelb); }
.board-chip.status-blau  { border-left-color: var(--status-blau); }
.board-chip.status-lila  { border-left-color: var(--status-lila); }
.board-chip.status-gruen { border-left-color: var(--status-gruen); }
.board-chip.status-neutral { border-left-color: var(--border); }
.board-chip.status-rot:hover,
.board-chip.status-gelb:hover,
.board-chip.status-blau:hover,
.board-chip.status-lila:hover,
.board-chip.status-gruen:hover,
.board-chip.status-neutral:hover { background: var(--brand-soft); }
.board-empty { font-size: .78rem; color: var(--text-muted); padding: 8px 2px; text-align: center; opacity: .8; }
.att-row { display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; border-top: 1px solid var(--border); }
.att-row:first-child { border-top: none; padding-top: 2px; }
.att-row .att-ico { font-size: 1.05rem; margin-top: 1px; flex: 0 0 auto; }
.att-row .att-main { min-width: 0; }
.att-row .att-title { font-size: .85rem; font-weight: 600; }
.att-row .att-sub { font-size: .77rem; color: var(--text-muted); }

/* --- Auth-Seiten ------------------------------------------------------------ */
.auth-card { background: var(--surface); border-radius: var(--radius); box-shadow: 0 1px 3px rgba(16, 24, 40, .08), 0 12px 32px -12px rgba(16, 24, 40, .14); border: 1px solid var(--border); }
.auth-logo { width: 64px; height: 64px; border-radius: 16px; background: var(--brand); color: #fff; display: flex; align-items: center; justify-content: center; margin: 0 auto 1.1rem; box-shadow: 0 4px 14px -4px rgba(47,107,65,.4); }
.auth-logo .wilo-logo { width: 38px; height: 38px; }

/* --- Verlauf / Timeline ----------------------------------------------------- */
.history-list { max-height: 420px; overflow-y: auto; }
.history-list .history-entry { position: relative; padding-left: 18px; }
.history-list .history-entry::before { content: ""; position: absolute; left: 2px; top: 7px; width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); }

/* --- Zeitstempel-Panel ------------------------------------------------------ */
.ts-row { border-color: var(--border) !important; }
.ts-value-set { color: var(--status-gruen); font-weight: 600; }
.ts-row input[name="grund"] { background: var(--status-gelb-soft); border-color: color-mix(in srgb, var(--status-gelb) 35%, var(--border)); }

/* Handgeraet: das Feld zum Nachtragen steht unter dem Istzeit-Knopf und nicht
   daneben. Die Seite ist auf 560 Pixel begrenzt (.mobile main), nebeneinander
   passen Beschriftung, Datumsfeld, "Uebernehmen" und "Istzeit" nicht und
   brechen versetzt um (Micha, 22.09.2026).
   Rechtsbuendig und schmal, damit es unter dem gruenen Knopf sitzt. */
#zeitstempel-panel .ts-manuell { max-width: 19rem; margin-left: auto; }

/* --- Kundenansicht: neutrale Status-Pills ----------------------------------- */
.kstatus { display: inline-block; padding: 2px 11px; border-radius: var(--radius-pill); font-size: .78rem; font-weight: 500; border: 1px solid transparent; }
.kstatus-geplant { background: var(--surface-2); color: var(--text-muted); border-color: var(--border); }
.kstatus-aktiv  { background: var(--status-blau-soft); color: var(--status-blau-ink); }
.kstatus-fertig { background: var(--status-gruen-soft); color: var(--status-gruen-ink); }

/* --- Mobile (/m/) ----------------------------------------------------------- */
.mobile main { max-width: 560px; margin: 0 auto; }
.mobile .btn-lg { min-width: 116px; min-height: 52px; font-size: 1.05rem; }
.mobile-card { box-shadow: none; }
.mobile-card .card-body { color: var(--text); }
.mobile-card:active { background: var(--surface-2); }
.mobile-daynav .btn { min-width: 56px; min-height: 48px; font-size: 1.15rem; }

/* Wochenuebersicht am Handgeraet (22.09.2026). Sieben Bloecke untereinander
   statt des Rasters vom Rechner: das haette in der Woche vom 22.09. rund
   2.300 Pixel gebraucht, also sechs Bildschirmbreiten auf einem Telefon.
   Jede Zeile mindestens 44 Pixel hoch, damit sie sich mit Handschuh treffen
   laesst. */
.mobile-wochentag {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); margin-bottom: 10px; overflow: hidden;
}
.mobile-wochentag.ist-heute { border-color: var(--brand); }
.mobile-wochentag-kopf {
  display: flex; align-items: center; gap: 6px; padding: 9px 12px;
  background: var(--surface-2); color: var(--text); text-decoration: none;
}
.mobile-wochentag-kopf:hover, .mobile-wochentag-kopf:active { color: var(--text); background: var(--border); }
.mobile-wochenzeile {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  min-height: 44px; color: var(--text); text-decoration: none;
  border-top: 1px solid var(--border); border-left: 4px solid transparent;
}
.mobile-wochenzeile:active { background: var(--surface-2); }
/* Kuerzel und Referenz teilen sich den Platz zwischen Uhrzeit und Spalte.
   Die Referenz schrumpft zuerst: sie ist lang (etwa 3KIWCSUS_22372649743) und
   laesst sich abgeschnitten noch wiedererkennen, ein halbes Kuerzel nicht.

   Genau das stand hier auch schon vorher, nur hielt es die Regel nicht ein:
   `min-width: 0` erlaubte dem Namen, bis auf nichts zu schrumpfen. Auf 390px
   stand am 06.10.2026 bei zwei von sechs Zeilen nur noch „B..." und „H...".
   Ursache ist nicht die Laenge der Referenz, sondern dass `anzeigename_kurz`
   bei Klienten OHNE Kuerzel der volle Firmenname ist: „ONC" passt, „Blonde
   No. 8" und „Heldenwerk GmbH" nicht.

   Vier Zeichen bleiben jetzt mindestens stehen, hoechstens die halbe Zeile. */
.mobile-wochenzeile .wz-name {
  flex: 0 1 auto; min-width: 4rem; max-width: 50%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mobile-wochenzeile .wz-ref {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text-muted); font-size: .86rem;
}
/* Die Spalte ganz rechts. Ohne nowrap wird aus „WA 1" ein „WA" ueber einer
   „1", und die Zeile ist ploetzlich hoeher als ihre Nachbarn. */
.mobile-wochenzeile .ms-auto { flex: 0 0 auto; white-space: nowrap; }
/* Der Tagesblock klappt auf und zu. Den eigenen Pfeil statt des Dreiecks vom
   Browser, weil `summary` mit `display: flex` das Dreieck je nach Browser
   verschluckt und der Kopf dann wie unbedienbarer Text aussieht. */
.mobile-wochentag > summary { list-style: none; cursor: pointer; }
.mobile-wochentag > summary::-webkit-details-marker { display: none; }
.mobile-wochentag > summary::marker { content: ""; }
.wt-pfeil { display: inline-block; opacity: .55; transition: transform .12s ease; }
.mobile-wochentag[open] > summary .wt-pfeil { transform: rotate(90deg); }
.mobile-wochentag-leer .mobile-wochentag-kopf { cursor: default; }
.mobile-wochentag-fuss {
  display: flex; align-items: center; justify-content: flex-end; gap: 5px;
  padding: 10px 12px; min-height: 44px; font-size: .88rem;
  border-top: 1px solid var(--border); text-decoration: none; color: var(--brand-hover);
}
.mobile-wochentag-fuss:active { background: var(--surface-2); }
/* Die Ueberschrift der Detailseite traegt die Referenz, und die ist im Betrieb
   lang: „ONEU0923787 Ref HW202602A6 + HW202602A9 + HW202602A20". Sie darf
   deshalb mitten im Wort umbrechen, sonst schiebt sie die Seite seitwaerts. */
.mobil-titel { overflow-wrap: anywhere; line-height: 1.3; }

.mobile .navbar.bg-dark { background: var(--brand) !important; }

/* Die Leiste am Handgeraet (Micha, 05.10.2026: „lass die Handy-Ansicht noch
   fixen"). Vorher vier Textknoepfe nebeneinander, die auf 390px umbrachen.
   Jetzt dieselbe Regel wie in der Seitenleiste: der Name ist der Verweis,
   Abmelden ist ein Zeichen.

   nowrap ist Absicht. Umbrechen hiesse: der Markenblock allein in Zeile eins,
   alles andere darunter, und die halbe Leiste leer. Stattdessen weicht der
   Inhalt: erst der Schriftzug der Marke, dann der Name. */
.mobil-leiste { flex-wrap: nowrap; gap: 8px; }
.mobil-leiste .navbar-brand { min-width: 0; margin-right: 0; }
.mobil-konto { display: flex; align-items: center; gap: 8px; min-width: 0; }
.mobil-konto .btn { white-space: nowrap; }

.mobil-name {
  display: inline-flex; align-items: center; min-height: 40px;
  padding: 0 8px; border-radius: 7px;
  color: #fff; text-decoration: none; font-weight: 600; font-size: .9rem;
  max-width: 7rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mobil-name:hover, .mobil-name:active { color: #fff; background: rgba(255, 255, 255, .16); }

/* Vierzig Pixel im Quadrat, auch auf einem Geraet, das mit Handschuh bedient
   wird. Dieselbe Grenze wie unter `@media (pointer: coarse)` weiter oben. */
.mobil-zeichen {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: none; border-radius: 7px;
  background: transparent; color: #fff; cursor: pointer; line-height: 1;
}
.mobil-zeichen:hover, .mobil-zeichen:active { background: rgba(255, 255, 255, .16); }

/* Auf dem Telefon weicht der Schriftzug, das Logo bleibt. Getroffen wird
   ohnehin das Logo, und „WiLo App" steht im Seitentitel. */
@media (max-width: 430px) {
  .mobil-leiste .marke-text { display: none; }
  .mobil-name { max-width: 5rem; }
}

/* --- Modal ------------------------------------------------------------------ */
.modal-overlay { position: fixed; inset: 0; z-index: 1050; background: rgba(16, 24, 40, .5); display: flex; align-items: flex-start; justify-content: center; padding: 5vh 16px; overflow-y: auto; }
.modal-box { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); width: 100%; max-width: 720px; padding: 1.25rem 1.4rem 1.4rem; }
.modal-head { display: flex; align-items: center; margin-bottom: .9rem; }
.modal-x { margin-left: auto; border: none; background: transparent; font-size: 1.2rem; color: var(--text-muted); cursor: pointer; line-height: 1; }
.modal-x:hover { color: var(--text); }
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 1.1rem; }
.confirm-msg { margin: .3rem 0 0; color: var(--text); line-height: 1.5; }

/* --- In-App-Toasts ---------------------------------------------------------- */
.wilo-toasts { position: fixed; right: 18px; bottom: 18px; z-index: 1080; display: flex; flex-direction: column; gap: 8px; max-width: min(360px, 90vw); }
.wilo-toast { padding: .7rem .9rem; border-radius: var(--radius-sm); box-shadow: var(--shadow); font-size: .9rem; line-height: 1.4; border: 1px solid transparent; }
.wilo-toast-ok { background: var(--status-gruen-soft); color: var(--status-gruen-ink); border-color: color-mix(in srgb, var(--status-gruen) 30%, transparent); }
.wilo-toast-error { background: var(--status-rot-soft); color: var(--status-rot-ink); border-color: color-mix(in srgb, var(--status-rot) 30%, transparent); }

/* --- PDF-Viewer ------------------------------------------------------------- */
.pdf-container { background: #3d4147; padding: 10px; border-radius: var(--radius); overflow: auto; }
.pdf-page { display: block; margin: 0 auto 10px; max-width: 100%; background: #fff; border-radius: 3px; box-shadow: 0 2px 8px rgba(0, 0, 0, .35); }

/* Eine Seite: Leinwand und Textebene genau uebereinander (09.10.2026).
   Die Leinwand traegt das Bild, die Textebene den unsichtbaren, markierbaren
   Text. Beide muessen auf denselben Pixel passen, sonst markiert man neben
   dem Wort, das man sieht. */
.pdf-seite {
  position: relative; margin: 0 auto 10px; background: #fff;
  border-radius: 3px; box-shadow: 0 2px 8px rgba(0, 0, 0, .35);
}
.pdf-seite canvas { display: block; border-radius: 3px; }
.pdf-kopf { position: sticky; top: 0; z-index: 2; background: var(--bg); padding: 6px 0; }

/* Textebene von pdf.js 4.10. Die Regeln stammen aus deren
   `text_layer_builder.css` und sind Pflicht, nicht Geschmack: ohne sie
   stehen die Woerter als sichtbarer, versetzter Text ueber dem Bild.
   Die Groesse jedes Wortes rechnet pdf.js gegen `--scale-factor`, das die
   Seite selbst setzt (siehe app.js). */
.textLayer {
  position: absolute; text-align: initial; inset: 0; overflow: clip;
  opacity: 1; line-height: 1; text-size-adjust: none; forced-color-adjust: none;
  transform-origin: 0 0; caret-color: CanvasText; z-index: 1;
}
.textLayer :is(span, br) {
  color: transparent; position: absolute; white-space: pre;
  cursor: text; transform-origin: 0% 0%;
}
.textLayer span.markedContent { top: 0; height: 0; }
.textLayer ::selection { background: rgba(60, 130, 255, .35); }
.textLayer br::selection { background: transparent; }
.textLayer .endOfContent {
  display: block; position: absolute; inset: 100% 0 0;
  z-index: -1; cursor: default; user-select: none;
}
.textLayer.selecting .endOfContent { top: 0; }

/* Das Vorschaufenster auf der Detailseite. Es nimmt fast den ganzen
   Bildschirm, weil eine Packliste in Briefmarkengroesse keine Vorschau ist. */
.doc-fenster { max-width: min(980px, 94vw); width: 94vw; }
.doc-fenster .modal-head { gap: 10px; align-items: center; }
.doc-fenster-knoepfe { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.doc-fenster-feld {
  background: #3d4147; border-radius: var(--radius); padding: 10px;
  max-height: 72vh; overflow: auto; color: #d7dade; font-size: .82rem;
}
.doc-fenster-bild { display: block; margin: 0 auto; border-radius: 3px; background: #fff; }

/* Ein Feld, das gerade nicht zaehlt. Siehe templates/slots/_automatik_zeit.html:
   der Haken „naechster freier Platz" schaltet die Uhrzeit ab, und das soll man
   sehen und nicht nur im Hilfetext lesen. */
.feld-aus { opacity: .5; }
.feld-aus input:disabled { background: var(--surface-2); }


/* --- Responsiv -------------------------------------------------------------- */
/* Grenze 1100px statt 820px: auf einem Tablet quer (1024) blieb die Seitenleiste
   stehen und nahm 248px weg. Uebrig waren 715px Inhalt, weniger als hochkant.
   Ueber der Grenze bleibt alles wie bisher. */
@media (max-width: 1100px) {
  .app-shell { flex-direction: column; }
  .sidebar { width: 100%; flex-basis: auto; height: auto; position: static; flex-direction: row; flex-wrap: wrap; align-items: center; }
  .sidebar-brand { border-right: 1px solid var(--border); }
  .sidebar-nav { display: flex; flex: 1 1 100%; order: 3; padding: 8px; gap: 4px; overflow-x: auto; }
  .sidebar-nav .nav-label { display: none; }
  .sidebar-nav a { margin-bottom: 0; white-space: nowrap; }
  .sidebar-nav a.active::before { display: none; }
  .sidebar-user { border-top: none; margin-left: auto; }
  /* In der Querleiste ist waagerecht kaum Platz. Der Name wird deshalb
     abgeschnitten statt umgebrochen, siehe .name weiter oben. Rolle und
     ausgeschriebener Verweis gab es hier bis zum 05.10.2026, die brachen
     mitten im Satz um; jetzt steht nur noch der Name da. */
  .sidebar-user .who { max-width: 52vw; }
  .app-main { padding: 18px 16px; }
}

/* Bis zum 05.10.2026 bekam der Benutzerblock hier eine eigene Zeile:
   Markenblock und Benutzerblock zusammen waren breiter als 390px, weil unter
   dem Namen noch die Rolle und der ausgeschriebene Verweis „Passwort und
   Anmeldung" standen. Beides ist weg, der Block ist nur noch Name und zwei
   Zeichen. Die eigene Zeile stand danach fast leer da, mit einer Handbreit
   Luft zwischen Namen und Glocke. Er steht jetzt wieder neben dem
   Markenblock, der Name weicht zuerst. */
@media (max-width: 600px) {
  .sidebar-user { padding-left: 8px; padding-right: 10px; }
  .sidebar-user .who { max-width: 30vw; }
}

/* Unter 430px weicht der Name und nur der Kreis bleibt stehen (Micha,
   19.10.2026). Dieselbe Grenze wie beim Schriftzug der Handgeraete-Leiste
   weiter oben: wer so schmal unterwegs ist, kennt seinen eigenen Namen.
   Der Kreis bleibt der Verweis auf die eigenen Anmeldedaten, deshalb steht
   er in base.html IM Verweis und nicht daneben. */
@media (max-width: 430px) {
  .sidebar-user .who { max-width: none; gap: 0; }
  .sidebar-user .who .name { display: none; }
}

@media (max-width: 700px) {
  /* Die Knopfgruppen ruecken unter den Titel und nehmen die volle Breite,
     statt sich rechts zu stapeln. */
  .seiten-kopf-aktionen { margin-left: 0; width: 100%; }
  /* Das Vorschaufenster und seine Knopfreihe gehoeren in DIESEN Block und
     nicht in einen eigenen weiter oben: `test_schmale_oberflaeche` sieht
     sich den ersten 700er-Block der Datei an, und ein zweiter davor hat ihn
     am 09.10.2026 umgeworfen. Eine Regel, eine Stelle. */
  .doc-fenster { width: 98vw; }
  .doc-fenster-knoepfe { width: 100%; }
  .seiten-kopf-aktionen .btn-group { flex: 1 1 auto; }
  .seiten-kopf-aktionen .btn-group .btn { flex: 1 1 auto; }
  .seiten-kopf-aktionen > .btn { flex: 1 1 100%; justify-content: center; }
  /* Ein Formular mit einem Knopf darin zaehlt genauso. Auf der Detailseite
     sind „Stornieren" und „Endgueltig loeschen" Formulare und keine Verweise;
     ohne diese Regel standen sie als einzige halb so breit daneben
     (06.10.2026). */
  .seiten-kopf-aktionen > form { flex: 1 1 100%; margin: 0; }
  .seiten-kopf-aktionen > form .btn { width: 100%; justify-content: center; }

  /* Die Filterkarte mischte die Feldbreiten: Container und Status standen
     nebeneinander, Klient und Typ ueber die volle Breite, je nachdem wie lang
     die laengste Auswahl gerade war. Auf 390px sieht das unfertig aus.
     Jetzt steht jedes Feld auf einer eigenen Zeile. */
  .cal-filter .card-body > div { flex: 1 1 100%; min-width: 0; }
}


/* --- Startseite des Portals --------------------------------------------------
   Liegt auf der Wurzel und steht ueber den Bereichen. Das Kachelraster
   (.launcher-*) stammt aus der frueheren Kachelansicht und wird hier
   weiterverwendet. */
.portal-kopf { margin-bottom: 26px; }

.meldung { display: flex; align-items: flex-start; gap: 12px; padding: 11px 2px; }
.meldung-trenner { border-bottom: 1px solid var(--border); }
.meldung-zahl {
  flex: 0 0 44px; text-align: center; font-weight: 700; font-size: 1.15rem;
  line-height: 1.5; border-radius: var(--radius-sm); padding: 2px 4px;
  background: var(--surface-2); color: var(--text-muted);
}
.meldung-text { min-width: 0; }
.meldung-titel { font-weight: 600; font-size: .92rem; }
.meldung-titel a { color: var(--text); text-decoration: none; }
.meldung-titel a:hover { color: var(--brand-hover); text-decoration: underline; }
.meldung-bereich {
  font-weight: 500; font-size: .7rem; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .05em; margin-left: 8px;
}
.meldung-satz { font-size: .81rem; color: var(--text-muted); line-height: 1.45; }
.meldung-dringend .meldung-zahl { background: var(--status-rot-soft); color: var(--status-rot-ink); }
.meldung-offen .meldung-zahl { background: var(--status-gelb-soft); color: var(--status-gelb-ink); }
.meldung-ruhig .meldung-zahl { background: var(--surface-2); color: var(--text-muted); }

.zustand { display: flex; align-items: baseline; gap: 10px; padding: 9px 2px; font-size: .86rem; }
.zustand-punkt {
  flex: 0 0 9px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--text-faint); align-self: center;
}
.zustand-gut .zustand-punkt { background: var(--status-gruen); }
.zustand-pruefen .zustand-punkt { background: var(--status-gelb); }
.zustand-schlecht .zustand-punkt { background: var(--status-rot); }
.zustand-name { flex: 0 0 190px; color: var(--text-muted); }
.zustand-wert { font-weight: 600; }
.zustand-hinweis { color: var(--text-faint); font-size: .78rem; min-width: 0; }

@media (max-width: 600px) {
  .zustand { flex-wrap: wrap; }
  .zustand-name { flex-basis: auto; }
  .zustand-hinweis { flex-basis: 100%; padding-left: 19px; }
}

/* --- Hinweise --------------------------------------------------------------
   Ersetzt das title-Attribut. Der Browser zeigt title erst nach etwa einer
   Sekunde Zeigen, auf Touch gar nicht, und gestalten laesst es sich nicht.
   Die Blase oeffnet beim Zeigen und beim Antippen, ohne JavaScript: ein
   Antippen setzt den Fokus auf den Knopf, :focus-within greift. */
.hinweis { position: relative; display: inline-flex; vertical-align: middle; }
.hinweis-knopf {
  border: 0; background: transparent; padding: 2px; margin: -2px;
  cursor: help; color: var(--text-faint); line-height: 0;
  display: inline-flex; border-radius: 50%;
}
.hinweis-knopf .ic { width: 16px; height: 16px; }
.hinweis-knopf:hover, .hinweis-knopf:focus-visible { color: var(--brand); }
.hinweis-blase {
  position: absolute; top: calc(100% + 8px); left: -8px; z-index: 1070;
  width: max-content; max-width: min(320px, 70vw);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow); padding: .55rem .7rem;
  font-size: .8rem; font-weight: 400; line-height: 1.45;
  text-align: left; text-transform: none; letter-spacing: normal; white-space: normal;
  opacity: 0; visibility: hidden; transition: opacity .12s ease;
}
/* Symbol am rechten Rand: sonst ragt die Blase aus der Karte. */
.hinweis-rechts .hinweis-blase { left: auto; right: -8px; }
.hinweis:hover .hinweis-blase, .hinweis:focus-within .hinweis-blase { opacity: 1; visibility: visible; }
@media (pointer: coarse) {
  .hinweis-knopf { padding: 12px; margin: -12px; }
}

/* --- Touch-Bedienung -------------------------------------------------------
   Greift nur, wenn der Zeiger grob ist (Finger). Maus bleibt unveraendert.
   Gemessen am 02.09.2026: Knoepfe 33px hoch, das Plus im Spaltenkopf 20x15,
   der Abmelde-Knopf 25x27. Empfohlen sind 40 bis 44px. */
@media (pointer: coarse) {
  .btn { min-height: 40px; display: inline-flex; align-items: center; justify-content: center; }
  .btn-close { min-width: 40px; min-height: 40px; }
  .logout-btn { min-width: 40px; min-height: 40px; }
  .sidebar-nav a { min-height: 40px; }
  .spaltenwahl-eintrag input { width: 18px; height: 18px; }
  .spaltenwahl-eintrag { min-height: 34px; }
}

/* Auf Touch bleibt der Hover-Zustand nach dem Antippen haengen. */
@media (hover: none) {
  .cal-slot:hover { transform: none; box-shadow: var(--shadow-sm); }
}

/* --- Dunkelmodus: Feinschliff für Bootstrap-Reste --------------------------- */
:root[data-theme="dark"] body { background: var(--bg); }
:root[data-theme="dark"] .table { --bs-table-bg: transparent; --bs-table-color: var(--text); }
:root[data-theme="dark"] .form-control, :root[data-theme="dark"] .form-select { background: var(--surface-2); color: var(--text); }
:root[data-theme="dark"] .form-control::placeholder { color: var(--text-faint); }
:root[data-theme="dark"] .module-tile .tile-icon, :root[data-theme="dark"] .kpi-card .kpi-icon { background: var(--brand-soft); }
:root[data-theme="dark"] .btn-close { filter: invert(1) grayscale(1) brightness(1.6); }


/* --- Spaltenwahl über dem Kalender -----------------------------------------
   Jeder blendet für sich aus, was er gerade nicht braucht. Absichtlich flach
   und unauffällig: Es ist eine Ansichtseinstellung, kein Filter mit Wirkung
   auf die Daten. */
.spaltenwahl {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px;
  margin-bottom: 10px; font-size: .82rem; color: var(--text-muted);
}
.spaltenwahl-titel {
  font-weight: 600; color: var(--text-faint); text-transform: uppercase;
  letter-spacing: .05em; font-size: .72rem;
}
.spaltenwahl-eintrag { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; user-select: none; }
.spaltenwahl-eintrag input { margin: 0; cursor: pointer; }
.spaltenwahl-eintrag:has(input:not(:checked)) span { color: var(--text-faint); text-decoration: line-through; }


/* --- Benutzerverwaltung ------------------------------------------------- */
/* Kürzel und Name stehen nebeneinander in einer festen Zeile. Vorher war das
   Kürzel ein Inline-Element direkt vor dem Namen: Bei zwei Wörtern brach der
   Name um und die zweite Hälfte stand unter dem Kreis. */
.benutzer { display: flex; align-items: center; gap: 10px; min-width: 0; }
.benutzer-kuerzel {
  flex: 0 0 32px; width: 32px; height: 32px; border-radius: 50%;
  background: var(--brand); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 650; font-size: .74rem; letter-spacing: .03em;
}
.benutzer-name { white-space: nowrap; }

/* Knöpfe am Zeilenende: gleicher Abstand, gleiche Höhe. „Passwort neu setzen"
   brach vorher auf zwei Zeilen um und war dadurch höher als „Bearbeiten". */
.zeilen-aktionen { display: flex; align-items: center; justify-content: flex-end; gap: .4rem; }
.zeilen-aktionen form { margin: 0; }
.zeilen-aktionen .btn { white-space: nowrap; }

/* Letzter Zeitstempel-Schritt: seit der Hilfetext darunter weg ist, wäre die
   Trennlinie eine Linie ins Leere. Bootstrap setzt sie mit !important. */
#zeitstempel-panel .ts-row:last-child {
  border-bottom: 0 !important; margin-bottom: 0 !important; padding-bottom: 0 !important;
}


/* =====================================================================
   Nur auf breiten Bildschirmen zeigen

   Gebraucht fuer den Kalender-Verweis in der Handgeraete-Vorlage: am
   Lagerrechner sinnvoll, am Scanner nicht. Bewusst eine Breitenregel und
   keine Geraeteerkennung ueber den User-Agent. Die raet, und sie raet falsch,
   sobald jemand ein Tablet quer haelt oder ein neues Geraet dazukommt.

   900px, weil die Tagesansicht darunter zwar noch funktioniert, aber vier
   Spalten nebeneinander dort nichts mehr nuetzen.
   ===================================================================== */
.nur-breit { display: none; }
@media (min-width: 900px) {
  .nur-breit { display: inline-flex; }
}


/* =====================================================================
   Der Hof am Handgeraet (06.10.2026)

   Eigene Klassen und nicht die `hk-*` der Karte: die stehen in hofkarte.css,
   und base_mobile.html laedt nur app.css. Zwei Dateien fuer eine Seite zu
   laden, von der die Haelfte nie gebraucht wird, waere am Scanner im Funkloch
   verschenkt.

   Jede Zeile ist mindestens 56px hoch. Das ist keine Geschmacksfrage: die
   Zeilen werden mit Arbeitshandschuhen getroffen.
   ===================================================================== */
.hofm-ueber {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); font-weight: 600;
  margin: 18px 0 6px; display: flex; align-items: center; gap: 8px;
}
.hofm-zahl {
  background: var(--status-rot-soft); color: var(--status-rot-ink);
  border-radius: var(--radius-pill); padding: 1px 8px;
  font-size: .72rem; font-weight: 700; letter-spacing: 0;
}

/* Dieselbe Zahl wie das linke Abzeichen auf der Karte, dieselben Farben:
   grau heisst „dazugekommen", blau heisst „betrifft dich". Siehe
   static/css/hofkarte.css. */
.hofm-neu {
  display: inline-block; min-width: 1.25rem; text-align: center;
  background: var(--text); color: var(--surface);
  border-radius: var(--radius-pill); padding: 0 5px;
  font-size: .75rem; font-weight: 700;
}
.hofm-neu-mich { background: var(--status-blau); }

/* Die Stellplaetze am Handgeraet: ein Raster, keine Liste. Elf Zeilen waeren
   die halbe Seite, und eine Platznummer braucht keine Zeile. Jede Kachel
   bleibt 44 Pixel hoch, damit sie mit Handschuhen zu treffen ist. */
.hofm-plaetze {
  list-style: none; margin: 0 0 18px; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: 6px;
}
.hofm-plaetze a {
  display: flex; align-items: baseline; gap: 8px;
  min-height: 44px; padding: 8px 10px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); text-decoration: none; color: var(--text);
}
.hofm-plaetze a:active { background: var(--brand-soft); }
.hofm-plaetze .hofm-platz-nr { font-weight: 700; font-size: 1rem; }
.hofm-plaetze .hofm-platz-rest {
  font-size: .8rem; color: var(--text-muted); min-width: 0; overflow-wrap: anywhere;
}
/* Belegt ist grau, genau wie auf der Karte. */
.hofm-plaetze a.hofm-platz-voll { background: var(--surface-2); border-color: var(--border-strong); }
.hofm-plaetze a.hofm-platz-voll .hofm-platz-rest { color: var(--text); }
.hofm-pille.hofm-platz-voll,
.hofm-platz-voll.hofm-pille { background: var(--surface-2); color: var(--text); }
.hofm-zahl-still { background: var(--surface-2); color: var(--text-muted); }

.hofm-liste { list-style: none; margin: 0; padding: 0; }
.hofm-liste li { margin-bottom: 6px; }
.hofm-liste a {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 8px;
  min-height: 56px; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); text-decoration: none; color: var(--text);
}
.hofm-liste a:active { background: var(--brand-soft); }
.hofm-name {
  font-weight: 600; font-size: .95rem; min-width: 0;
  overflow-wrap: anywhere;
}
/* Die Restzeile laeuft ueber die ganze Breite, unter Name und Pille. */
.hofm-rest {
  grid-column: 1 / -1;
  font-size: .8rem; color: var(--text-muted); overflow-wrap: anywhere;
}

.hofm-pille {
  justify-self: end; align-self: start; white-space: nowrap;
  border-radius: var(--radius-pill); padding: 2px 9px;
  font-size: .72rem; font-weight: 650;
}
/* „nichts offen" bleibt grau. Rot gehoert allein der offenen Meldung, sonst
   gewoehnt sich das Auge daran und uebersieht sie. Dieselbe Regel wie auf der
   Karte. */
.hofm-zu-ruhe { background: var(--surface-2); color: var(--text-faint); border: 1px solid var(--border); }
.hofm-zu-offen { background: var(--status-rot-soft); color: var(--status-rot-ink); }
.hofm-zu-arbeit { background: var(--status-gelb-soft); color: var(--status-gelb-ink); }

.hofm-leer {
  font-size: .86rem; color: var(--text-muted);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px; margin: 0;
}

/* Der Zurueck-Knopf auf der Objektseite ist ein echter Verweis und kein
   Skriptknopf: ohne JavaScript fuehrt `wiloBack()` nirgendwohin. Als <a>
   braucht er die Unterstreichung nicht. */
.back-bar a.btn-back { text-decoration: none; }

.hofm-kopf { margin-bottom: 10px; }

.hofm-werte { margin: 0 0 14px; font-size: .86rem; }
.hofm-werte dt {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); font-weight: 600; margin-top: 8px;
}
.hofm-werte dd { margin: 0; overflow-wrap: anywhere; }

/* Ein Formular je Zeile, volle Breite. Nebeneinander waere auf 390px ein
   Eingabefeld von zwei Zentimetern. */
.hofm-knoepfe { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.hofm-knoepfe .hk-form { display: flex; gap: 6px; margin: 0; }
/* Beide Zeilen gleich breit. `hofkarte.css` deckelt `.hk-menge` auf 78px,
   damit das Zahlenfeld in der schmalen Tafel neben der Karte nicht die halbe
   Zeile frisst. Im Popup am Handgeraet steht es allein in seiner Zeile, und
   dann stehen „Melden" und „Bestand" verschieden weit rechts (gesehen am
   06.10.2026 auf der Live-Seite). */
.hofm-knoepfe .hk-form { flex-wrap: wrap; }
.hofm-knoepfe .hk-form input { flex: 1 1 auto; min-width: 0; }
.hofm-knoepfe .hk-form .hk-menge { max-width: none; }
/* Die Empfaengerwahl allein in ihrer Zeile und 44 Pixel hoch, damit sie mit
   Handschuhen zu treffen ist. */
.hofm-knoepfe .hk-form .hk-kreis { flex: 1 1 100%; min-height: 44px; }
.hofm-knoepfe .hk-form .btn { flex: 0 0 auto; min-height: 44px; min-width: 6.5rem; }

.hofm-protokoll { list-style: none; margin: 0; padding: 0; }
.hofm-protokoll li {
  padding: 8px 0; border-bottom: 1px solid var(--border); font-size: .86rem;
}
.hofm-protokoll li:last-child { border-bottom: 0; }
.hofm-protokoll span { font-size: .78rem; color: var(--text-muted); }


/* =====================================================================
   Die Hofkarte am Handgeraet (06.10.2026)

   Das Zeichnen selbst steht in hofkarte.css, die diese eine Seite zusaetzlich
   laedt. Hier steht nur der Rahmen darum: Leiste, Kartenfeld und Popup.

   `touch-action` steht ausdruecklich NICHT hier, sondern wird in app.js
   gesetzt. Im Stylesheet wuerde es auch ohne JavaScript gelten, und dann
   liesse sich die Seite nicht mehr scrollen, sobald der Finger auf der Karte
   aufsetzt.
   ===================================================================== */
.hofm-leiste { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.hofm-zoom { display: inline-flex; gap: 6px; margin-left: auto; }
.hofm-zoom .btn { min-width: 44px; min-height: 36px; }

.hk-karte-feld {
  overflow: hidden; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: grab;
}
.hk-karte-feld:active { cursor: grabbing; }

.hofm-fussnote { font-size: .78rem; color: var(--text-faint); margin: 8px 0 0; }

/* Das Popup. Bis auf den Rand dieselbe Darstellung wie die Objektseite, der
   Inhalt ist auch dieselbe Vorlage. */
.hof-popup {
  width: min(92vw, 420px); max-height: 86vh; overflow: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
  padding: 14px 16px 18px; box-shadow: var(--shadow);
}
.hof-popup::backdrop { background: rgba(16, 24, 40, .45); }
.hof-popup-zu { display: flex; justify-content: flex-end; margin: -4px -6px 0 0; }
.hof-popup-zu .mobil-zeichen { color: var(--text-muted); }


/* =====================================================================
   Postfach (07.10.2026)

   Die Zeilen sind dieselben wie bisher (`.att-row`), dazu kommt rechts eine
   Aktion. Auf dem Telefon rutscht sie unter den Text: ein Knopf, der sich
   neben einem umbrechenden Titel auf zwei Zentimeter zusammenzieht, ist
   keiner.
   ===================================================================== */
.pf-zeile .pf-aktion { margin-left: auto; margin-bottom: 0; flex: 0 0 auto; }
.pf-verweis { text-decoration: none; color: var(--text); }
.pf-verweis:hover { color: var(--brand-hover); }

/* Auswahlkaesten je Zeile, nicht nebeneinander: „Alle internen" und „Ganze
   Rollen" nebeneinander liest sich wie eine Aufzaehlung statt wie eine Wahl. */
.pf-kreis label { display: block; font-size: .88rem; padding: 2px 0; }
.pf-kreis input { margin-right: 7px; }

@media (max-width: 700px) {
  .pf-zeile { flex-wrap: wrap; }
  .pf-zeile .pf-aktion { flex: 1 1 100%; margin-left: 0; margin-top: 6px; }
  .pf-zeile .pf-aktion .btn { width: 100%; }
}

/* =====================================================================
   Postfach, zweiter Durchgang (08.10.2026)

   Drei Dinge: ungelesene Zeilen sind als solche zu erkennen, eine Nachricht
   hat eine eigene Seite mit Bildern, und die Schreibmaske zeigt nur noch den
   Teil der Empfaengerwahl, der gerade gilt.
   ===================================================================== */

/* Ungelesen. Ein Strich links und ein fetterer Titel, keine Farbflaeche:
   im Posteingang ist fast alles ungelesen, eine Flaeche waere dann die
   Normalform und saehe aus wie ein Fehler. */
.pf-neu { border-left: 3px solid var(--brand); padding-left: 9px; margin-left: -12px; }
.pf-neu .att-title { font-weight: 700; }
.pf-vorschau { display: inline-block; max-width: 100%; }

/* --- Eine Nachricht ganz --- */
.pf-brief .pf-meta { font-size: .78rem; color: var(--text-muted); margin-bottom: 12px; }
.pf-brief .pf-text { font-size: .92rem; line-height: 1.55; white-space: normal; }
.pf-brief .pf-ziel { margin-top: 14px; }

.pf-anhaenge { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 16px; }
.pf-bild { margin: 0; max-width: 320px; }
.pf-bild img {
  display: block; max-width: 100%; height: auto; max-height: 340px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
}
.pf-bild figcaption {
  font-size: .74rem; color: var(--text-muted); margin-top: 4px;
  display: flex; gap: 8px; justify-content: space-between;
}
.pf-datei {
  display: flex; align-items: center; gap: 8px; text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 9px 12px; color: var(--text); background: var(--surface);
}
.pf-datei:hover { border-color: var(--brand); color: var(--brand-hover); }
.pf-datei-name { font-size: .85rem; font-weight: 600; }
.pf-datei-groesse { font-size: .74rem; color: var(--text-muted); }

/* --- Die Schreibmaske --- */
.pf-wahl { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.pf-kachel {
  display: flex; align-items: flex-start; gap: 9px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 10px 14px; flex: 1 1 200px; background: var(--surface);
}
/* Der gewaehlte Kasten ist am Rahmen zu erkennen und nicht nur am Punkt im
   Kreis. Auf dem Tablet sieht man den Punkt im Stehen schlicht nicht. */
.pf-kachel:has(input:checked),
.pf-kachel.pf-kachel-an { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.pf-kachel input { margin-top: 3px; flex: 0 0 auto; }
.pf-kachel-text { display: flex; flex-direction: column; min-width: 0; }
.pf-kachel-titel { font-size: .88rem; font-weight: 600; }
.pf-kachel-sub { font-size: .74rem; color: var(--text-muted); }

.pf-block {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 14px; background: var(--surface-2, var(--surface));
}
.pf-block[hidden] { display: none; }
.pf-block-kopf { font-size: .8rem; font-weight: 600; margin-bottom: 8px; display: flex; align-items: center; }
.pf-block-aktionen { margin-left: auto; }
.pf-block-aktionen .btn { padding: 0 6px; font-size: .78rem; }

.pf-haken { display: flex; flex-direction: column; gap: 2px; }
.pf-haken-zeile { display: flex; align-items: center; gap: 8px; font-size: .86rem; padding: 3px 0; cursor: pointer; }
.pf-haken-zeile[hidden] { display: none; }
/* Scrollt ab etwa zwoelf Namen. Eine Liste, die die halbe Seite einnimmt,
   schiebt den Verschicken-Knopf aus dem Bild. */
.pf-personen { max-height: 260px; overflow-y: auto; }

.pf-dateiliste { margin-top: 6px; }
.pf-dateizeile { font-size: .78rem; color: var(--text-muted); }

@media (max-width: 700px) {
  .pf-kachel { flex: 1 1 100%; }
  .pf-bild { max-width: 100%; }
}

/* =====================================================================
   Baustellen (08.10.2026)

   Ein Bereich, der angekuendigt ist und noch keinen Inhalt hat. Gedaempft
   und nicht bunt: eine Baustelle ist kein Alarm, sie soll nur nicht mit
   einem fertigen Bereich verwechselt werden.
   ===================================================================== */
.sidebar-nav a.nav-aufbau { color: var(--text-muted); }
.nav-aufbau-zeichen { margin-left: auto; display: inline-flex; opacity: .75; }
.nav-aufbau-zeichen .ic { width: 14px; height: 14px; }

.launcher-card.launcher-aufbau { border-style: dashed; }
/* Der Ruf an der Kachel, seit dem 23.10.2026: ein Bereich meldet etwas
   Dringendes. Rand und Zeichen, keine volle Flaeche: die Kachel soll
   auffallen und nicht alarmieren, und mehrere rote Kacheln nebeneinander
   waeren wieder eine Wand. */
.launcher-card.launcher-ruf { border-color: var(--status-rot); }
.launcher-ruf-zeichen { display: inline-flex; vertical-align: -2px; color: var(--status-rot); }
.launcher-ruf-zeichen .ic { width: 15px; height: 15px; }
.launcher-marke {
  font-size: .68rem; font-weight: 500; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: 1px 7px; vertical-align: 1px; white-space: nowrap;
}
/* Das Zeichen in der Marke, seit dem 23.10.2026: dasselbe Sinnbild wie in
   der Navigation, nur kleiner. Michas Vorgabe war ein Zeichen und nicht
   nur ein Wort. */
.launcher-marke .ic { width: 11px; height: 11px; vertical-align: -1px; }

.baustelle { display: flex; gap: 14px; align-items: flex-start; padding: 6px 0; }
.baustelle-ico { flex: 0 0 auto; color: var(--text-muted); }
.baustelle-ico .ic { width: 30px; height: 30px; }
.baustelle-satz { font-size: .95rem; font-weight: 600; }
.baustelle-text { font-size: .85rem; color: var(--text-muted); margin-top: 2px; }
.baustelle-liste { font-size: .85rem; margin: 8px 0 0; padding-left: 20px; }
.baustelle-liste li { margin-bottom: 3px; }

/* --- Auswertungen, Startseite (07.10.2026) ------------------------------ */
.aw-kopf { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.aw-kopf .btn .ic { width: 15px; height: 15px; vertical-align: -2px; }
.aw-schnell { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.aw-chip { font-size: .8rem; padding: 4px 11px; border-radius: var(--radius-pill); border: 1px solid var(--border); color: var(--text-muted); background: var(--surface); text-decoration: none; }
.aw-chip:hover { border-color: var(--border-strong); color: var(--text); }
.aw-chip.aktiv { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-strong); font-weight: 600; }
.aw-filter { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; margin-bottom: 16px; display: flex; flex-direction: column; gap: 10px; }
.aw-filter-zeile { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; }
.aw-filter-zeile + .aw-filter-zeile { border-top: 1px solid var(--border); padding-top: 10px; }
.aw-feld { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.aw-feld[hidden] { display: none; }
.aw-feld .form-select, .aw-feld .form-control { width: auto; min-width: 7rem; }
.aw-label { font-size: .72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.aw-blaettern .btn { min-width: 2.2rem; font-size: 1rem; line-height: 1; }
.aw-kacheln { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
.aw-kachel { padding: 1rem 1.1rem; }
.aw-kachel .kpi-value { font-size: 1.8rem; }
.aw-kachel .kpi-label { display: inline-flex; align-items: center; gap: 4px; }
.aw-vergleich { font-size: .75rem; margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--border); }
.aw-vergleich.aw-besser { color: var(--status-gruen-ink); }
.aw-vergleich.aw-schlechter { color: var(--status-rot-ink); }
.aw-vergleich.aw-gleich, .aw-vergleich.aw-neutral { color: var(--text-muted); }
.aw-tabelle th, .aw-tabelle td { white-space: nowrap; vertical-align: middle; }
.aw-tabelle tbody th { font-weight: 600; }
.aw-tabelle tr.aw-leer td, .aw-tabelle tr.aw-leer th, .aw-tabelle tr.aw-geplant td, .aw-tabelle tr.aw-geplant th { color: var(--text-muted); }
.aw-teil { font-size: .68rem; font-weight: 500; color: var(--text-muted); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 0 6px; margin-left: 4px; }
.aw-balken-kopf { min-width: 12rem; }
.aw-balken { display: inline-block; width: 9rem; height: 8px; border-radius: var(--radius-pill); background: var(--surface-2); border: 1px solid var(--border); overflow: hidden; vertical-align: middle; }
.aw-balken-fuellung { display: block; height: 100%; background: var(--brand); }
.aw-balken-zahl { display: inline-block; min-width: 3rem; text-align: right; margin-left: 6px; font-variant-numeric: tabular-nums; }
.aw-tabelle td.text-end { font-variant-numeric: tabular-nums; }
.aw-bezug { font-size: .8rem; color: var(--text-muted); display: flex; flex-direction: column; gap: 4px; }
.aw-bezug strong { color: var(--text); font-weight: 600; }
.aw-details { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.aw-detail { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; background: var(--surface); text-decoration: none; color: var(--text); box-shadow: inset -1px -1px 0 var(--border); }
.aw-detail:hover { background: var(--brand-softer); }
.aw-detail-titel { font-weight: 600; font-size: .9rem; }
.aw-detail-text { font-size: .78rem; color: var(--text-muted); }
@media (max-width: 1200px) { .aw-kacheln { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px) {
  .aw-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .aw-feld { flex: 1 1 45%; }
  .aw-feld-modus, .aw-blaettern { flex: 1 1 100%; }
  .aw-feld-modus .btn-group, .aw-blaettern .btn-group { width: 100%; }
  .aw-feld .form-select, .aw-feld .form-control { width: 100%; }
}

/* --- Auswertungen, Reiter und Liniendiagramme (07.10.2026) -------------- */
/* Farben: acht Plaetze in fester Reihenfolge, am 07.10.2026 mit dem
   Palettenpruefer gegen #ffffff und #151c18 geprueft (reports/diagramme.py). */
.aw-reiter { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 12px; }
.aw-reiter-tab { display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px; margin-bottom: -1px; border-bottom: 2px solid transparent; color: var(--text-muted); text-decoration: none; font-weight: 500; font-size: .9rem; }
.aw-reiter-tab .ic { width: 16px; height: 16px; }
.aw-reiter-tab:hover { color: var(--text); }
.aw-reiter-tab.aktiv { color: var(--brand-strong); border-bottom-color: var(--brand); font-weight: 600; }
.aw-diagramme { --aw-serie-1: #2a78d6; --aw-serie-2: #eb6834; --aw-serie-3: #1baf7a; --aw-serie-4: #eda100;
  --aw-serie-5: #e87ba4; --aw-serie-6: #008300; --aw-serie-7: #4a3aa7; --aw-serie-8: #e34948;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 16px; }
:root[data-theme="dark"] .aw-diagramme { --aw-serie-1: #3987e5; --aw-serie-2: #d95926; --aw-serie-3: #199e70; --aw-serie-4: #c98500;
  --aw-serie-5: #d55181; --aw-serie-6: #008300; --aw-serie-7: #9085e9; --aw-serie-8: #e66767; }
.aw-s1 { --c: var(--aw-serie-1); } .aw-s2 { --c: var(--aw-serie-2); } .aw-s3 { --c: var(--aw-serie-3); } .aw-s4 { --c: var(--aw-serie-4); }
.aw-s5 { --c: var(--aw-serie-5); } .aw-s6 { --c: var(--aw-serie-6); } .aw-s7 { --c: var(--aw-serie-7); } .aw-s8 { --c: var(--aw-serie-8); }
.aw-diagramm { margin: 0; padding: 12px 14px 8px; }
.aw-diagramm-kopf { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 14px; margin-bottom: 6px; }
.aw-diagramm-titel { font-weight: 600; font-size: .92rem; color: var(--text); }
.aw-legende { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: .78rem; color: var(--text-muted); }
.aw-legende-eintrag { display: inline-flex; align-items: center; gap: 6px; }
.aw-legende-strich { display: inline-block; width: 14px; height: 3px; border-radius: 2px; background: var(--c); }
.aw-diagramm-flaeche { position: relative; }
.aw-diagramm svg { display: block; width: 100%; height: auto; overflow: visible; }
.aw-gitter { stroke: var(--border); stroke-width: 1; }
.aw-achse { fill: var(--text-muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.aw-reihe path { fill: none; stroke: var(--c); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.aw-reihe circle { fill: var(--c); stroke: var(--surface); stroke-width: 2; }
.aw-reihe circle.aw-offen { fill: var(--surface); stroke: var(--c); }
.aw-endwert { fill: var(--text); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
.aw-fadenkreuz { stroke: var(--border-strong); stroke-width: 1; }
.aw-treffer { fill: transparent; cursor: crosshair; }
.aw-tooltip { position: absolute; top: 8px; z-index: 5; min-width: 150px; padding: 8px 10px; background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-sm); box-shadow: var(--shadow-sm); font-size: .78rem; pointer-events: none; }
.aw-tooltip-titel { font-weight: 600; margin-bottom: 4px; color: var(--text); }
.aw-tooltip-zeile { display: grid; grid-template-columns: 14px 1fr auto; align-items: center; gap: 8px; color: var(--text-muted); }
.aw-tooltip-zeile strong { color: var(--text); font-variant-numeric: tabular-nums; }
.aw-diagramm-leer { padding: 24px 0; margin: 0; }
@media (max-width: 900px) { .aw-diagramme { grid-template-columns: 1fr; } }

/* --- Hallenuebersicht, 26.10.2026 ---------------------------------------
   Sieben Kaesten je Arbeitsbereich. Gleich breit und gleich hoch: wer
   vergleichen soll, darf nicht erst Groessen vergleichen muessen. */
.halle-raster { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.halle-kasten { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; display: flex; flex-direction: column; gap: 10px; }
.halle-kopf { display: flex; flex-direction: column; gap: 2px; }
.halle-name { font-weight: 650; font-size: 1.02rem; }
.halle-filter { font-size: .74rem; color: var(--text-muted); }
.halle-zahlen { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.halle-zahl { display: flex; flex-direction: column; }
.halle-zahl-gross { grid-column: 1 / -1; }
.halle-wert { font-size: 1.25rem; font-weight: 650; line-height: 1.1; }
.halle-zahl-gross .halle-wert { font-size: 1.9rem; }
.halle-wort { font-size: .74rem; color: var(--text-muted); }
.halle-luecke { font-size: .74rem; color: var(--text-muted); border-top: 1px solid var(--border); padding-top: 8px; }

/* Das Auftragsalter je Kasten, 26.10.2026. Vier Stufen, von ruhig nach
   auffaellig. Kein Rot fuer die letzte Stufe: liegengebliebene Auftraege
   sind der Normalfall in jedem Lager, und eine Seite, die dauerhaft rot
   leuchtet, wird nicht mehr gelesen. */
.halle-alter { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.halle-alter-stufe { display: flex; flex-direction: column; align-items: center; padding: 6px 2px; border-radius: 7px; background: var(--surface-2, #f4f6f5); }
.halle-alter-zahl { font-weight: 650; font-size: .95rem; line-height: 1.1; }
.halle-alter-wort { font-size: .62rem; color: var(--text-muted); text-align: center; }
.halle-alter-1 { background: color-mix(in srgb, var(--status-gelb, #e8b931) 14%, var(--surface)); }
.halle-alter-2 { background: color-mix(in srgb, var(--status-gelb, #e8b931) 26%, var(--surface)); }
.halle-alter-3 { background: color-mix(in srgb, var(--status-rot) 18%, var(--surface)); }
.halle-wert-fehlt { font-size: .8rem; font-weight: 500; color: var(--text-muted); }
.halle-alter-stufe { text-decoration: none; color: inherit; transition: outline-color .1s; outline: 1px solid transparent; }
.halle-alter-stufe:hover { outline-color: var(--border-strong, var(--border)); color: inherit; }
.halle-name a { color: inherit; text-decoration: none; }
.halle-name a:hover { text-decoration: underline; }
.halle-zugang { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; border-top: 1px solid var(--border); padding-top: 8px; }
.halle-zugang-wort { font-size: .72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; }
.halle-zugang-zahl { font-size: .82rem; font-weight: 600; }
