/* Auftragserfassung - eigene Styles */

/* ============================================================
   Globaler Chevron-Animations-Stack für Collapse-Toggles.
   Funktioniert mit allen üblichen Klassen-Konventionen:
     .collapse-chevron, .vac-chevron, .month-chevron,
     .completed-chevron, .kdv-chevron, .holiday-chevron,
     .user-block-chevron, ...
   Voraussetzung: das Toggle-Element hat
     - data-bs-toggle="collapse"
     - aria-expanded="true"/"false"
   Der globale JS-Helper in app.js synct aria-expanded zuverlässig
   auch auf <div>/<span>-Toggles. display:inline-block ist Pflicht,
   sonst greift transform: rotate auf einem <i> nicht.
   ============================================================ */
[data-bs-toggle="collapse"] [class*="-chevron"] {
    display: inline-block;
    transform-origin: center;
    transition: transform .2s ease;
}
[data-bs-toggle="collapse"][aria-expanded="false"] [class*="-chevron"],
[data-bs-toggle="collapse"].collapsed [class*="-chevron"] {
    transform: rotate(-90deg);
}

/* Schriftgrößen-Abstufung Mobile-First */
body {
    font-size: 1rem;
    -webkit-tap-highlight-color: transparent;
}

/* ============================================================
   Persönliche Schriftgrößen-Modi (Profil-Einstellung)
   "normal" ist Default und braucht keine Klasse.
   ============================================================ */
body.font-size-large {
    font-size: 1.25rem;
}
body.font-size-large h1 { font-size: 2.4rem; }
/* Karten-Ueberschriften (<h2 class="h6|h5">) nicht auf Titelgroesse ziehen (R4-PB-4) */
body.font-size-large h2:not(.h5):not(.h6) { font-size: 2.0rem; }
body.font-size-large .h5 { font-size: 1.4rem; }
body.font-size-large .h6 { font-size: 1.25rem; }
body.font-size-large .h3 { font-size: 1.85rem !important; }
body.font-size-large .small,
body.font-size-large small { font-size: 1.0rem !important; }
body.font-size-large .order-list-item .customer-name { font-size: 1.5rem; }
body.font-size-large .order-list-item .description-preview { font-size: 1.15rem !important; }
body.font-size-large .badge { font-size: 0.95rem; }
body.font-size-large .btn { font-size: 1.15rem; }
body.font-size-large .form-control,
body.font-size-large .form-select { font-size: 1.15rem; }

body.font-size-xlarge {
    font-size: 1.5rem;
    font-weight: 500;
}
body.font-size-xlarge h1,
body.font-size-xlarge h2,
body.font-size-xlarge .h3,
body.font-size-xlarge .h4,
body.font-size-xlarge .h5,
body.font-size-xlarge .h6 { font-weight: 800 !important; }
body.font-size-xlarge h1 { font-size: 2.9rem; }
body.font-size-xlarge h2:not(.h5):not(.h6) { font-size: 2.4rem; }
body.font-size-xlarge .h5 { font-size: 1.7rem; }
body.font-size-xlarge .h6 { font-size: 1.5rem; }
body.font-size-xlarge .h3 { font-size: 2.2rem !important; }
body.font-size-xlarge .small,
body.font-size-xlarge small { font-size: 1.2rem !important; font-weight: 500; }
body.font-size-xlarge .order-list-item .customer-name {
    font-size: 1.85rem;
    font-weight: 800;
}
body.font-size-xlarge .order-list-item .description-preview {
    font-size: 1.4rem !important;
    color: var(--dm-fg-333333, #333) !important;
    font-weight: 500;
}
body.font-size-xlarge .order-list-item .appointment-block {
    font-size: 1.2rem;
    font-weight: 700;
    padding: 6px 14px;
}
body.font-size-xlarge .order-list-item .meta-footer { font-size: 1rem; }
body.font-size-xlarge .badge { font-size: 1.1rem; font-weight: 700; padding: 0.35em 0.7em; }
body.font-size-xlarge .btn {
    font-size: 1.4rem;
    font-weight: 600;
    padding: 0.6rem 1.1rem;
}
body.font-size-xlarge .form-control,
body.font-size-xlarge .form-select {
    font-size: 1.4rem;
    padding: 0.7rem 0.95rem;
    font-weight: 500;
}
body.font-size-xlarge .form-label { font-weight: 700; font-size: 1.2rem; }
body.font-size-xlarge .navbar { font-size: 1.3rem; font-weight: 600; }
body.font-size-xlarge .nav-link { font-weight: 600; }
body.font-size-xlarge .table { font-size: 1.25rem; }
body.font-size-xlarge .table th { font-weight: 800; }
body.font-size-xlarge .alert { font-size: 1.25rem; font-weight: 500; }

/* Druck soll IMMER normale Größe haben, unabhängig vom Bildschirm-Modus */
@media print {
    body.font-size-large,
    body.font-size-xlarge {
        font-size: 1rem !important;
        font-weight: normal !important;
    }
    body.font-size-large *,
    body.font-size-xlarge * {
        font-size: revert !important;
        font-weight: revert !important;
    }
}

/* Karten-Hover-Effekt für die Dashboard-Kacheln */
a.text-decoration-none .card {
    transition: transform .15s ease, box-shadow .15s ease;
}
a.text-decoration-none:hover .card {
    transform: translateY(-2px);
    box-shadow: 0 .5rem 1rem rgba(0,0,0,.1) !important;
}

/* Cards mit border-0 verschwinden auf weissem/hellem Hintergrund.
   Wir setzen ueberall einen dezenten aber sichtbaren Border, damit
   Container voneinander abgegrenzt sind - auch auf "schwachen" Monitoren. */
.card.border-0 {
    border: 1px solid rgba(0, 0, 0, .12) !important;
}
.card.shadow-sm {
    box-shadow: 0 .125rem .35rem rgba(0, 0, 0, .12) !important;
}

/* ============================================================
   Touch / Mobile Quality-of-Life
   ============================================================ */

/* Tap-Highlight (graues Rechteck beim Antippen) global aus — sieht auf
   Tablets schmuddelig aus und :active-Feedback macht das schon. */
* {
    -webkit-tap-highlight-color: transparent;
}

/* Größere Touch-Ziele auf Mobilgeräten */
@media (max-width: 576px) {
    .btn, .form-control, .form-select {
        min-height: 44px;
    }

    /* iOS zoomed beim Fokussieren in ein Input rein, wenn dessen
       computed font-size < 16px ist. Bootstrap-Defaults sind 1rem,
       aber kleinere Form-Controls (.form-control-sm, Inline-Edit-
       Tabellen) liegen darunter. Pauschale 16px hier verhindert das
       ungewollte Zoom-In auf iPad/iPhone. */
    input[type="text"],
    input[type="email"],
    input[type="search"],
    input[type="password"],
    input[type="number"],
    input[type="tel"],
    input[type="url"],
    input[type="date"],
    input[type="datetime-local"],
    input[type="month"],
    input[type="time"],
    input[type="week"],
    select,
    textarea {
        font-size: 16px !important;
    }
    /* Die Auftragskarten-Regeln fuer schmale Bildschirme stehen im Block
       "Handy-Darstellung" (html.ae-handy .order-list-item ...). */
}

/* Prioritäts-Farbkennzeichnung als linker Balken */
.priority-bar {
    border-left: 5px solid var(--priority-color, #6c757d);
    padding-left: 16px;
}

/* Listenansicht: Kundenname groß als Überschrift */
.order-list-item .customer-name {
    font-size: 1.15rem;
    font-weight: 600;
    line-height: 1.3;
}

/* Order-Liste: Karten mit kleinem Abstand */
.order-list {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

/* Dashboard-Gruppen-Header (Heute, Diese Woche, etc.) */
.dashboard-group-header {
    padding: 8px 14px;
    border-radius: 6px;
    margin-bottom: 5px;
    border: 1px solid rgba(0,0,0,0.08);
}

/* Einzelne Karten: weißer Hintergrund, Schatten, abgerundete Ecken */
.order-list-item {
    display: grid;
    background: var(--dm-bg-ffffff, #ffffff);
    color: var(--dm-fg-212529, #212529);
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 6px;
    padding: 14px 16px !important;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    transition: box-shadow 0.15s ease, transform 0.05s ease;
}
.order-list-item:hover {
    box-shadow: 0 2px 6px rgba(0,0,0,0.10);
    text-decoration: none;
    color: var(--dm-fg-212529, #212529);
}
.order-list-item:active {
    transform: translateY(1px);
}

/* Prioritäts-Balken bei List-Items: nur Border, kein eigenes Padding */
.order-list-item.priority-bar {
    border-left: 5px solid var(--priority-color, #6c757d);
    padding-left: 16px !important;
}

/* Termin-Block oben - groß und farblich hervorgehoben */
.order-list-item .appointment-block {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    border-radius: 4px;
    font-size: .95rem;
    font-weight: 600;
    background: var(--priority-color, #6c757d);
    color: var(--priority-text-color, #fff);
}

/* Action-Stack rechts in der Karte: Termin + Drucken + Erledigt.
   Die Karte ist ein Raster: links Titel / Kennzeichen / Auftragstext, rechts
   der Stack ueber alle Zeilen. So waechst die Karte mit dem Stack mit - frueher
   war er absolut positioniert und ragte bei grosser Schrift ("Gross" /
   "Sehr gross") in die naechste Karte. Spaltenbreite und Abstand in em, damit
   sie mit der Schriftgroesse des Profils mitwachsen (150 px bei normaler Schrift). */
.order-list-item {
    position: relative;
    grid-template-columns: minmax(0, 1fr) 9.4em;
    grid-template-rows: auto auto 1fr;
    column-gap: .75em;
    min-height: 140px;
}
.order-list-item > * {
    grid-column: 1;
    min-width: 0;
    align-self: start;
}
.order-list-item .order-action-stack {
    grid-column: 2;
    grid-row: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    z-index: 2;
}
.order-list-item .order-action-stack .btn { white-space: nowrap; }
.order-list-item .order-action-stack .appointment-block {
    justify-content: center;
}
.order-list-item .order-action-stack .btn {
    text-align: center;
}

/* Beschreibung als clean-typografischer Textblock mit dezentem Border (Card-in-Card),
   ohne eigenen Hintergrund (transparent zur Order-Item-Farbe). Leicht fettere Schrift
   und mehr Abstand zur Badge-Zeile, ergaenzt durch feinen grauen Rahmen + minimalen
   Schatten - sieht aus wie ein in sich geschlossener Notiz-Block. */
.order-list-item .description-preview {
    display: -webkit-box;
    -webkit-line-clamp: var(--description-max-lines, 3);
    line-clamp: var(--description-max-lines, 3);
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: pre-wrap;
    color: var(--dm-fg-1c1c1c, #1c1c1c);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.5;
    margin: 16px 0 0 0 !important;
    padding: 8px 10px !important;
    text-indent: 0 !important;
    border: 1px solid var(--dm-bd-dee2e6, #dee2e6);
    border-radius: 4px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}

/* Footer-Zeile mit Erstellt-Datum/Benutzer */
.order-list-item .meta-footer {
    margin-top: 8px;
    color: var(--dm-fg-6c757d, #6c757d);
    font-size: .8rem;
}

/* Druck-Layout */
@media print {
    .navbar, footer, .no-print { display: none !important; }
    body { background: white !important; }
    main { padding: 0 !important; }
}

/* =====================================================
   Leaflet-Popups: Bootstrap-Buttons korrekt darstellen
   =====================================================
   Leaflet definiert .leaflet-container a { color: #0078A8 } mit höherer
   Spezifität als Bootstraps .btn-primary - daher würden Buttons in
   Karten-Popups blau-grau statt weiß angezeigt.
   Die folgenden Overrides stellen die Bootstrap-Standard-Farben wieder
   her und entfernen die Leaflet-Unterstreichung.
   ===================================================== */
.leaflet-container a.btn {
    text-decoration: none;
}
.leaflet-container a.btn-primary,
.leaflet-container a.btn-primary:hover,
.leaflet-container a.btn-primary:focus {
    color: #fff;
}
.leaflet-container a.btn-outline-primary {
    color: var(--bs-primary, #0d6efd);
}
.leaflet-container a.btn-outline-primary:hover,
.leaflet-container a.btn-outline-primary:focus {
    color: #fff;
}
.leaflet-container a.btn-outline-secondary {
    color: var(--dm-fg-6c757d, #6c757d);
}
.leaflet-container a.btn-outline-secondary:hover,
.leaflet-container a.btn-outline-secondary:focus {
    color: #fff;
}
.leaflet-container a.btn-success,
.leaflet-container a.btn-success:hover,
.leaflet-container a.btn-success:focus,
.leaflet-container a.btn-danger,
.leaflet-container a.btn-danger:hover,
.leaflet-container a.btn-danger:focus,
.leaflet-container a.btn-warning,
.leaflet-container a.btn-warning:hover,
.leaflet-container a.btn-warning:focus {
    color: #fff;
}

/* =====================================================
   Password-Strength-Meter (siehe assets/js/password-strength.js)
   ===================================================== */
.pw-strength-meter .pw-bar {
    transition: width 0.25s ease, background-color 0.25s ease;
}
.pw-strength-meter .pw-checks li {
    transition: color 0.15s ease;
}
.pw-strength-meter .pw-icon {
    display: inline-block;
    width: 1.1em;
    text-align: center;
    font-weight: bold;
}

/* =====================================================
   Hoher Kontrast-Modus
   =====================================================
   Aktiv durch body.high-contrast. Verstärkt Hintergrundfarben,
   verdunkelt Texte und macht Rahmen deutlicher sichtbar -
   bewusst etwas zurückhaltend, damit die Anwendung nicht "hart"
   wirkt, aber dennoch deutlich lesbarer als im Normal-Modus.
   ===================================================== */
html:not([data-bs-theme="dark"]) body.high-contrast {
    background: #fff !important;
    color: #1a1a1a;
}
html:not([data-bs-theme="dark"]) body.high-contrast .card,
html:not([data-bs-theme="dark"]) body.high-contrast .modal-content {
    border: 1px solid #444 !important;
    box-shadow: none !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .card-header {
    background: #f0f0f0 !important;
    border-bottom: 1px solid #444 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .table-light,
html:not([data-bs-theme="dark"]) body.high-contrast thead.table-light tr {
    background-color: #e0e0e0 !important;
    color: #1a1a1a !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .table {
    border-color: #555 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .table > :not(caption) > * > * {
    border-bottom-color: #b0b0b0 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .text-muted,
html:not([data-bs-theme="dark"]) body.high-contrast .small.text-muted {
    color: #555 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .form-control,
html:not([data-bs-theme="dark"]) body.high-contrast .form-select {
    border: 1.5px solid #444 !important;
    background: #fff !important;
    color: #1a1a1a !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .form-control:focus,
html:not([data-bs-theme="dark"]) body.high-contrast .form-select:focus {
    border-color: #0a44d6 !important;
    box-shadow: 0 0 0 2px rgba(10,68,214,0.25) !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .form-label {
    color: #1a1a1a !important;
    font-weight: 600;
}

/* Buttons: kräftigere Border und mehr Kontrast */
html:not([data-bs-theme="dark"]) body.high-contrast .btn-outline-primary {
    border: 1.5px solid #0a44d6 !important;
    color: #0a44d6 !important;
    background: #fff !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-outline-secondary {
    border: 1.5px solid #555 !important;
    color: #1a1a1a !important;
    background: #fff !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-outline-success {
    border: 1.5px solid #1a7a36 !important;
    color: #1a7a36 !important;
    background: #fff !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-outline-danger {
    border: 1.5px solid #b80000 !important;
    color: #b80000 !important;
    background: #fff !important;
}
/* Ausgewählte btn-check-Toggles (z.B. Monteur-Auswahl beim Kundendienst) müssen
   auch im Kontrast-Modus als GEFÜLLT erkennbar sein. Ohne diese Regeln überschreibt
   die Outline-Regel oben (background:#fff !important) den Auswahl-Zustand, sodass
   ein angehakter Button optisch wie ein nicht angehakter aussieht. */
html:not([data-bs-theme="dark"]) body.high-contrast .btn-check:checked + .btn-outline-primary {
    background: #0a44d6 !important;
    color: #fff !important;
    border-color: #0a44d6 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-check:checked + .btn-outline-secondary {
    background: #555 !important;
    color: #fff !important;
    border-color: #555 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-check:checked + .btn-outline-success {
    background: #1a7a36 !important;
    color: #fff !important;
    border-color: #1a7a36 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-check:checked + .btn-outline-danger {
    background: #b80000 !important;
    color: #fff !important;
    border-color: #b80000 !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-primary,
html:not([data-bs-theme="dark"]) body.high-contrast .btn-primary:not(:disabled):not(.disabled) {
    background: #0a44d6 !important;
    border-color: #0a44d6 !important;
    color: #fff !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-success,
html:not([data-bs-theme="dark"]) body.high-contrast .btn-success:not(:disabled):not(.disabled) {
    background: #1a7a36 !important;
    border-color: #1a7a36 !important;
    color: #fff !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .btn-danger,
html:not([data-bs-theme="dark"]) body.high-contrast .btn-danger:not(:disabled):not(.disabled) {
    background: #b80000 !important;
    border-color: #b80000 !important;
    color: #fff !important;
}

/* Badges kräftiger */
html:not([data-bs-theme="dark"]) body.high-contrast .badge {
    border: 1px solid rgba(0,0,0,0.25);
    font-weight: 600;
}
html:not([data-bs-theme="dark"]) body.high-contrast .badge.bg-light {
    background: #e0e0e0 !important;
    color: #1a1a1a !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .badge.bg-secondary {
    background: #444 !important;
    color: #fff !important;
}

/* Auftragslisten-Karten: deutlicher Rahmen + verstärkte Highlight-Farben */
html:not([data-bs-theme="dark"]) body.high-contrast .order-list-item {
    border: 1px solid #444 !important;
    box-shadow: none !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .order-list-item:hover {
    box-shadow: 0 0 0 2px rgba(10,68,214,0.25) !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .order-list-item.priority-bar {
    border-left-width: 6px !important;
}

/* Navbar/Modul-Wechsler kräftiger */
html:not([data-bs-theme="dark"]) body.high-contrast .navbar.bg-primary {
    background-color: #0a2b80 !important;
    border-bottom: 2px solid #1a1a1a !important;
}
html:not([data-bs-theme="dark"]) body.high-contrast .navbar .nav-link,
html:not([data-bs-theme="dark"]) body.high-contrast .navbar .navbar-brand,
html:not([data-bs-theme="dark"]) body.high-contrast .navbar .navbar-text {
    color: #fff !important;
    font-weight: 500;
}

/* Alerts etwas kräftiger umranden */
html:not([data-bs-theme="dark"]) body.high-contrast .alert {
    border-width: 1.5px !important;
    font-weight: 500;
}
html:not([data-bs-theme="dark"]) body.high-contrast .alert-success { background: #d3f5dd !important; color: #0e3d1d !important; border-color: #1a7a36 !important; }
html:not([data-bs-theme="dark"]) body.high-contrast .alert-danger  { background: #fde0e0 !important; color: #6b0000 !important; border-color: #b80000 !important; }
html:not([data-bs-theme="dark"]) body.high-contrast .alert-warning { background: #fff5b8 !important; color: #503600 !important; border-color: #806600 !important; }
html:not([data-bs-theme="dark"]) body.high-contrast .alert-info    { background: #d3e0ff !important; color: #0a2b80 !important; border-color: #0a44d6 !important; }

/* Links kräftiger */
html:not([data-bs-theme="dark"]) body.high-contrast a {
    color: #0a44d6;
}
html:not([data-bs-theme="dark"]) body.high-contrast a:hover {
    color: #082880;
    text-decoration: underline;
}

/* Tabellen-Highlights (überfällig/heute/zugewiesen/gedruckt) leicht intensivieren */
html:not([data-bs-theme="dark"]) body.high-contrast .order-list-item[style*="background-color"] {
    border: 1px solid #444 !important;
    box-shadow: 1px 1px 0 rgba(0,0,0,0.08) !important;
}

/* =====================================================
   Article-Search Dropdown - Mobile-Anpassung
   =====================================================
   Auf Mobile-Bildschirmen ist das Eingabefeld oft schmal
   (z.B. in einer Tabelle mit wenig Spaltenbreite). Das
   Dropdown würde dann unleserlich klein werden. Daher
   strecken wir es auf Mobile bis fast zum Viewport-Rand
   und größere Items für Touch-Bedienung.
   ===================================================== */
@media (max-width: 768px) {
    .article-search-dropdown {
        /* Fast volle Fensterbreite, min/max-width gewinnt gegen das Bootstrap w-100.
           left ist relativ zum article-search-wrapper (= linke Kante des Inputs);
           article-search.js (adjustDropdownWidth) setzt --asd-left/--asd-width beim
           Oeffnen so, dass die Liste 12 px vom LINKEN FENSTERRAND beginnt und rechts
           12 px Rand laesst - auch wenn das Feld eingerueckt ist (Auftrags-Modal,
           Audit R4-PM-3: sonst ragte sie rechts heraus und die Seite scrollte seitlich).
           Ohne JS-Wert wie bisher ab der Feldkante. */
        left: var(--asd-left, 0px) !important;
        width: auto !important;
        min-width: var(--asd-width, calc(100vw - 24px)) !important;
        max-width: var(--asd-width, calc(100vw - 24px)) !important;
    }
    /* Treffer-Items größer/luftiger für Touch-Bedienung */
    .article-search-dropdown .list-group-item {
        padding: 12px 14px;
        font-size: 0.95rem;
        line-height: 1.35;
    }
}

/* Trefferliste der Artikelsuche am PC: deutlich breiter als die Zelle, in der das
   Nummernfeld steht (Positions-Tabellen haben table-layout: fixed und eine schmale
   Nummern-Spalte - die Liste war dort auf ~150 px gestutzt, Rueckmeldung 2026-10-20,
   Lieferschein). EINE Regel fuer alle Belege/Kasse/Auftrag statt je View; Handy
   regelt die Media-Query darunter mit !important, die Beleg-Ansicht #belegSheet und
   das Regal-Panel setzen eigene Breiten. */
.article-search-dropdown { min-width: min(640px, calc(100vw - 40px)); }

/* Treffer-Items immer auf Weiß — Bootstrap-Listen erben --bs-body-bg als
   Item-Hintergrund (im Modern-Design früher der graue Seitengrund, seit
   2026-09-10 weiß; bleibt als Absicherung). Variante (.active, -warning)
   definieren die Variable am Item selbst neu und bleiben unberührt. */
.article-search-dropdown,
.customer-search-dropdown {
    --bs-list-group-bg: #fff;
}

/* Aktiver Treffer (Hover/Pfeiltasten): Bootstraps .active färbt den
   Hintergrund primärblau — text-muted bliebe grau und wäre darauf
   kaum lesbar. Muted-Zeilen daher auf Weiß aufhellen. */
.article-search-dropdown .list-group-item.active .text-muted,
.customer-search-dropdown .list-group-item.active .text-muted {
    color: rgba(255, 255, 255, 0.85) !important;
}

/* Slot-Suche: das Kundenfeld ist die schmale letzte Spalte - die Trefferliste
   haengt rechtsbuendig darunter und bekommt eine lesbare Mindestbreite. */
#tpSlotModal .customer-search-dropdown { left: auto; right: 0; width: auto; min-width: 26rem; max-width: 90vw; }
/* Katalog-Abgleich im Artikel-Dropdown: abgekündigter Treffer grau zurückgenommen,
   sein Nachfolger direkt darunter eingerückt und grün markiert. */
.article-search-dropdown .list-group-item.article-discontinued:not(.active) {
    background: var(--dm-bg-eceef0, #eceef0);
    color: var(--dm-fg-6c757d, #6c757d);
}
.article-search-dropdown .list-group-item.article-discontinued:not(.active) .fw-semibold,
.article-search-dropdown .list-group-item.article-discontinued:not(.active) .fw-bold {
    color: var(--dm-fg-6c757d, #6c757d);
    font-weight: 500 !important;
}
.article-search-dropdown .list-group-item.article-discontinued:not(.active) img {
    opacity: .55;
}
.article-search-dropdown .list-group-item.article-successor {
    padding-left: 2.25rem;
    border-left: 4px solid #198754;
}
.article-search-dropdown .list-group-item.article-successor:not(.active) {
    background: var(--dm-bg-eaf6ef, #eaf6ef);
}
/* Satz-Verweis (keine Abkündigung): eingerückt, aber neutral statt grün */
.article-search-dropdown .list-group-item.article-successor.article-successor-set {
    border-left-color: #adb5bd;
}
.article-search-dropdown .list-group-item.article-successor.article-successor-set:not(.active) {
    background: var(--dm-bg-f6f7f8, #f6f7f8);
}
/* Artikellisten im Artikel-Dropdown: Reiterzeile + Listen-Ansicht (Pfeil rechts/links,
   article-search.js). top+bottom: klebt auch im Drop-Up (column-reverse) am Eingabefeld. */
.article-search-dropdown .article-search-tabs {
    display: flex;
    gap: .25rem;
    padding: .3rem;
    position: sticky;
    top: 0;
    bottom: 0;
    z-index: 2;
    background: var(--dm-bg-f8f9fa, #f8f9fa);
}
.article-search-dropdown .article-search-tabs .btn {
    flex: 1 1 0;
    padding: .15rem .5rem;
    font-size: .8rem;
}
.article-search-dropdown .article-list-head {
    background: var(--dm-bg-e7f1ff, #e7f1ff);
    border-left: 4px solid #0d6efd;
    padding: .35rem .75rem;
}
/* Beleg-Erfassung: Kopfzeile ist wählbar ("Ganze Liste übernehmen") */
.article-search-dropdown .list-group-item.article-list-head.active {
    background: var(--bs-list-group-active-bg);
    color: var(--bs-list-group-active-color);
}
.article-search-dropdown .list-group-item.active .article-list-take {
    color: #fff;
    border-color: #fff;
}
.article-search-dropdown .list-group-item.article-list-item {
    padding-left: 2.25rem;
    border-left: 4px solid var(--dm-bd-9ec5fe, #9ec5fe);
}
.article-search-dropdown .list-group-item.active .text-secondary {
    color: #fff !important;
}
/* ... ebenso die Katalog-Hinweise (Nachfolger / Nachfolger von) */
.article-search-dropdown .list-group-item.active .text-success,
.article-search-dropdown .list-group-item.active .text-warning-emphasis {
    color: #fff !important;
}

/* =====================================================
   Geteilte Kachel (z.B. "Alle / Meine Aufträge" auf Dashboard)
   =====================================================
   Die ganze Karte hebt sich beim Hover wie die anderen Kacheln,
   und die einzelne Hälfte zeigt zusätzlich einen leichten
   Hintergrund-Highlight, damit klar ist welche Seite geklickt wird.
   ===================================================== */
.split-tile {
    transition: transform .15s ease, box-shadow .15s ease;
}
.split-tile:hover {
    transform: translateY(-2px);
    box-shadow: 0 .5rem 1rem rgba(0,0,0,.1) !important;
}
.split-tile .tile-half {
    transition: background-color .15s ease;
}
.split-tile .tile-half:hover {
    background-color: rgba(13, 110, 253, 0.05);
}


/* ============================================================
   Admin-Kennzeichnung
   Elemente, die NUR Admins sehen (Navbar-Punkte, Buttons, Cards),
   tragen .admin-marked und sind einheitlich gelb umrandet -
   gleiche Optik wie die Admin-Card im Auftrags-Detail.
   Nur fuer admin-EXKLUSIVE Funktionen verwenden (isAdmin()-Gate),
   nicht fuer Permission-basierte, die auch Nicht-Admins haben koennen
   - auch dann nicht, wenn das Ziel unter /admin/... liegt.
   ============================================================ */
.admin-marked {
    border: 1px solid #ffc107 !important;
    border-radius: var(--bs-border-radius, .375rem);
}

/* ============================================================
   Diktat-Komponente (Spracheingabe, assets/js/dictation.js)
   Ohne Browser-Unterstuetzung blendet .no-dictation am <html>
   die Bars komplett aus.
   ============================================================ */
.no-dictation .dictation-bar {
    display: none !important;
}
.dictation-btn.recording {
    animation: dictation-pulse 1.2s ease-in-out infinite;
}
@keyframes dictation-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.45); }
    70%  { box-shadow: 0 0 0 8px rgba(220, 53, 69, 0); }
    100% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); }
}


/* ============================================================
   Auftrags-Timer (Arbeitszeit-Bereich im Auftrag)
   Gruener Puls-Punkt zeigt eine laufende Zeit an.
   ============================================================ */
.wt-timer-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #198754;
    animation: wt-timer-pulse 1.6s ease-in-out infinite;
}
@keyframes wt-timer-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: .25; }
}

/* ============================================================
   Handy-Darstellung (html.ae-handy = kuerzere Bildschirmseite < 768 px,
   gesetzt in partials/theme_head.php; Tablet = PC).
   .handy-hide / .handy-only schalten Bausteine je Geraet,
   .ae-sheet ist das Fenster von unten (Arbeitszeit, Material).
   ============================================================ */
html.ae-handy .handy-hide { display: none !important; }
html:not(.ae-handy) .handy-only { display: none !important; }

/* Arbeitszeit am Handy: Leseliste + Fenster von unten statt der Tabelle
   (orders/_work_times.php). Am PC bleibt .wt-desktop. */
html.ae-handy .wt-desktop { display: none !important; }
html:not(.ae-handy) .wt-mobile { display: none !important; }
.wt-sheet, .ae-sheet { position: fixed; inset: 0; z-index: 1080; }
.wt-sheet-backdrop, .ae-sheet-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .45); }
.wt-sheet-panel, .ae-sheet-panel {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    max-height: 88vh;
    overflow-y: auto;
    background: var(--dm-bg-ffffff, #fff);
    border-radius: 1rem 1rem 0 0;
    padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -4px 20px rgba(0, 0, 0, .2);
}

/* Auftrag am Handy: Reihenfolge der Karten. Die beiden Spalten (col-lg-8 /
   col-lg-4) werden aufgeloest (display:contents), die Karten haengen direkt
   in der Flex-Zeile und sortieren sich ueber od-*: Aktionen, Kunde, Termin,
   Auftragstext, Erledigt-Notiz, Material, Arbeitszeit, Bilder, Mitarbeiter,
   Erstellt, Wieder oeffnen, Admin. Am PC unveraendert. */
html.ae-handy .order-detail-row { margin: 0; }
html.ae-handy .order-detail-row > [class*="col-"] { display: contents; }
html.ae-handy .order-detail-row > [class*="col-"] > * { flex: 0 0 100%; max-width: 100%; min-width: 0; }
html.ae-handy .od-actions  { order: 1; }
html.ae-handy .od-customer { order: 2; }
html.ae-handy .od-termin   { order: 3; }
html.ae-handy .od-text     { order: 4; }
html.ae-handy .od-done     { order: 5; }
html.ae-handy .od-material { order: 6; }
html.ae-handy .od-worktime { order: 7; }
html.ae-handy .od-images   { order: 8; }
html.ae-handy .od-staff    { order: 9; }  /* Mitarbeiter erst nach den Bildern (User-Vorgabe 2026-09-26) */
html.ae-handy .od-created  { order: 10; }
html.ae-handy .od-reopen   { order: 11; }
html.ae-handy .od-admin    { order: 12; }

/* Aktionsleiste am Handy: zwei gleich breite Spalten, Timer oben in voller
   Breite, darunter Navi + Karte, Erledigt + Drucken. */
html.ae-handy .order-actions { display: grid !important; grid-template-columns: 1fr 1fr; gap: .5rem; } /* !important gegen .d-flex */
html.ae-handy .order-actions > * { width: 100%; min-width: 0; }
html.ae-handy .order-actions .btn { width: 100%; display: flex; align-items: center; justify-content: center; }
html.ae-handy .order-actions > [data-timer-top] { grid-column: 1 / -1; order: -1; }
html.ae-handy .order-actions > .od-act-navi { order: 1; }
html.ae-handy .order-actions > .od-act-map  { order: 2; }
html.ae-handy .order-actions > .od-act-done { order: 3; }
html.ae-handy .order-actions > .print-action-btn { order: 4; }

/* Reiter Auftragstext / Arbeiten: nie umbrechen (Beschriftung am Handy kurz). */
html.ae-handy .order-text-toggle .nav-link { white-space: nowrap; padding-inline: .5rem; }

/* Abschnitts-Koepfe am Handy: Arbeitszeit = Titel + Start/Stopp in einer
   Zeile, Summen darunter. */
html.ae-handy #orderWorkTimeCard .card-header > h2 { flex: 1 1 100%; flex-wrap: nowrap; justify-content: space-between; }
html.ae-handy #orderWorkTimeCard .card-header > .wt-sums { flex: 0 0 100%; }

/* Lieferschein am Handy (Audit RM3, 2026-10-13): keine Beleg-Ansicht (Umschalter
   weg, beleg-form.js startet mit cfg.handyTable in der Tabelle), die Positionen
   als Karten statt der Tabelle mit festen Spalten - dieselben Felder, nur anders
   dargestellt (delivery_notes/form.php, Zellen dn-c-* + data-label). Am PC unveraendert. */
html.ae-handy #deliveryNoteForm .be-viewbar { display: none !important; } /* !important gegen .d-flex */
html.ae-handy #deliveryNoteForm #itemsCard > .card-body { padding: .5rem; }
html.ae-handy #deliveryNoteForm #itemsTable,
html.ae-handy #deliveryNoteForm #itemsTable > tbody,
html.ae-handy #deliveryNoteForm #itemsTable > tbody > tr:not(.item-row),
html.ae-handy #deliveryNoteForm #itemsTable > tbody > tr:not(.item-row) > td { display: block; width: 100%; }
html.ae-handy #deliveryNoteForm #itemsTable > thead { display: none; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row {
    display: grid;
    grid-template-columns: 1fr 1fr auto;
    grid-template-areas: "nr nr rm" "name name name" "qty unit unit";
    gap: .5rem;
    padding: .75rem;
    margin-bottom: .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
}
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > td { display: block; padding: 0; border: 0; min-width: 0; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > td.row-drag { display: none; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > .dn-c-nr   { grid-area: nr; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > .dn-c-name { grid-area: name; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > .dn-c-qty  { grid-area: qty; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > .dn-c-unit { grid-area: unit; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > .dn-c-rm   { grid-area: rm; align-self: end; }
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row > td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: .75rem;
    color: var(--bs-secondary-color);
    margin-bottom: .125rem;
}
/* 16 px: iOS zoomt sonst beim Antippen ins Feld */
html.ae-handy #deliveryNoteForm #itemsTable tr.item-row .form-control { font-size: 1rem; }
html.ae-handy #deliveryNoteForm #itemsTable .row-remove { padding: .375rem .75rem; }
/* Trefferliste der Artikelsuche: so breit wie das Nummernfeld der Karte (die allgemeine
   Handy-Regel - Fensterbreite ab der Feldkante - ragte hier ueber den Rand hinaus) */
html.ae-handy #deliveryNoteForm #itemsTable .article-search-dropdown { min-width: 100% !important; max-width: 100% !important; }

/* Material am Handy: Artikelnummer gross und gleichwertig zur Bezeichnung. */
.om-number { font-size: 1.15rem; line-height: 1.25; }
.om-name   { line-height: 1.3; }

/* Stammdaten am Handy (User-Entscheidung 2026-09-26, A1 / B2 / C2):
   - Artikelliste: Karten (articles/_handy_list.php), Filter nebeneinander,
     Kopf nur "+" und Menue.
   - Artikel-Stammblatt + Kundenkarte: Aktionsknoepfe als Raster mit zwei
     Spalten (.sb-actions), Reiter in EINER wischbaren Zeile (.handy-tabs),
     Reiter-Tabellen als Listen (.sb-list neben .handy-hide-Tabellen). */
.al-handy .al-nr { font-size: 1.15rem; line-height: 1.25; }
html.ae-handy #articleFilterForm .al-filter-col { flex: 0 0 auto; width: auto; }
html.ae-handy .sb-actions { display: grid !important; grid-template-columns: 1fr 1fr; gap: .5rem; width: 100%; } /* !important gegen .d-flex */
html.ae-handy .sb-actions > * { width: 100%; min-width: 0; margin: 0; }
html.ae-handy .sb-actions .btn { width: 100%; display: flex; align-items: center; justify-content: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.ae-handy .sb-actions .sb-act-big { grid-row: 1; font-size: 1.1rem; padding-block: .65rem; }
html.ae-handy .sb-actions .sb-act-big.btn-outline-success { font-weight: 600; }
html.ae-handy .sb-actions .sb-act-first { order: -1; }
html.ae-handy .sb-actions .sb-act-last  { order: 9; }
/* Kopf in zwei Zeilen (2026-11-04, articles/show.php + customers/show.php): am PC Zurueck + Knoepfe oben,
   Titel darunter; am Handy wie der Lieferschein (.dn-head) Zurueck, Titel, dann das Raster. */
html.ae-handy .sb-head { display: flex; flex-direction: column; }
html.ae-handy .sb-head > .sb-topbar { display: contents !important; } /* !important gegen .d-flex */
html.ae-handy .sb-head .sb-back { margin-bottom: .75rem; }
html.ae-handy .sb-head .sb-actions { order: 3; margin-bottom: 1rem; }
html.ae-handy .handy-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
html.ae-handy .handy-tabs::-webkit-scrollbar { display: none; }
html.ae-handy .handy-tabs .nav-link { white-space: nowrap; }
html.ae-handy #customer-mini-map { height: 140px !important; }

/* Auftragsliste am Handy (User-Entscheidung 2026-10-02: nur Karten, kein
   Umschalter - orders/index.php, OrderController::resolveViewMode()).
   - Karte: kein rechter Freiraum mehr, der Action-Stack (Termin, Drucken,
     Erledigt) ist nicht mehr absolut, sondern eine Zeile UNTER dem
     Auftragstext: Termin in eigener Zeile links, Drucken + Erledigt je
     halbe Breite (ein einzelner Knopf volle Breite), Knoepfe 44 px hoch.
     Gilt fuer jede .order-list-item (die 576-px-Regeln dafuer sind hierher
     gewandert; dashboard/_order_row.php nutzt dieselbe Klasse).
   - Filter (.of-*): Suche volle Breite mit Reset-Symbol daneben, Prioritaet +
     Mitarbeiter je halbe Breite, Kategorie-Chips in EINER wischbaren Zeile,
     "Nur meine Auftraege" darunter. */
html.ae-handy .order-list-item.order-list-item { min-height: 0; grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
html.ae-handy .order-list-item .customer-name { white-space: normal; overflow-wrap: anywhere; }
html.ae-handy .order-list-item .order-action-stack {
    grid-column: 1;
    grid-row: auto;
    width: 100%;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .5rem;
    margin-top: .75rem;
}
html.ae-handy .order-list-item .order-action-stack .appointment-block { grid-column: 1 / -1; justify-content: flex-start; min-height: 44px; }
html.ae-handy .order-list-item .order-action-stack .btn { min-height: 44px; display: flex; align-items: center; justify-content: center; }
html.ae-handy .order-list-item .order-action-stack .print-action-btn:last-child { grid-column: 1 / -1; }
html.ae-handy .order-list-item .order-action-stack .complete-action-form { display: flex; }
html.ae-handy .order-list-item .order-action-stack .complete-action-form .btn { flex: 1 1 auto; }
html.ae-handy #orderFilterForm .of-search { flex: 1 1 0; width: auto; min-width: 70%; } /* min-width: Prioritaet passt nicht mehr daneben -> eigene Zeile */
html.ae-handy #orderFilterForm .of-reset  { order: 1; }
html.ae-handy #orderFilterForm .of-reset .btn { min-width: 44px; }
html.ae-handy #orderFilterForm .of-prio,
html.ae-handy #orderFilterForm .of-tech  { order: 2; flex: 0 0 50%; width: 50%; }
html.ae-handy #orderFilterForm .of-cats-row { flex-direction: column; align-items: stretch; }
html.ae-handy #orderFilterForm .of-cats { flex-wrap: nowrap !important; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; width: 100%; }
html.ae-handy #orderFilterForm .of-cats::-webkit-scrollbar { display: none; }
html.ae-handy #orderFilterForm .of-cats .btn { white-space: nowrap; flex: 0 0 auto; }
html.ae-handy #orderFilterForm #onlyMineBtn { margin-left: 0 !important; width: 100%; }

/* Stammdaten am Handy, Teil 2 (User-Entscheidung 2026-10-02: Anzeigen reicht):
   - Kundenliste: Karten (customers/_handy_list.php) mit Anrufen + Navi, Tippen
     oeffnet die Kundenkarte.
   - Kundenkonto: Zeitraum-Formular umbrechend (.konto-range), Listen statt
     Tabellen; Kunden-Formular: Karte niedriger.
   - Artikelliste (articles/lists/show.php, .al-handy-grid): DIESELBE
     Tabellenzeile aus _item_row.php wird zum Karten-Raster - ein Markup, damit
     article-lists.js (Menge, Entfernen, AJAX-Hinzufuegen) ueberall greift. */
.cl-handy .cl-name { font-size: 1.1rem; line-height: 1.25; }
.cl-handy .cl-acts .btn { flex: 1 1 0; display: flex; align-items: center; justify-content: center; }
html.ae-handy .konto-range { flex-wrap: wrap; width: 100%; margin-left: 0 !important; }
html.ae-handy .konto-range label { flex: 0 0 100%; }
html.ae-handy .konto-range input[type="date"] { flex: 1 1 40%; width: auto !important; min-width: 0; }
html.ae-handy .konto-range .btn { flex: 1 1 45%; }
html.ae-handy #customerLocationMap { height: 200px !important; }
html.ae-handy .al-handy-grid table,
html.ae-handy .al-handy-grid tbody,
html.ae-handy .al-handy-grid tfoot { display: block; width: 100%; }
html.ae-handy .al-handy-grid thead,
html.ae-handy .al-handy-grid .al-drag { display: none; }
html.ae-handy .al-handy-grid tbody tr {
    display: grid;
    grid-template-columns: 52px auto minmax(0, 1fr) auto auto;
    grid-template-areas: "thumb nr nr nr remove" "thumb name name name name" "qty qty unit price total"; /* Menge ueber Bild- + Nummernspalte, sonst passt das 5.5-rem-Feld nicht in 52 px */
    column-gap: .5rem;
    row-gap: .2rem;
    align-items: center;
    padding: .5rem .25rem;
    border-bottom: 1px solid var(--bs-border-color);
}
html.ae-handy .al-handy-grid tbody td { display: block; padding: 0; border: 0; width: auto !important; white-space: normal; min-width: 0; }
html.ae-handy .al-handy-grid .al-c-thumb  { grid-area: thumb; }
html.ae-handy .al-handy-grid .al-c-nr     { grid-area: nr; font-size: 1.15rem; line-height: 1.25; }
html.ae-handy .al-handy-grid .al-c-name   { grid-area: name; }
html.ae-handy .al-handy-grid .al-c-qty    { grid-area: qty; }
html.ae-handy .al-handy-grid .al-c-qty .al-quantity { width: 5.5rem; }
html.ae-handy .al-handy-grid .al-c-unit   { grid-area: unit; }
html.ae-handy .al-handy-grid .al-c-price  { grid-area: price; font-size: .85rem; color: var(--bs-secondary-color); }
html.ae-handy .al-handy-grid .al-c-total  { grid-area: total; font-weight: 600; }
html.ae-handy .al-handy-grid .al-c-remove { grid-area: remove; }

/* Projekte am Handy (User-Entscheidung 2026-10-08: A1 / B1 / D1 / E1 / F1,
   Auftraege als Karten der Auftragsliste, Anfragen + Abrechnung "am PC"):
   - Liste: Karten (projekte/_handy_list.php).
   - Kopf: Raster .sb-actions wie die Kundenkarte, Reiter wischbar (.handy-tabs).
   - Absprachen: Text zuerst, Knoepfe darunter (.pn-*), "Neue Absprache" als
     Fenster von unten.
   - Montage: Checkliste .pm-list mit grossem Haken; Klappkopf -> Knopf.
   - Dokumente: Vorschau-Raster .pd-grid, Foto-Knoepfe .pd-pick. */
.pl-handy .pl-title { font-size: 1.1rem; line-height: 1.25; }
html.ae-handy .pk-head h1 { font-size: 1.35rem; }
html.ae-handy #projektTabs { display: flex; max-width: 100%; }
html.ae-handy .pn-new { width: 100%; padding-block: .6rem; }
html.ae-handy .projekt-note-card .card-body { display: flex; flex-direction: column; }
html.ae-handy .projekt-note-card .pn-top { display: contents !important; } /* !important gegen .d-flex */
html.ae-handy .projekt-note-card .pn-meta  { order: 0; }
html.ae-handy .projekt-note-card .pn-text  { order: 1; }
html.ae-handy .projekt-note-card .pn-files { order: 2; }
html.ae-handy .projekt-note-card .pn-acts  { order: 3; gap: .5rem !important; margin-top: .5rem; padding-top: .5rem; border-top: 1px solid var(--bs-border-color); }
html.ae-handy .projekt-note-card .pn-edit  { order: 4; }
html.ae-handy .projekt-note-card .pn-acts .btn { min-height: 42px; display: flex; align-items: center; justify-content: center; }
html.ae-handy .projekt-note-card .pn-acts .projekt-note-file-btn { flex: 1 1 auto; }
html.ae-handy .projekt-note-card .pn-acts .btn-sm { font-size: .95rem; padding-inline: .9rem; }
html.ae-handy #projektNoteModal .modal-dialog { position: fixed; left: 0; right: 0; bottom: 0; margin: 0; max-width: none; min-height: 0; align-items: flex-end; }
html.ae-handy #projektNoteModal.fade .modal-dialog { transform: translateY(100%); transition: transform .25s ease-out; }
html.ae-handy #projektNoteModal.show .modal-dialog { transform: none; }
html.ae-handy #projektNoteModal .modal-content { border: 0; border-radius: 1rem 1rem 0 0; max-height: 92vh; padding-bottom: env(safe-area-inset-bottom, 0px); }
html.ae-handy #projektNoteModal .modal-body { overflow-y: auto; }
html.ae-handy #projektNoteModal .modal-footer .btn { flex: 1 1 0; }
.pn-pick, .pd-pick { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.pn-pick .btn, .pd-pick .btn { padding-block: .6rem; display: flex; align-items: center; justify-content: center; }
html.ae-handy .pm-new-card:has(> .collapse:not(.show):not(.collapsing)) { display: none; }
.pm-list .pm-check { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; font-size: 1.25rem; padding: 0; }
.pd-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; }
.pd-grid .pd-thumb { position: relative; display: flex; align-items: center; justify-content: center; aspect-ratio: 1; overflow: hidden; border: 1px solid var(--bs-border-color); border-radius: .375rem; background: var(--dm-bg-ffffff, #fff); }
.pd-grid .pd-thumb img { width: 100%; height: 100%; object-fit: cover; }
.pd-grid .pd-thumb canvas { max-width: 100%; max-height: 100%; position: relative; z-index: 1; }
.pd-grid .pd-thumb .projekt-tile-icon .bi { font-size: 2rem; }
.pd-grid .pd-sub { font-size: .72rem; }
html.ae-handy .order-list-item .order-action-stack .po-unlink { display: flex; }
html.ae-handy .order-list-item .order-action-stack .po-unlink .btn,
html.ae-handy .order-list-item .order-action-stack button.po-unlink { flex: 1 1 auto; min-height: 44px; display: flex; align-items: center; justify-content: center; }
html.ae-handy .al-handy-grid tfoot tr { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .5rem; padding: .5rem .25rem; }
html.ae-handy .al-handy-grid tfoot td { display: block; padding: 0; border: 0; }
html.ae-handy .al-handy-grid #alEmptyRow td { flex: 1 1 100%; }

/* Lieferscheine + Benutzerverwaltung am Handy (User-Entscheidung 2026-10-31: L1 / A1 / B1):
   - Liste: Karten (delivery_notes/_handy_list.php), Ansichts-Knoepfe in EINER
     wischbaren Zeile, nur "Neuer Lieferschein" im Kopf.
   - Ansicht: Knoepfe als Raster .sb-actions (Formulare darin als Block),
     immer Tabellen-Ansicht (Umschalter weg, beleg-view.js cfg.handyTable),
     Artikel-Karte vor Kunde/Erstellt, Positionen als Liste mit Menge links.
   - Benutzer: Karten mit Knoepfen mit Text (.ul-handy), Protokoll zugeklappt. */
.dl-handy .dl-name { font-size: 1.05rem; line-height: 1.25; }
.dl-handy .dl-meta { font-size: .8rem; color: var(--bs-secondary-color); }
html.ae-handy #lieferscheineListe .dl-views > div { flex-wrap: nowrap !important; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; } /* !important gegen .flex-wrap */
html.ae-handy #lieferscheineListe .dl-views > div::-webkit-scrollbar { display: none; }
html.ae-handy #lieferscheineListe .dl-views .btn { white-space: nowrap; flex: 0 0 auto; }
html.ae-handy .dn-head { display: flex; flex-direction: column; }
html.ae-handy .dn-head > .dn-topbar { display: contents !important; } /* !important gegen .d-flex */
html.ae-handy .dn-head .dn-back:not(:empty) { margin-bottom: .75rem; }
html.ae-handy .dn-head .dn-actions { order: 3; margin-bottom: 1rem; }
html.ae-handy .dn-actions > form { display: block; }
html.ae-handy .dn-actions .btn { white-space: normal; line-height: 1.2; }
html.ae-handy .be-viewbar[data-handy-table] { display: none !important; } /* !important gegen .d-flex */
html.ae-handy #belegTableView:has(#dnItemsCard) { display: flex; flex-direction: column; }
html.ae-handy #belegTableView #dnItemsCard { order: -1; }
html.ae-handy #belegTableView #dnItemsCard > .card-body { padding: .5rem; }
html.ae-handy #dnItemsTable,
html.ae-handy #dnItemsTable > tbody { display: block; width: 100%; margin: 0; }
html.ae-handy #dnItemsTable > thead { display: none; }
html.ae-handy #dnItemsTable > tbody > tr {
    display: grid; grid-template-columns: 4.5rem auto minmax(0, 1fr);
    grid-template-areas: "qty name name" "qty nr dim";
    gap: .1rem .75rem; padding: .55rem .25rem; border-bottom: 1px solid var(--bs-border-color);
}
html.ae-handy #dnItemsTable > tbody > tr:last-child { border-bottom: 0; }
html.ae-handy #dnItemsTable > tbody > tr > td { display: block; padding: 0; border: 0; min-width: 0; background: transparent; }
html.ae-handy #dnItemsTable .dn-s-qty  { grid-area: qty; font-size: 1.1rem; font-weight: 600; line-height: 1.25; }
html.ae-handy #dnItemsTable .dn-s-qty .small { display: block; font-size: .72rem; font-weight: 400; font-family: var(--bs-body-font-family); }
html.ae-handy #dnItemsTable .dn-s-name { grid-area: name; overflow-wrap: anywhere; }
html.ae-handy #dnItemsTable .dn-s-nr   { grid-area: nr; color: var(--bs-secondary-color); }
html.ae-handy #dnItemsTable .dn-s-dim  { grid-area: dim; overflow-wrap: anywhere; }
html.ae-handy #dnItemsTable .dn-s-dim:not(:empty)::before { content: "· "; }
.ul-handy .ul-name { font-size: 1.05rem; }
.ul-handy .ul-acts > * { flex: 1 1 0; min-width: 0; }
.ul-handy .ul-acts .btn { width: 100%; display: flex; align-items: center; justify-content: center; white-space: nowrap; padding-inline: .4rem; }
html.ae-handy .ul-new { width: 100%; }
html:not(.ae-handy) #userSwitchLog.collapse:not(.show) { display: block; }

/* Schaltplaene am Handy (schaltplan/index.php, _baum.php, _liste.php, show.php,
   assets/js/schaltplan-touch.js; User-Entscheidung 2026-10-02):
   - Uebersicht: Seitenleiste + Liste untereinander (auch quer gehaltenes Handy),
     Baumzeilen 44 px hoch, Klapp-Knopf 40x40 px Tipp-Flaeche.
   - Plan-Ansicht: Kopf einzeilig, Werkzeugleiste EINE Zeile (Suche + "3 / 12"),
     Treffer-Chips wischbar zwischen zwei festen Knoepfen, Zuruecksetzen als X,
     Pfeile ueber dem Bild kleiner + blasser, Pinch/Pan ueber Pointer Events
     (touch-action: none), Marker tippbar. */
html.ae-handy .splan-explorer > [class*="col-"] { flex: 0 0 100%; max-width: 100%; width: 100%; }
html.ae-handy .splan-nav { font-size: 1rem; }
html.ae-handy .splan-nav-row { min-height: 44px; padding: .25rem .75rem .25rem .25rem; }
html.ae-handy .splan-nav-row:hover { background: inherit; }
html.ae-handy .splan-nav-row.active { background: var(--dm-bg-e7f1ff, #e7f1ff); }
html.ae-handy .splan-nav-toggle { flex: 0 0 40px; width: 40px; height: 40px; }
html.ae-handy .splan-nav-toggle .bi { font-size: 1rem; }
html.ae-handy .splan-nav-link { padding: .35rem .25rem; }
html.ae-handy .splan-status-badge { font-size: .7rem; vertical-align: baseline; }
html.ae-handy .splan-head { flex-wrap: nowrap; align-items: center; }
html.ae-handy .splan-head-main { display: flex; align-items: center; gap: .5rem; flex: 1 1 auto; min-width: 0; }
html.ae-handy .splan-title { margin-top: 0 !important; max-width: none !important; min-width: 0; flex: 1 1 auto; font-size: 1.05rem; }
html.ae-handy .splan-tools { flex-wrap: nowrap; }
html.ae-handy .splan-tools > .splan-tool-search { flex: 1 1 auto; width: auto; min-width: 0; }
html.ae-handy .splan-tools > .splan-tool-pages { flex: 0 0 auto; width: auto; }
html.ae-handy .splan-tool-search form { align-items: stretch; }
html.ae-handy .splan-search-form .btn-outline-warning,
html.ae-handy .splan-tool-search .btn-outline-warning { font-size: 0; padding-inline: .5rem; } /* Zuruecksetzen nur als X */
html.ae-handy .splan-search-form .btn-outline-warning .bi,
html.ae-handy .splan-tool-search .btn-outline-warning .bi { font-size: 1rem; margin-right: 0 !important; }
html.ae-handy .splan-hits { flex-wrap: nowrap !important; } /* !important gegen Bootstrap .flex-wrap: Knopf | Chips | Knopf in EINER Zeile */
html.ae-handy .splan-hits > .btn { flex: 0 0 auto; }
html.ae-handy .splan-hitchips { flex-wrap: nowrap !important; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; min-width: 0; }
html.ae-handy .splan-hitchips::-webkit-scrollbar { display: none; }
html.ae-handy .splan-hitchips .badge { white-space: nowrap; padding-block: .45rem; }
html.ae-handy .splan-pagearrow { width: 36px; height: 36px; opacity: .55; }
html.ae-handy .splan-pagearrow .bi { font-size: 1.1rem !important; }
html.ae-handy #splanViewport { touch-action: none; overscroll-behavior: contain; }
html.ae-handy .splan-hit { pointer-events: auto; cursor: pointer; }

/* Statistik am PC: Tabellen direkt in einer Karte (ohne card-body) bekommen seitlichen
   Innenabstand - die erste/letzte Spalte klebte sonst am Kartenrand (Umsatz, Lager, Kunden ...) */
html:not(.ae-handy) .statistik-page .card > .table-responsive > .table > * > tr > :first-child { padding-left: 1rem; }
html:not(.ae-handy) .statistik-page .card > .table-responsive > .table > * > tr > :last-child { padding-right: 1rem; }
/* Statistik am Handy (User-Entscheidung 2026-10-02: Stapel-/Kartendarstellung NUR innerhalb
   der Statistik - Wrapper .statistik-page aus StatistikController::render(), nie projektweit):
   - Kopf untereinander, Zeitraum-Filter eingeklappt hinter einem Knopf (_filter_form.php,
     Bootstrap collapse; am PC immer offen), Schnellwahl + Ansicht-Kacheln in EINER wischbaren Zeile
   - Kennzahl-Kacheln kleiner, Diagramme 200 px (Kurzformat der Achse: assets/js/statistik.js)
   - table.statistik-stack (ui_table-Option stack bzw. von Hand mit data-label je td): thead aus,
     jede Zeile eine Karte, jede Zelle "Label: Wert" aus data-label, erste Zelle = Kopf der Karte,
     Summenzeile (tfoot) eigene Karte; Sortieren ueber ein Select (statistik.js)
   - Spaltenwaehler: Haekchen bleiben, Griffe handy-hide (UiTable.php), Menue max. 90vw */
html:not(.ae-handy) .statistik-zeitraum-collapse { display: block !important; height: auto !important; }
html.ae-handy .statistik-page .statistik-head { flex-direction: column; align-items: stretch !important; }
html.ae-handy .statistik-page .statistik-head h1 { font-size: 1.35rem; }
html.ae-handy .statistik-page .statistik-head-side { align-items: flex-start !important; }
html.ae-handy .statistik-page .statistik-head-side .text-end { text-align: left !important; }
html.ae-handy .statistik-page .statistik-zeitraum-collapse .card { margin-top: .5rem; }
html.ae-handy .statistik-page .statistik-filter .form-control,
html.ae-handy .statistik-page .statistik-filter .form-select { min-width: 0; }
html.ae-handy .statistik-page .statistik-filter [type="submit"] { width: 100%; }
html.ae-handy .statistik-page .statistik-ranges-col { order: -1; }
html.ae-handy .statistik-page .statistik-ranges { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
html.ae-handy .statistik-page .statistik-ranges::-webkit-scrollbar { display: none; }
html.ae-handy .statistik-page .statistik-ranges .btn { white-space: nowrap; flex: 0 0 auto; }
/* Kennzahl-Kacheln (Spalte > .card mit .fs-3 in allen Views, auch $viewTile und a.card der
   Kunden-Analyse): kleinere Schrift, Betraege duerfen umbrechen */
html.ae-handy .statistik-page .row > [class*="col-"] > .card .fs-3 { font-size: 1.25rem !important; overflow-wrap: anywhere; }
html.ae-handy .statistik-page .row > [class*="col-"] > .card > .card-body { padding: .6rem .75rem; }
/* Ansicht-Kacheln ($viewTile bzw. Kunden-Analyse, Umschalter ?ansicht=) in EINER wischbaren Zeile */
html.ae-handy .statistik-page .row:has(> [class*="col-"] > .statistik-view-tile) { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; scroll-snap-type: x mandatory; }
html.ae-handy .statistik-page .row:has(> [class*="col-"] > .statistik-view-tile)::-webkit-scrollbar { display: none; }
html.ae-handy .statistik-page .row:has(> [class*="col-"] > .statistik-view-tile) > [class*="col-"] { flex: 0 0 auto; width: 70%; max-width: 70%; scroll-snap-align: start; }
/* Diagramme (vorher Media-Query 575.98 px im Statistik-Block - jetzt nur noch hier) */
html.ae-handy .statistik-page .statistik-chart { height: 200px !important; }
/* Tabellen als Stapel */
html.ae-handy .statistik-page table.statistik-stack { display: block; width: 100% !important; table-layout: auto !important; }
html.ae-handy .statistik-page table.statistik-stack > thead { display: none; }
html.ae-handy .statistik-page table.statistik-stack > tbody,
html.ae-handy .statistik-page table.statistik-stack > tfoot { display: block; }
html.ae-handy .statistik-page table.statistik-stack > * > tr { display: block; margin: .5rem .75rem; padding: .35rem .6rem; border: 1px solid var(--bs-border-color); border-radius: .5rem; background: var(--bs-body-bg); }
html.ae-handy .statistik-page table.statistik-stack > tfoot > tr { background: var(--bs-tertiary-bg); }
html.ae-handy .statistik-page table.statistik-stack > * > tr > td { display: flex; justify-content: space-between; align-items: baseline; gap: .75rem; width: auto !important; padding: .15rem 0; border: 0; box-shadow: none; background: transparent; white-space: normal; }
html.ae-handy .statistik-page table.statistik-stack > * > tr > td::before { content: attr(data-label); flex: 0 0 auto; max-width: 45%; color: var(--bs-secondary-color); font: 400 .8rem var(--bs-body-font-family); }
html.ae-handy .statistik-page table.statistik-stack > * > tr > td:first-child { display: block; font-weight: 600; font-size: 1.05rem; padding-bottom: .3rem; margin-bottom: .2rem; border-bottom: 1px solid var(--bs-border-color); text-align: left !important; }
html.ae-handy .statistik-page table.statistik-stack > * > tr > td:first-child::before { display: inline; margin-right: .4rem; }
html.ae-handy .statistik-page table.statistik-stack > * > tr > td[colspan] { display: block; text-align: center; }
html.ae-handy .statistik-page table.statistik-stack > * > tr > td:not([data-label])::before,
html.ae-handy .statistik-page table.statistik-stack > * > tr > td[data-label=""]::before,
html.ae-handy .statistik-page table.statistik-stack > * > tr > td[colspan]::before { display: none; }
html.ae-handy .statistik-page .statistik-sort .form-select { min-width: 0; }
html.ae-handy .statistik-page .ui-table-chooser-menu { max-width: 90vw; }

/* Kundendienst vor Ort (kdv/services/_einsatz.php, _checkliste.php, teile.php,
   assets/js/kdv-einsatz.js): Checkliste mit Pflichtantwort, Teileliste,
   feste Erledigt-Leiste. Zustand haengt an data-state / data-status. */
.kdv-task[data-state="done"] .kdv-task-text         { text-decoration: line-through; color: var(--bs-secondary-color); }
.kdv-task[data-state="not_needed"] .kdv-task-text   { color: var(--bs-secondary-color); }
.kdv-task[data-state="not_possible"] .kdv-task-text { color: var(--bs-warning-text-emphasis); }
.kdv-task-btns .btn { font-size: .85rem; padding: .55rem .25rem; white-space: nowrap; } /* drei Antworten in einer Zeile bei 390 px */
.kdv-part-editable { cursor: pointer; }
.kdv-part[data-status="collected"] .kdv-part-number,
.kdv-part[data-status="collected"] .kdv-part-name { color: var(--bs-secondary-color); text-decoration: line-through; }
.kdv-part[data-status="missing"] .kdv-part-missing { background: var(--bs-warning); border-color: var(--bs-warning); color: #000; }
.kdv-einsatz-bar {
    position: sticky; bottom: 0; z-index: 5;
    background: var(--dm-bg-ffffff, #fff);
    border-top: 1px solid var(--bs-border-color);
    padding: .5rem 0 calc(.5rem + env(safe-area-inset-bottom, 0px));
}
/* Im Modal: ein klebendes Element haelt den Innenabstand seines Scroll-Containers
   ein (Chrome/Safari) - mit dem unteren Innenabstand des Modal-Koerpers stuende die
   Leiste 16 px zu hoch. Deshalb faellt er weg, sobald der Einsatz drin ist. */
.modal-body:has(.kdv-einsatz-wrap) { padding-bottom: 0; }
.modal-body .kdv-einsatz-bar  { margin-inline: -1rem; padding-inline: 1rem; }

/* Drucken aus dem PDF-Fenster (#kdvPdfModal, kdv-einsatz.js setzt body.kdv-pdf-printing):
   nur die gerenderten Seiten kommen aufs Papier, eine Seite je Blatt. */
@media print {
    body.kdv-pdf-printing > *:not(#kdvPdfModal) { display: none !important; }
    body.kdv-pdf-printing #kdvPdfModal,
    body.kdv-pdf-printing #kdvPdfModal .modal-dialog,
    body.kdv-pdf-printing #kdvPdfModal .modal-content,
    body.kdv-pdf-printing #kdvPdfModal .modal-body {
        position: static !important; display: block !important; overflow: visible !important;
        height: auto !important; max-height: none !important; width: auto !important; max-width: none !important;
        margin: 0 !important; padding: 0 !important; border: 0 !important; box-shadow: none !important;
        transform: none !important; background: #fff !important;
    }
    body.kdv-pdf-printing #kdvPdfModal .modal-header { display: none !important; }
    body.kdv-pdf-printing #kdvPdfPages canvas { display: block; width: 100% !important; height: auto !important; break-after: page; page-break-after: always; }
    body.kdv-pdf-printing #kdvPdfPages canvas:last-child { break-after: auto; page-break-after: auto; }
}

/* --- Artikel-Thumbnails (article_thumb-Helper) --- */
.article-thumb {
    object-fit: cover;
    border-radius: 0.375rem;
    border: 1px solid var(--dm-bd-dee2e6, #dee2e6);
    background: var(--dm-bg-ffffff, #fff);
    flex-shrink: 0;
}

/* Platz fuer die vertikale Scrollleiste IMMER reservieren: Seiten mit und
   ohne Scrollleiste haben sonst unterschiedlich breite Viewports, und der
   zentrierte Inhalt springt um ~8px (User-Befund 2026-09-03, Rechnungen). */
html { scrollbar-gutter: stable; }
/* Bootstrap-Modals gleichen die beim Oeffnen ausgeblendete Scrollleiste per
   inline padding-right (body, .sticky-top/.fixed-*) aus. Mit reserviertem
   Gutter wuerde das den Inhalt DOPPELT verschieben (Befund: Auftrags-Modal
   ueber der Liste) - Ausgleich daher neutralisieren (!important schlaegt
   Bootstraps Inline-Style). */
body.modal-open,
.modal-open .sticky-top,
.modal-open .fixed-top,
.modal-open .fixed-bottom,
.modal-open .is-fixed { padding-right: 0 !important; }
.modal-open .sticky-top { margin-right: 0 !important; }

/* Navbar: Modulname als Orientierung hinter dem Brand "Startseite" */
.navbar .navbar-module-label {
    /* Navbar-Textfarbe des jeweiligen Themes (dunkel: hell, Apple: dunkel) */
    color: var(--bs-navbar-color, rgba(255, 255, 255, .7));
    font-weight: 500;
    padding: 0;
    white-space: nowrap;
}
/* Zugeklappte Navbar (Handy/schmal): Modulname nimmt nur den Platz zwischen
   Brand und Burger und wird gekuerzt - sonst rutscht der Burger in eine
   zweite Zeile (Navbar doppelt so hoch). */
@media (max-width: 991.98px) {
    .navbar .navbar-module-label {
        flex: 1 1 0;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        margin-right: .5rem !important;
    }
}
/* Navbar (aufgeklappt): wenn Menuepunkte bei Platznot zweizeilig werden
   (Icon ueber Text), stehen Dropdowns wie "Neu"/"Admin" sonst oben am Rand -
   alle Punkte vertikal auf die Mitte ausrichten. */
@media (min-width: 992px) {
    .navbar-expand-lg .navbar-nav { align-items: center; }

    /* Icon-Breite (1em) schon VOR dem Laden der Icon-Schrift reservieren:
       layout-nav.js misst den Umbruch inline beim ersten Parsen - so stimmt
       die Messung bereits ohne geladene Glyphen (kein Umspringen danach). */
    .navbar-nav > .nav-item > .nav-link > .bi:first-child {
        display: inline-block;
        min-width: 1em;
        text-align: center;
    }

    /* Platznot (layout-nav.js setzt .nav-stacked, sobald ein Punkt umbricht):
       ALLE Punkte einheitlich Icon zentriert ueber zentriertem Text -
       gilt fuer jede Modul-Navbar, weil alle dieselbe Liste nutzen. */
    .navbar-nav.nav-stacked > .nav-item > .nav-link {
        text-align: center;
        line-height: 1.2;
        padding-top: .3rem;
        padding-bottom: .3rem;
    }
    .navbar-nav.nav-stacked > .nav-item > .nav-link > .bi:first-child {
        display: block;
        margin: 0 auto .15rem;
        font-size: 1.2rem;
        line-height: 1;
    }

    /* Reicht auch das Stapeln nicht (Leiste breiter als das Fenster, Audit
       R4-PC-1), setzt layout-nav.js an der Navbar stufenweise:
       nav-tight     Modulname hinter dem Brand + Benutzername weg (Tooltip),
       nav-iconsonly Modulpunkte nur als Symbol - der Text bleibt im DOM
                     (Screenreader) und steht im Tooltip,
       nav-wrap      letzte Stufe: umbrechen statt seitlich scrollen. */
    .navbar.nav-tight .navbar-module-label,
    .navbar.nav-tight .nav-user-name { display: none; }
    .navbar { --nav-icon-fs: 1.25rem; }
    body.font-size-large .navbar  { --nav-icon-fs: 1.45rem; }
    body.font-size-xlarge .navbar { --nav-icon-fs: 1.7rem; }
    .navbar.nav-iconsonly #moduleNav > .nav-item > .nav-link:has(> .bi:first-child) {
        font-size: 0;
        padding-left: .45rem;
        padding-right: .45rem;
    }
    .navbar.nav-iconsonly #moduleNav > .nav-item > .nav-link > .bi:first-child {
        display: inline-block;
        margin: 0;
        font-size: var(--nav-icon-fs);
        line-height: 1.5;
    }
    .navbar.nav-iconsonly #moduleNav > .nav-item > .nav-link .badge { font-size: .75rem; }
    .navbar.nav-iconsonly #moduleNav > .nav-item > .dropdown-toggle::after { font-size: 1rem; }
    .navbar.nav-wrap .navbar-collapse,
    .navbar.nav-wrap #moduleNav { flex-wrap: wrap; }
}

/* ============================================================
   Dashboard (/dashboard): Modul-Kacheln je User (s/m/l)
   4 Spalten Desktop, 2 Tablet, 1 Handy. s = 1x1, m = 2x1, l = 2x2.
   Bearbeiten-Modus (.is-editing): Griff + Groessen-Button sichtbar,
   Inhalte nicht klickbar. Kein pointer-events:none auf .sortable-drag
   (SortableJS-Merker aus dem Monteur-Board).
   ============================================================ */
/* Raster: 9 Spalten x 88px-Zeilen (StartPageService::COLS/MAX_H). --cols
   setzt start-page.js aus der Breite (Desktop mindestens 9, auf breiten
   Bildschirmen mehr Spalten a ~180px = StartPageService::COL_WIDTH; Tablet
   2; Handy 1). Jede Kachel spannt --w Spalten x --h Zeilen
   (data-w/data-h), frei ziehbar im Anpassen-Modus (Ecke unten rechts).
   Der INHALT richtet sich per Container-Query nach der Kachelgroesse:
     1 Zeile (< 150px)   .start-tile-compact  Icon + Name (+ Badge)
     ab 2 Zeilen         .start-tile-full     Kopfleiste + Kennzahlen/Aktionen
     ab 3 Zeilen         .start-list          Liste, so viele Zeilen wie passen
     ab 560px breit      .start-row-x         Zusatzspalten in Listen
     < 400px breit       Aktionen als Reihe unter den Kennzahlen
     < 300px breit       "Oeffnen" nur als Pfeil, Name darf 2-zeilig werden */
.start-grid {
    --cols: 9;
    display: grid;
    grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    grid-auto-rows: 88px;
    gap: 1rem;
}
.start-tile {
    --x: 1;
    --y: 1;
    --w: 1;
    --h: 1;
    /* feste Position im Raster (data-x/data-y); Fliesslayout s.u. */
    grid-column: var(--x) / span var(--w);
    grid-row: var(--y) / span var(--h);
    border: 0;
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    container-type: size;
    container-name: tile;
    transition: transform .15s ease, box-shadow .15s ease;
}
/* Fliesslayout (weniger als 9 Spalten, Tablet/Handy): DOM-Reihenfolge
   (= nach y/x sortiert), Breite geklemmt; kein Verschieben/Resize */
.start-grid-flow .start-tile { grid-column: span var(--w); grid-row: span var(--h); }
.start-grid-flow .start-tile-tools, .start-grid-flow .start-tile-resize { display: none !important; }
/* Verschieben: die gezogene Kachel folgt dem Zeiger (fixed), ein Platzhalter
   zeigt das Ziel im Raster (blau = frei, rot = belegt) */
.start-tile.is-dragging {
    position: fixed;
    z-index: 1000;
    pointer-events: none;
    opacity: .92;
    transition: none;
    box-shadow: 0 .75rem 1.5rem rgba(0,0,0,.22) !important;
}
/* Breite Bildschirme: Kachel steht eigentlich weiter rechts (bzw. ist breiter),
   als hier Spalten da sind -> nur in der Anzeige versetzt/gekuerzt (start-page.js
   layoutTiles()); dezentes Symbol mit Tooltip unten links */
.start-tile-moved {
    position: absolute;
    left: .3rem;
    bottom: .3rem;
    z-index: 5;
    width: 1.35rem;
    height: 1.35rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .7rem;
    line-height: 1;
    border-radius: 50%;
    background: var(--dm-bg-fff3cd, #fff3cd);
    color: var(--dm-fg-664d03, #664d03);
    border: 1px solid var(--dm-bd-ffe69c, #ffe69c);
    cursor: help;
}
.start-tile-placeholder {
    border: 2px dashed var(--bs-primary, #0d6efd);
    border-radius: var(--bs-card-border-radius, .375rem);
    background: rgba(13, 110, 253, .07);
}
.start-tile-placeholder.is-invalid {
    border-color: var(--bs-danger, #dc3545);
    background: rgba(220, 53, 69, .08);
}
/* Schnellsuche: das Ergebnis-Dropdown muss UEBER die Kachel hinausragen
   duerfen (overflow:hidden schnitt es ab); z-index hebt es ueber die
   Nachbar-Kacheln. */
.start-tile[data-key="suche"] { overflow: visible; z-index: 10; }
/* ... und auch der Body darf hier nicht clippen (overflow:hidden fuer die
   "safe center"-Kacheln schnitt das Ergebnis-Dropdown am Kachelende ab). */
.start-tile[data-key="suche"] .start-tile-body { overflow: visible; }
/* Urlaub: Abwesenheitsliste beim Drueberfahren als Panel UEBER den Nachbar-
   kacheln (User-Wunsch 2026-09-11, Ersatz fuer den Klapp-Banner des alten
   Dashboards). start-page.js setzt .is-peek nur, wenn die Liste nicht in die
   Kachel passt (1-zeilig oder zu viele Zeilen); das Raster bleibt stehen, der
   Inhalt loest sich absolut von der Kachel und waechst nach unten (und bei
   schmalen Kacheln nach rechts, am rechten Rasterrand nach links: .is-peek-left).
   Container-Query-Stufen gelten weiter fuer die Kachelgroesse, daher hier
   ausdruecklich: Kompakt aus, Vollstufe + Liste an, kein Ausblenden und keine Maske. */
.start-tile[data-key="urlaub"].is-peek { overflow: visible; z-index: 20; }
.start-tile[data-key="urlaub"].is-peek .start-tile-content {
    position: absolute;
    top: 0; left: 0; right: 0;
    min-height: 100%;
    min-width: min(360px, calc(100vw - 2rem));
    background: var(--bs-card-bg, var(--dm-bg-ffffff, #fff));
    border-radius: var(--bs-card-border-radius, .375rem);
    box-shadow: 0 .75rem 1.5rem rgba(0,0,0,.22);
}
.start-tile[data-key="urlaub"].is-peek.is-peek-left .start-tile-content { left: auto; right: 0; }
.start-tile.is-peek .start-tile-compact { display: none; }
.start-tile.is-peek .start-tile-full { display: flex; }
.start-tile.is-peek .start-tile-body { overflow: visible; flex: 0 0 auto; }
.start-tile.is-peek .start-list { display: block; overflow: visible; -webkit-mask-image: none; mask-image: none; }
.start-tile.is-peek .start-urlaub-toggle .bi { transform: rotate(180deg); }
/* Ueberschrift der Liste als Knopf (Touch-Toggle), optisch wie die Textzeile */
.start-urlaub-toggle { background: none; border: 0; padding: 0; text-align: left; display: inline-flex; align-items: center; gap: .3rem; }
.start-urlaub-toggle .bi { font-size: .75rem; transition: transform .15s ease; }
/* Ohne overflow:hidden clippt die Kachel die Kopfleiste nicht mehr an den
   runden Ecken - die Kopfleiste bekommt die oberen Radien daher selbst. */
/* Dropdown "Kachel einblenden": kann auf alle Modul- + Funktionskacheln
   anwachsen (>20 Eintraege) - deckeln statt aus dem Fenster laufen lassen.
   Positioniert wird es per data-bs-display="static" (dashboard/index.php). */
.start-hidden-menu { max-height: 60vh; overflow-y: auto; }
/* Abschnitte (Module / Funktionen / Statistik-Auswertungen): Trennlinie vor jeder weiteren sichtbaren Ueberschrift */
.start-hidden-menu .start-hidden-head:not([hidden]) ~ .start-hidden-head:not([hidden]) { border-top: 1px solid var(--bs-border-color); margin-top: .25rem; padding-top: .25rem; }
.start-tile-head { border-top-left-radius: var(--bs-card-border-radius, .375rem); border-top-right-radius: var(--bs-card-border-radius, .375rem); }
/* Ganze Kachel klickbar (JS, data-home) - innere Controls bleiben eigenstaendig */
.start-tile[data-home] { cursor: pointer; }
.start-tile[data-home]:hover, .start-tile-solo:hover { box-shadow: 0 .5rem 1rem rgba(0,0,0,.1) !important; }
.start-tile-content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
}
.start-tile-desktop, .start-tile-mobile { min-height: 0; }

/* ---- Stufe 1 Zeile: Icon + Name in einer Reihe, ganze Kachel ist der Link ---- */
.start-tile-compact {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    padding: .5rem 1rem;
    text-decoration: none;
    color: inherit;
    font-weight: 600;
    font-size: 1rem;
    min-width: 0;
}
.start-tile-compact > .bi:first-child { font-size: 2.1rem; color: var(--bs-primary, #0d6efd); line-height: 1; flex: none; }
.start-tile-compact .start-tile-label { min-width: 0; line-height: 1.2; hyphens: auto; overflow-wrap: anywhere; }
.start-tile-compact .badge { flex: none; }
/* Mehrere Zaehler (tiles/_badges.php, z.B. Urlaub abwesend/demnaechst/Antraege):
   Pillen duerfen umbrechen, bei Platzmangel rutscht die Gruppe unter Icon + Name */
.start-tile-compact { flex-wrap: wrap; row-gap: .3rem; }
.start-tile-badges { display: inline-flex; flex-wrap: wrap; justify-content: center; gap: .25rem; flex: 0 1 auto; }
a.start-tile-compact:hover { color: var(--bs-primary, #0d6efd); }
/* Zeiterfassung 1-zeilig: Symbol + Name (Link) links, Art/Ticker, Start/Stop rechts */
.start-tile-compact-stempel { justify-content: flex-start; gap: .5rem; }
.start-tile-compact-link { display: flex; align-items: center; gap: .5rem; text-decoration: none; color: inherit; min-width: 0; }
.start-tile-compact-link .bi { font-size: 2.1rem; line-height: 1; }
.start-tile-compact-link:hover { color: var(--bs-primary, #0d6efd); }
.start-stempel-badge { font-weight: 600; white-space: nowrap; }
select.start-stempel-type { width: auto; max-width: 9rem; }

/* ---- Stufe ab 2 Zeilen: Kopfleiste (sichtbarer Modul-Link) + Body ---- */
.start-tile-full { display: none; flex: 1 1 auto; flex-direction: column; min-height: 0; min-width: 0; }
.start-tile-head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .55rem .75rem .55rem 1rem;
    font-weight: 600;
    text-decoration: none;
    min-width: 0;
    color: var(--bs-primary, #0d6efd);
    background: rgba(13, 110, 253, .13);
    border-bottom: 1px solid rgba(13, 110, 253, .20);
    transition: background .12s, color .12s;
}
.start-tile-head > .bi:first-child { font-size: 1.25rem; line-height: 1; flex: none; }
.start-tile-head .start-tile-label {
    min-width: 0;
    line-height: 1.2;
    hyphens: auto;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.start-tile-open {
    margin-left: auto;
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-size: .78rem;
    padding: .15rem .5rem .15rem .65rem;
    border-radius: 999px;
    background: var(--dm-bg-ffffff, #fff);
    border: 1px solid var(--bs-primary, #0d6efd);
    white-space: nowrap;
}
a.start-tile-head:hover { background: var(--bs-primary, #0d6efd); color: #fff; }
a.start-tile-head:hover .start-tile-open { background: transparent; border-color: rgba(255,255,255,.7); color: #fff; }
.start-tile-head-static { cursor: default; }
.start-tile-body {
    padding: .75rem 1rem 1rem;
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    /* Fuellt der Inhalt die Kachel nicht, verteilt sich der Rest oben+unten;
       "safe": laeuft er ueber, beginnt er oben und wird unten abgeschnitten
       (statt in die Kopfleiste zu ragen) */
    display: flex;
    flex-direction: column;
    justify-content: center;
    justify-content: safe center;
    overflow: hidden;
}
.start-kpi { text-decoration: none; color: inherit; min-width: 0; }
/* Grosse Kennzahlen in ALLEN Kacheln ab 2 Zeilen (User-Feedback: Platz nutzen) */
.start-kpi-num { font-size: 2.5rem; font-weight: 700; line-height: 1.1; white-space: nowrap; }
/* Aktions-Spalte rechts neben den Kennzahlen (schmal: Reihe darunter) */
.start-tile-actions { margin-left: auto; display: flex; flex-direction: column; gap: .5rem; align-items: stretch; }
/* Liste: ab 3 Zeilen; zeigt so viele Zeilen wie passen (Rest ausgeblendet) */
.start-list {
    display: none;
    font-size: .9rem;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(#000 calc(100% - 16px), transparent);
            mask-image: linear-gradient(#000 calc(100% - 16px), transparent);
}
/* Listen, die der Hauptinhalt der Kachel sind (Schaltplaene): schon ab 2 Zeilen */
.start-list-main { display: block; }
.start-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: .5rem;
    padding: .3rem 0;
    border-top: 1px solid rgba(0,0,0,.075);
    text-decoration: none;
    color: inherit;
    min-width: 0;
}
a.start-row:hover { color: var(--bs-primary, #0d6efd); }
.start-row > :first-child { min-width: 0; }
.start-row-x { display: none; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dm-fg-6c757d, #6c757d); }

/* Schnellsuche: nur EINE Stufe (Suchfeld existiert nur einmal); bei 1 Zeile
   bleiben Suchfeld + Suchen, Kopfleiste und Schnellzugriffe verschwinden */
.start-tile-always { display: flex; }
@container tile (max-height: 149px) {
    .start-tile-always .start-tile-head, .start-tile-always .start-suche-more { display: none !important; }
    .start-tile-always .start-tile-body { padding: .5rem 1rem; justify-content: center; }
}

/* Auftragszeit-Banner: so breit wie die belegten Raster-Spalten (--used-cols
   aus index.php, --grid-cols/--used-cols setzt start-page.js), schliesst rechts mit den Kacheln ab; im Fliesslayout
   (Tablet/Handy) volle Breite */
@media (min-width: 992px) {
    .start-banner { width: calc((100% - (var(--grid-cols, 9) - 1) * 1rem) / var(--grid-cols, 9) * var(--used-cols, 9) + (var(--used-cols, 9) - 1) * 1rem); }
}

/* Kompakte Kennzahlen in EINER Zeile (Urlaub: Zahl + Text, Button rechts) -
   fuer Kacheln, deren Hauptinhalt die Liste ist */
.start-tile-body-top { justify-content: flex-start; }
.start-kpi-row { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem 1.1rem; }
.start-kpi-inline { display: inline-flex; align-items: baseline; gap: .35rem; text-decoration: none; color: inherit; white-space: nowrap; }
.start-kpi-inline b { font-size: 1.5rem; font-weight: 700; line-height: 1; }
.start-kpi-inline span { color: var(--dm-fg-6c757d, #6c757d); font-size: .85rem; }
.start-kpi-inline.admin-marked { padding: .15rem .5rem; }
.start-kpi-inline:hover span { color: var(--bs-primary, #0d6efd); }

/* ---- Container-Queries: Inhalt folgt der Kachelgroesse ---- */
@container tile (min-height: 150px) {
    .start-tile-compact { display: none; }
    .start-tile-full { display: flex; }
    /* Kacheln ohne Partial (Lager/Archiv/Kasse): Icon gross ueber dem Namen */
    .start-tile-solo .start-tile-compact { display: flex; flex-direction: column; gap: .6rem; font-size: 1.1rem; padding: 1rem .5rem; text-align: center; }
    .start-tile-solo .start-tile-compact > .bi:first-child { font-size: 3.4rem; }
}
@container tile (min-height: 270px) {
    .start-list { display: block; }
    .start-tile-body { justify-content: flex-start; }
}
@container tile (min-width: 560px) {
    /* Jede Zeile ist ein eigenes Grid: Namensspalte fest (nicht fr), sonst
       verschiebt die unterschiedlich breite Datumsspalte die Spalten je Zeile */
    .start-row:has(.start-row-x) { grid-template-columns: 42% auto minmax(0, 1fr); }
    .start-row-x { display: block; }
}
/* Statistik: drei Kennzahlen + Knopf in EINER Zeile - ein Umbruch wuerde in
   der M-Hoehe abgeschnitten; darum kleinere Zahlen und Icon-Knopf */
@container tile (max-width: 700px) {
    .start-stat-kpis { gap: .5rem 1.25rem !important; }
    .start-stat-kpis .start-kpi-num { font-size: 2rem; }
    .start-stat-kpis .start-tile-actions .btn { font-size: 0; padding: .4rem .55rem; }
    .start-stat-kpis .start-tile-actions .btn .bi { font-size: 1rem; margin: 0 !important; }
}
@container tile (max-width: 400px) {
    .start-tile-actions { margin-left: 0; width: 100%; flex-direction: row; flex-wrap: wrap; }
    .start-tile-actions > * { flex: 1 1 auto; }
    .start-kpi-num { font-size: 2rem; }
}
@container tile (max-width: 300px) {
    .start-tile-head { padding-left: .75rem; gap: .4rem; }
    .start-tile-open { font-size: 0; padding: .2rem .35rem; gap: 0; }
    .start-tile-open .bi { font-size: .9rem; }
    .start-stempel-type { display: none; }
    .start-tile-compact-stempel .start-tile-label { display: none; }
}
@container tile (max-width: 260px) {
    .start-tile-compact { flex-direction: column; gap: .15rem; padding: .35rem .6rem; font-size: .9rem; text-align: center; }
    .start-tile-compact > .bi:first-child { font-size: 1.7rem; }
    .start-tile-compact .badge { font-size: .68rem; }
}

/* Sehr schmale Kachel (1 Spalte): keine Aktionsknoepfe, kleinere Kennzahlen,
   engere Abstaende - nur das Wichtigste passt */
@container tile (max-width: 200px) {
    .start-tile-actions { display: none !important; }
    .start-kpi-num { font-size: 1.6rem; }
    .start-kpi .text-muted { font-size: .8rem; white-space: normal; line-height: 1.15; }
    .start-tile-body { padding: .5rem .75rem .75rem; }
    .start-tile-body > .d-flex.gap-4 { gap: .5rem .9rem !important; }
}

/* Kopf der Beleg-Seiten (Rechnung/Angebot/Lieferschein): erste Zeile links
   Zurueck/Neu, rechts Kundenkarte/Drucken/PDF; darunter in EIGENER Zeile die
   Belegnummer (prominent) mit allen Kennzeichen - die haben so die volle
   Breite und druecken die Knoepfe nie in die naechste Zeile (User-Vorgabe
   2026-09-30). */
.doc-head-number { font-family: var(--bs-font-monospace); font-size: 1.5rem; font-weight: 600; line-height: 1.2; }

/* Knopf-Reihe unter den Kennzahlen (Anlege-Knoepfe der Auftrags-/Beleg-
   Kacheln, Suche: Schnellzugriffe). Die M-Hoehe laesst genau EINE Zeile zu
   (Umbruch wuerde abgeschnitten), darum werden die Knoepfe erst dann zu
   Icon-Knoepfen (title = Tooltip), wenn die Beschriftungen wirklich nicht
   mehr in die Zeile passen - Icon-only ist Notloesung, nicht Regelfall
   (User-Vorgabe 2026-09-04). Schwelle nach Knopfzahl: start-actions-3
   (drei kurze Anlege-Knoepfe, ~385px) / start-actions-2 (~280px); Reihen
   ohne Zaehl-Klasse (Suche) wie bisher 480px. Ein Zusatz-Knopf mit
   start-actions-opt (Auftrag: "Meine Aufträge", auch ueber die Liste
   erreichbar) faellt VOR den Beschriftungen weg. Sehr schmal ganz weg.
   Schwellen in em (Basis 16px: 30em=480px, 27.5em=440px, 25em=400px,
   18.125em=290px, 12.5em=200px): em in @container bezieht sich auf die
   Schrift der Kachel, damit wachsen die Schwellen mit der Einstellung
   "Schrift gross" (body 1.25rem) mit - bei festen px brachen die breiteren
   Knoepfe in eine zweite Zeile um, die die Kachelhoehe abschneidet. */
@container tile (max-width: 30em) {
    .start-tile-actions-row:not(.start-actions-2):not(.start-actions-3) .btn { font-size: 0; padding: .4rem .55rem; }
    .start-tile-actions-row:not(.start-actions-2):not(.start-actions-3) .btn .bi { font-size: 1rem; margin: 0 !important; }
}
@container tile (max-width: 27.5em) {
    .start-tile-actions-row .start-actions-opt { display: none !important; }
}
@container tile (max-width: 25em) {
    .start-actions-3 .btn { font-size: 0; padding: .4rem .55rem; }
    .start-actions-3 .btn .bi { font-size: 1rem; margin: 0 !important; }
}
@container tile (max-width: 18.125em) {
    .start-actions-2 .btn { font-size: 0; padding: .4rem .55rem; }
    .start-actions-2 .btn .bi { font-size: 1rem; margin: 0 !important; }
}
@container tile (max-width: 12.5em) {
    .start-tile-actions-row { display: none !important; }
}

/* Kennzahlen-Zeile (Urlaub): der kleine Icon-Button bleibt auch schmal in
   der Zeile - keine eigene Zeile, die der Liste den Platz nimmt */
@container tile (max-width: 400px) {
    .start-kpi-row .start-tile-actions { margin-left: auto; width: auto; flex-direction: row; }
}

/* ---- Handy (< 576px) im PC-Layout (Fliesslayout): eine Spalte, Hoehe nach Inhalt.
   Das eigene Handy-Layout (.start-grid-mobile) hat feste Zeilen, siehe unten ---- */
@media (max-width: 575.98px) {
    .start-grid:not(.start-grid-mobile) { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
    .start-grid:not(.start-grid-mobile) .start-tile { grid-column: span 1; grid-row: span 1; container-type: inline-size; min-height: 88px; }
    .start-grid:not(.start-grid-mobile) .start-tile-resize { display: none !important; }
    /* Keine feste Hoehe -> Hoehen-Queries greifen nicht: Stufe nach der
       GESPEICHERTEN Zeilenzahl (data-h), sonst faellt alles auf kompakt zurueck */
    .start-grid:not(.start-grid-mobile) .start-tile:not([data-h="1"]) .start-tile-compact { display: none; }
    .start-grid:not(.start-grid-mobile) .start-tile:not([data-h="1"]) .start-tile-full { display: flex; }
    .start-grid:not(.start-grid-mobile) .start-tile[data-h="1"] .start-tile-always .start-tile-head, .start-grid:not(.start-grid-mobile) .start-tile[data-h="1"] .start-tile-always .start-suche-more { display: none !important; }
    /* Kacheln ohne Partial (Lager/Archiv/Kasse): am Handy IMMER Icon gross
       ueber dem Namen - unabhaengig von der Desktop-Hoehe, sonst sind sie
       kleiner als die Modul-Kacheln mit Handy-Block (User-Meldung 2026-09-04) */
    .start-grid:not(.start-grid-mobile) .start-tile.start-tile-solo .start-tile-compact { display: flex; flex-direction: column; gap: .6rem; font-size: 1.1rem; padding: 1rem .5rem; }
    .start-grid:not(.start-grid-mobile) .start-tile.start-tile-solo .start-tile-compact > .bi:first-child { font-size: 3.4rem; }
    .start-grid:not(.start-grid-mobile) .start-tile.start-tile-solo .start-tile-compact .start-tile-label { line-height: 1.5; }   /* = Handy-Block, gleiche Kachelhoehe */
    .start-grid:not(.start-grid-mobile) .start-tile[data-h="3"] .start-list, .start-grid:not(.start-grid-mobile) .start-tile[data-h="4"] .start-list,
    .start-grid:not(.start-grid-mobile) .start-tile[data-h="5"] .start-list, .start-grid:not(.start-grid-mobile) .start-tile[data-h="6"] .start-list { display: block; max-height: 240px; }
}

/* ---- Handy-Layout (eigenes Layout je User, User-Vorgabe 2026-09-23):
   2 Spalten, klein = halbe Breite, gross = volle Breite; Reihenfolge = DOM,
   "dense" fuellt Luecken neben einzelnen kleinen Kacheln. HOEHE NACH INHALT
   (feste 88px-Zeilen schnitten Stop-Knopf, Zaehler und lange Namen ab): nur
   Breiten-Container, die Stufe kommt aus der Groesse - klein = kompakt,
   gross = Kopfleiste + Inhalt, Liste ab data-h 3, data-h 1 = ohne Kopfleiste.
   Anpassen: Pfeile / klein-gross / Farbe / Ausblenden, kein Ziehen ---- */
.start-grid.start-grid-mobile {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: auto;
    grid-auto-flow: row dense;
    gap: .75rem;
}
.start-grid-mobile .start-tile { grid-column: span var(--w); grid-row: auto; container-type: inline-size; min-height: 88px; }
.start-grid-mobile .start-tile[data-w="2"]:not(.start-tile-solo):not([data-h="1"]) .start-tile-compact { display: none; }
.start-grid-mobile .start-tile[data-w="2"]:not([data-h="1"]) .start-tile-full { display: flex; }
.start-grid-mobile .start-tile[data-h="1"] .start-tile-always .start-tile-head,
.start-grid-mobile .start-tile[data-h="1"] .start-tile-always .start-suche-more { display: none !important; }
.start-grid-mobile .start-tile[data-w="2"]:not([data-h="1"]):not([data-h="2"]) .start-list { display: block; max-height: 240px; }
.start-grid-mobile .start-tile-body { overflow: visible; }
.start-grid-mobile .start-tile-resize { display: none !important; }
/* fuenf Werkzeuge muessen auch in eine halbe Handy-Breite passen */
.start-grid-mobile .start-tile-tools { left: .3rem; right: .3rem; top: .3rem; justify-content: flex-end; flex-wrap: wrap; gap: .2rem; }
.start-grid-mobile .start-tile-tools .btn { padding: .1rem .35rem; font-size: .8rem; }
/* Anpassen-Modus: Werkzeuge als eigene Zeile UEBER dem Inhalt (lagen sonst auf
   Symbolen und dem Oeffnen-Knopf); reine Optik, Reihenfolge/Groesse unberuehrt */
.start-grid-mobile.is-editing .start-tile-tools { position: static; padding: .3rem .3rem 0; }
/* Handy-Layout am PC einrichten (/dashboard?geraet=handy): Handy-Rahmen */
.start-phone-frame {
    max-width: 400px;
    margin: 0 auto;
    padding: 1rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 1.75rem;
    box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.08);
}
/* Handy-Block (start-tile-mobile): Icon gross ueber dem Namen, ganze Kachel Link */
.start-tile-link {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    padding: 1rem .5rem;
    text-align: center;
    text-decoration: none;
    color: inherit;
    font-weight: 600;
    font-size: 1.1rem;
}
.start-tile-link i { font-size: 3.4rem; color: var(--bs-primary, #0d6efd); line-height: 1; }
.start-tile-link:hover { color: var(--bs-primary, #0d6efd); }
/* Urlaub am Handy: eigene Zeile unter dem Link klappt die Abwesenheitsliste auf */
.start-urlaub-mobile-toggle { background: none; border: 0; border-top: 1px solid var(--bs-border-color); padding: .6rem 1rem; width: 100%; display: flex; align-items: center; justify-content: center; gap: .3rem; }
.start-urlaub-mobile-toggle .bi { font-size: .75rem; transition: transform .15s ease; }
.start-urlaub-mobile-toggle:not(.collapsed) .bi { transform: rotate(180deg); }
.start-urlaub-mobile-list { padding: 0 1rem .75rem; }

/* ---- Bearbeiten-Modus: Verschieben-Griff + Resize-Ecke ---- */
.start-tile-tools {
    display: none;
    position: absolute;
    top: .4rem;
    right: .4rem;
    gap: .25rem;
    z-index: 4;
}
.start-tile-tools .btn { background: var(--dm-bg-ffffff, #fff); }
.start-tile-hide { line-height: 1; }
.start-tile-handle { cursor: grab; touch-action: none; }   /* sonst scrollt das Tablet statt zu ziehen */
.start-tile-resize {
    display: none;
    position: absolute;
    right: 0;
    bottom: 0;
    width: 28px;
    height: 28px;
    z-index: 4;
    cursor: nwse-resize;
    color: var(--bs-primary, #0d6efd);
    touch-action: none;
}
.start-tile-resize::before {
    content: "";
    position: absolute;
    right: 5px;
    bottom: 5px;
    width: 14px;
    height: 14px;
    background: linear-gradient(135deg, transparent 0 50%, currentColor 50% 60%, transparent 60% 70%, currentColor 70% 80%, transparent 80% 90%, currentColor 90%);
}
.start-tile-size-badge {
    display: none;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 5;
    padding: .3rem .7rem;
    border-radius: .4rem;
    background: #212529;
    color: #fff;
    font-weight: 600;
    font-size: 1.05rem;
    pointer-events: none;
    font-variant-numeric: tabular-nums;
}
.start-tile.is-resizing { z-index: 6; transition: none; box-shadow: 0 .5rem 1.25rem rgba(0,0,0,.18) !important; }
.start-tile.is-resizing .start-tile-size-badge { display: block; }
.start-grid.is-editing .start-tile-tools { display: flex; }
.start-grid.is-editing .start-tile-resize { display: block; }
.start-grid.is-editing .start-tile-content { pointer-events: none; opacity: .75; }
.start-grid.is-editing .start-tile {
    outline: 2px dashed rgba(13, 110, 253, .45);
    outline-offset: -2px;
}
.start-tile-ghost { opacity: .35; }

/* ---- Zahlen verdecken je Kachel (data-conceal, StartPageService::concealed(),
   User-Vorgabe 2026-10-20: an fremden PCs soll nicht jeder die Betraege sehen):
   ALLE Zahlen der Kachel unscharf - Kennzahlen, Trend-Prozente, Zaehler im
   Label, Betraege/Werte der Listenzeilen, Zaehler-Pillen der 1-zeiligen Kachel.
   .is-revealed setzt start-page.js nach 0,5 s Verweilen der Maus (Handy: Tippen). ---- */
.start-tile[data-conceal] .start-kpi-num,
.start-tile[data-conceal] .start-kpi .text-muted > span,
.start-tile[data-conceal] .start-kpi-inline b,
.start-tile[data-conceal] .start-row > .text-nowrap,
.start-tile[data-conceal] .start-row > .font-monospace,
.start-tile[data-conceal] .start-tile-badges .badge {
    filter: blur(7px);
    user-select: none;
    transition: filter .2s ease;
}
.start-tile[data-conceal].is-revealed .start-kpi-num,
.start-tile[data-conceal].is-revealed .start-kpi .text-muted > span,
.start-tile[data-conceal].is-revealed .start-kpi-inline b,
.start-tile[data-conceal].is-revealed .start-row > .text-nowrap,
.start-tile[data-conceal].is-revealed .start-row > .font-monospace,
.start-tile[data-conceal].is-revealed .start-tile-badges .badge {
    filter: none;
    user-select: auto;
}
.start-conceal-hint { display: none; }
.start-tile[data-conceal] .start-tile-head .start-conceal-hint { display: inline-block; flex: none; font-size: .95rem; opacity: .65; }
.start-tile[data-conceal].is-revealed .start-tile-head .start-conceal-hint { opacity: .3; }
.start-tile[data-conceal] .start-tile-conceal { color: var(--bs-primary, #0d6efd); border-color: var(--bs-primary, #0d6efd); }

/* ---- Kachelfarbe je User (data-color + CSS-Vars aus StartPageService::colorStyle(),
   User-Wunsch 2026-09-08): 1-zeilig/Solo = Vollflaeche in der Farbe (wie die
   alten gruenen/blauen Dashboard-Kacheln), ab 2 Zeilen = Kopfleiste in der Farbe
   + Body leicht getoent. Zeiterfassung 1-zeilig (Select/Buttons) nur getoent. ---- */
.start-tile[data-color] .start-tile-compact,
.start-tile[data-color] .start-tile-link { background: var(--tile-color); color: var(--tile-fg); }
.start-tile[data-color] .start-tile-compact > .bi:first-child,
.start-tile[data-color] .start-tile-link i,
.start-tile[data-color] a.start-tile-compact:hover,
.start-tile[data-color] .start-tile-link:hover { color: var(--tile-fg); }
.start-tile[data-color] a.start-tile-compact:hover,
.start-tile[data-color] .start-tile-link:hover { filter: brightness(.92); }
.start-tile[data-color] .start-tile-compact-stempel { background: rgba(var(--tile-rgb), .12); color: inherit; }
.start-tile[data-color] .start-tile-compact-stempel .start-tile-compact-link { color: var(--tile-color); }
.start-tile[data-color] .start-tile-head { background: var(--tile-color); color: var(--tile-fg); border-bottom-color: rgba(0,0,0,.12); }
.start-tile[data-color] .start-tile-open { background: transparent; border-color: var(--tile-fg); color: var(--tile-fg); }
.start-tile[data-color] a.start-tile-head:hover { background: var(--tile-color); color: var(--tile-fg); filter: brightness(.9); }
.start-tile[data-color] .start-tile-body { background: rgba(var(--tile-rgb), .07); }
/* Palette (Anpassen-Modus): EIN Menue fuer alle Kacheln, start-page.js
   positioniert es unter dem Paletten-Knopf (fixed, ausserhalb der clippenden Kachel) */
.start-color-menu {
    position: fixed;
    z-index: 1060;
    padding: .6rem;
    background: var(--dm-bg-ffffff, #fff);
    border: 1px solid rgba(0,0,0,.15);
    border-radius: .5rem;
    box-shadow: 0 .5rem 1rem rgba(0,0,0,.18);
}
.start-color-swatches { display: grid; grid-template-columns: repeat(7, 30px); gap: .4rem; }
.start-color-swatch {
    width: 30px;
    height: 30px;
    padding: 0;
    border: 2px solid #fff;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(0,0,0,.25);
    cursor: pointer;
}
.start-color-swatch:hover { transform: scale(1.12); }
.start-color-swatch.is-active { box-shadow: 0 0 0 2px #212529; }
.start-color-none { background: var(--dm-bg-ffffff, #fff) linear-gradient(135deg, transparent 45%, #dc3545 45% 55%, transparent 55%); }
.start-color-custom { display: flex; align-items: center; gap: .5rem; margin: .6rem 0 0; font-size: .85rem; cursor: pointer; }
.start-color-custom input { width: 30px; height: 30px; padding: 0; border: 0; background: none; cursor: pointer; }

/* =====================================================================
   Statistik (/statistik): Chart-Container + klickbare KPI-Karten
   ===================================================================== */
.statistik-chart { position: relative; width: 100%; }
.statistik-kpi { transition: box-shadow .15s ease, transform .15s ease; }
.statistik-kpi:hover { box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .12) !important; transform: translateY(-1px); }
/* Kennzahl-Kacheln als Umschalter der Ansicht (Kunden-Analyse): die aktive ist gruen umrandet */
.statistik-view-tile.active { background: rgba(26, 77, 46, .04); }
/* Teil-Aktualisierung (partial-nav.js): Bereich waehrend des Nachladens abblenden, Klicks sperren */
.partial-loading { opacity: .55; pointer-events: none; transition: opacity .12s ease; }
.statistik-filter .form-control,
.statistik-filter .form-select { min-width: 9rem; }
/* Diagramm-Hoehe am Handy: Block "Statistik am Handy" (html.ae-handy .statistik-page) */

/* ---------- Datenimport: PDF-Erkennung (assets/js/import-pdf.js) ---------- */
.pdf-recognize-stage { overflow: auto; max-height: 70vh; }
.pdf-ruler {
    height: 18px; background: #e9ecef; border-bottom: 1px solid #ced4da;
    cursor: crosshair; position: sticky; top: 0; z-index: 3;
}
.pdf-canvas-wrap { position: relative; }
.pdf-canvas-wrap canvas { display: block; max-width: 100%; }
.pdf-overlay { position: absolute; inset: 0; touch-action: none; }
.pdf-bound {
    position: absolute; top: 0; bottom: 0; width: 9px; margin-left: -4px;
    cursor: col-resize; z-index: 2;
}
.pdf-bound::before {
    content: ""; position: absolute; top: 0; bottom: 0; left: 4px;
    border-left: 2px dashed #dc3545;
}
.pdf-bound.dragging::before { border-left-style: solid; }
.pdf-bound-handle {
    position: absolute; top: 2px; left: -4px; min-width: 17px; padding: 0 3px;
    font-size: 10px; line-height: 15px; text-align: center; border-radius: 3px;
    background: #dc3545; color: #fff; user-select: none;
}

/* =====================================================================
   Beleg-Ansicht: Erfassung direkt auf dem aus der Druckvorlage gerenderten
   Beleg (Angebot/Rechnung/Lieferschein). Vorlagen-CSS ist serverseitig auf
   #belegSheet eingegrenzt (BelegAnsichtService::scopeCss); hier nur Rahmen,
   Eingabefelder und Bedienelemente. JS: assets/js/beleg-form.js
   ===================================================================== */
.be-sheet-wrap { position: relative; }
.be-sheet {
    position: relative; width: 210mm; max-width: 100%; margin: 0 auto; background: #fff;
    box-shadow: 0 2px 14px rgba(0, 0, 0, .18); padding: 15mm 15mm 10mm; box-sizing: border-box;
}
.be-sheet.be-landscape { width: 297mm; }
#belegSheet { font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 11pt; color: #1a1a1a; line-height: 1.35; }
#belegSheet table { border-collapse: collapse; }
#belegSheet .pt-table td:not(.pt-num) { overflow-wrap: anywhere; } /* wie PrintTemplateRenderer: ueberlange Woerter sprengen die Tabelle nicht */
#belegSheet .no-print { display: none !important; }
#belegSheet.be-has-footer { display: flex; flex-direction: column; min-height: 271mm; }
#belegSheet.be-has-footer .pt-footer { margin-top: auto; }
/* Kopffelder: anklickbar */
#belegSheet .be-field { cursor: pointer; border-bottom: 1px dashed transparent; border-radius: 2px; transition: background .12s, border-color .12s; }
#belegSheet .be-field:hover { border-bottom-color: #0d6efd; background: #eaf2ff; }
#belegSheet .be-field-text:empty::before { content: attr(data-be-placeholder); color: #adb5bd; font-style: italic; font-weight: normal; }
#belegSheet .be-field-text:empty { display: inline-block; min-width: 3em; }
/* Leere Felder zeigen, wie deutlich sie eine Eingabe erwarten. data-need setzt
   beleg-form.js aus BelegAnsichtService::headFields: req = Pflicht (Kunde),
   warn = erwartet (z.B. Leistungsdatum), opt = optional. Gefuelltes Feld = nur
   eine dezente gestrichelte Linie, damit das Blatt ein Beleg bleibt und kein
   Formular wird. Feste Farben sind hier richtig: das Blatt ist immer hell. */
#belegSheet .be-field[data-need] { border-bottom-color: #dee2e6; }
#belegSheet .be-field[data-need]:has(.be-field-text:empty) {
    border: 1px dashed; border-radius: 4px; padding: 0 .4em; display: inline-block;
}
#belegSheet .be-field[data-need] .be-field-text:empty::before { font-style: normal; }
#belegSheet .be-field[data-need="req"]:has(.be-field-text:empty) { background: #e7f0ff; border-color: #0d6efd; padding: .1em .45em; }
#belegSheet .be-field[data-need="req"]:has(.be-field-text:empty):hover { background: #d7e5ff; }
#belegSheet .be-field[data-need="req"] .be-field-text:empty::before { color: #0b5ed7; font-weight: 600; }
#belegSheet .be-field[data-need="req"]:has(.be-field-text:empty)::after {
    content: "\F4CB"; font-family: "bootstrap-icons"; margin-left: .45em; color: #0b5ed7; font-size: .8em; vertical-align: 1px;
}
#belegSheet .be-field[data-need="warn"]:has(.be-field-text:empty) { background: #fff6e0; border-color: #e0a800; }
#belegSheet .be-field[data-need="warn"]:has(.be-field-text:empty):hover { background: #ffedc2; }
#belegSheet .be-field[data-need="warn"] .be-field-text:empty::before { color: #8a6100; font-weight: 500; }
#belegSheet .be-field[data-need="opt"]:has(.be-field-text:empty) { background: #f6f7f9; border-color: #ced4da; }
#belegSheet .be-field[data-need="opt"]:has(.be-field-text:empty):hover { background: #eceff2; }
#belegSheet .be-field[data-need="opt"] .be-field-text:empty::before { color: #8b9098; }
/* Adresszusatz (zweite Adresszeile, {{customer.address_extra}}): leer entfaellt
   die Zeile wie im Druck (PrintTemplateRenderer::dropEmptyExtraLines) - samt dem
   Umbruch dahinter, wenn die Vorlage die Anschrift mit <br> baut. Sichtbar bleibt
   das leere Feld nur mit Hinweis "Adresszusatz ..." (Rechnung/Angebot, setzt
   beleg-form.js) oder solange sein Eingabefenster offen ist. */
.be-sheet .be-field[data-be-field$=".address_extra"]:empty,
.be-sheet .be-field[data-be-field$=".address_extra"]:has(> .be-field-text:empty:not([data-be-placeholder])):not(:has(.be-pop)),
.be-sheet .be-field[data-be-field$=".address_extra"]:empty + br,
.be-sheet .be-field[data-be-field$=".address_extra"]:has(> .be-field-text:empty:not([data-be-placeholder])):not(:has(.be-pop)) + br { display: none !important; }
/* Knoepfe unter der Anschrift (beleg-form.js: buildCustomerActions) - ohne sie
   sieht man der Adresse nicht an, dass man sie anklicken kann. */
.be-cust-actions { display: flex; gap: 6px; margin-top: 5px; }
.be-cust-actions button {
    font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 11px; line-height: 1.2;
    padding: 2px 7px; border-radius: 4px; cursor: pointer;
    background: #fff; border: 1px solid #adb5bd; color: #495057;
}
.be-cust-actions button:hover { background: #f1f3f5; }
.be-cust-actions button i { margin-right: 3px; }
.be-cust-actions button[data-be-cust="remove"] { border-color: #e3a0a0; color: #b02a37; }
.be-cust-actions button[data-be-cust="remove"]:hover { background: #fdf0f0; }
/* Hinweis "abweichende Anschrift" (nur fuer diesen Beleg, RecipientAddress) - Blatt ist immer hell */
.be-cust-actions { flex-wrap: wrap; align-items: center; }
.be-cust-actions .be-recipient-flag {
    font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 11px; line-height: 1.2;
    padding: 2px 7px; border-radius: 4px; background: #fff6e0; border: 1px dashed #e0a800; color: #8a6100;
}
.be-cust-actions .be-recipient-flag.d-none, .be-cust-actions button.d-none { display: none !important; }
/* Zugeordnete Auftraege auf dem Blatt ("Auftrag übernehmen", beleg-form.js: renderLinkedOrders) */
.be-cust-actions .be-linked-orders { font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 11px; line-height: 1.2; color: #495057; }
.be-cust-actions .be-linked-orders.d-none { display: none !important; }
.be-cust-actions .be-linked-orders a { color: #0a58ca; }
.be-cust-actions .be-linked-orders button { border: 0; background: none; padding: 0 2px; color: #b02a37; }
.be-cust-actions .be-linked-orders button:hover { background: #fdf0f0; }
/* Positionszeilen: Eingabefelder erben die Vorlagen-Schrift */
#belegSheet .item-row td { position: relative; vertical-align: top; } /* mehrzeilige Bezeichnung: uebrige Spalten auf Hoehe der ersten Zeile (wie PrintTemplateRenderer) */
#belegSheet .item-row .form-control,
#belegSheet .item-row .form-select {
    border: 0; background: transparent; background-image: none; font: inherit; color: inherit; width: 100%;
    padding: 0 1px; height: auto; min-height: 0; line-height: inherit; border-radius: 2px; box-shadow: none; outline: 0;
    appearance: none; -webkit-appearance: none;
}
#belegSheet .item-row .pt-r .form-control, #belegSheet .item-row .pt-num .form-control,
#belegSheet .item-row .pt-r .form-select, #belegSheet .item-row .pt-num .form-select { text-align: right; }
/* Aktives Feld immer weiss mit blauem Rahmen - unabhaengig von Leerzeile/Hover (keine blaue Zeilen-Toenung beim Tippen) */
#belegSheet .item-row .form-control:focus, #belegSheet .item-row .form-select:focus { box-shadow: inset 0 0 0 1.5px #0d6efd; background: #fff; }
#belegSheet .item-row .form-control::placeholder { color: #c5cad0; font-style: italic; }
#belegSheet .item-row:hover td { background: #f4f8ff; }
/* Menge + Einheit in einer Zelle: Zahl rechtsbuendig, Einheit daneben, nichts umbricht */
#belegSheet .be-qu { display: flex; gap: 3px; align-items: baseline; white-space: nowrap; }
#belegSheet .be-qu .row-quantity { flex: 0 0 2.6em; min-width: 2.6em; text-align: right; }
#belegSheet .be-qu .row-unit { flex: 1 1 auto; min-width: 2em; text-align: left; }
#belegSheet .text-row textarea { resize: none; overflow: hidden; font-style: italic; }
/* Bezeichnung der Artikelzeile (Belege, Kasse, Auftrag): bricht in die naechste Zeile um statt abzuschneiden (Verhalten in app.js) */
textarea.row-name-wrap { resize: none; overflow: hidden; field-sizing: content; min-height: 0; }
.table textarea.row-name-wrap { min-height: calc(1.5em + .5rem + 2px); }
.table textarea.row-name-wrap:not(.form-control-sm) { min-height: calc(1.5em + .75rem + 2px); }
/* field-sizing schrumpft sonst die Breite auf den Text - Tabellen ohne feste Spaltenbreiten brauchen ein Minimum */
#invItemsTable textarea.row-name-wrap, #itemsTable textarea.row-name-wrap { min-width: 14rem; }
/* Beleg-Ansicht: field-sizing macht das laengste Wort zur Mindestbreite der Spalte - ein ueberlanges Wort
   (z.B. DUESENSCHEIBEXXXX...) zog die Tabelle ueber das Blatt und quetschte Nummer/Einheit/Betrag. Wie im Druck umbrechen. */
#belegSheet .item-row textarea.row-name-wrap { overflow-wrap: anywhere; min-width: 0; }
#belegSheet .row-line-total { white-space: nowrap; }
/* Zeilen-Bedienung: Griff links, Entfernen rechts – nur bei Hover/Fokus */
/* Griff und X: immer sichtbar, direkt an der Zeile (keine tote Zone), volle Zeilenhoehe als Trefferflaeche */
#belegSheet .be-row-drag, #belegSheet .be-row-remove {
    position: absolute; top: 0; bottom: 0; display: flex; align-items: center; justify-content: center;
    width: 26px; line-height: 1; padding: 0; border: 0; background: transparent; opacity: .55; transition: opacity .12s, color .12s;
}
/* Griff ragt nur 10px ueber die Zeile hinaus: Sortable wertet einen Zeiger weiter links
   (> 10px vor der Tabelle) als "vor die erste Zeile" - dann liesse sich nichts nach unten ziehen. */
#belegSheet .be-row-drag { left: -10px; width: 16px; color: #6c757d; cursor: grab; font-size: 15px; }
#belegSheet .be-row-drag:active { cursor: grabbing; }
/* Muelleimer wie in der Bestellerfassung (btn-sm btn-outline-danger), rechts neben der Zeile */
#belegSheet .be-row-remove {
    right: -44px; width: auto; top: 50%; bottom: auto; transform: translateY(-50%);
    padding: .15rem .45rem; font-size: 12px; line-height: 1.3; border: 1px solid #dc3545; border-radius: .25rem; background: #fff; color: #dc3545;
}
#belegSheet .be-row-remove:hover { background: #dc3545; color: #fff; }
/* Leerzeile: das Nummernfeld zeigt als weisses Eingabefeld, wo die naechste Position entsteht */
/* Schildchen "manuell" (beleg-form.js: markManual) - Position ohne Stammartikel.
   Sitzt auf der Oberkante des Feldes, nimmt der Eingabe also keinen Platz.
   Nur in der Erfassung, nie auf dem Druck. */
.item-row .row-manual-badge {
    position: absolute; top: -7px; right: 3px; z-index: 2; pointer-events: none;
    font: 600 9px/1 system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; letter-spacing: .02em;
    padding: 2px 5px; border-radius: 8px; white-space: nowrap;
    background: var(--dm-bg-fff3cd, #fff3cd); color: var(--dm-fg-664d03, #664d03);
    border: 1px solid var(--dm-bd-ffe69c, #ffe69c);
}
.item-row td:has(> .row-manual-badge) { position: relative; }
/* Schildchen "aus Auftragstext" an einer Textposition (beleg-form.js: markTextSource) -
   gleiche Optik, nur in der Erfassung, nie auf dem Druck. */
.item-row .row-source-badge {
    position: absolute; top: -7px; right: 3px; z-index: 2;
    font: 600 9px/1 system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; letter-spacing: .02em;
    padding: 2px 5px; border-radius: 8px; white-space: nowrap;
    background: var(--dm-bg-fff3cd, #fff3cd); color: var(--dm-fg-664d03, #664d03);
    border: 1px solid var(--dm-bd-ffe69c, #ffe69c);
}
.item-row :has(> .row-source-badge) { position: relative; }
/* Leeres Nummer-Feld der manuellen Zeile: Platzhalter weg, sonst liegt das Schildchen darauf */
.item-row.be-manual .row-article-number::placeholder { color: transparent; }
#belegSheet .item-row.be-blank .row-article-number { background: #fff; box-shadow: inset 0 0 0 1px #adb5bd; padding: 0 4px; }
#belegSheet .item-row.be-blank .row-article-number:focus { box-shadow: inset 0 0 0 1.5px #0d6efd; background: #fff; }
/* Artikelnummer beim Tippen: Feld schwebt groesser ueber der Zeile - die Spalte der Druckvorlage ist oft schmaler
   als die Nummer. Schwebend (absolute, ohne top/left = bleibt an seiner Stelle), damit die Spalten nicht springen; nur Bildschirm. */
#belegSheet .item-row .row-article-number:focus,
#belegSheet .item-row.be-blank .row-article-number:focus {
    position: absolute; margin: -6px 0 0 -8px; z-index: 6;
    width: max(100%, 15em); max-width: none; font-size: 1.25em; padding: 4px 8px; border-radius: 4px;
    background: #fff; box-shadow: 0 0 0 1.5px #0d6efd, 0 4px 14px rgba(0, 0, 0, .22);
}
/* Der Rahmen der Artikelsuche behaelt dabei seine Hoehe, die Trefferliste rueckt unter (bzw. ueber) das groessere Feld */
#belegSheet .item-row .article-search-wrapper:focus-within { min-height: 1.5em; min-height: 1lh; }
#belegSheet .item-row .article-search-wrapper:focus-within > .article-search-dropdown { margin: 8px 0 9px -8px; }
/* Hinzufuegen-Zeile mit Plus-Menue */
#belegSheet .be-add-row td { border: 0 !important; background: transparent !important; padding-top: 2mm; }
#belegSheet .be-add { position: relative; display: flex; align-items: center; gap: 8px; font: 13px system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; color: #6c757d; }
#belegSheet .be-add-btn {
    width: 26px; height: 26px; border-radius: 50%; border: 1px dashed #6c757d; background: #fff; color: #6c757d;
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; font-size: 13px;
}
#belegSheet .be-add-btn:hover, #belegSheet .be-add:hover .be-add-btn { border-style: solid; border-color: #0d6efd; color: #0d6efd; }
#belegSheet .be-add-label { cursor: pointer; }
#belegSheet .be-add:hover .be-add-label { color: #0d6efd; }
#belegSheet .be-add-menu {
    position: absolute; left: 0; top: 100%; margin-top: 4px; z-index: 1050; min-width: 230px; padding: 4px;
    background: #fff; border: 1px solid #ced4da; border-radius: 6px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
}
#belegSheet .be-add-menu button { display: block; width: 100%; text-align: left; border: 0; background: none; padding: 6px 10px; border-radius: 4px; color: #212529; font: inherit; }
#belegSheet .be-add-menu button:hover { background: #f1f3f5; }
/* Text ueber den Positionen / Schlusstext: leer = Plus "Textbaustein hinzufuegen"
   statt des grauen Felds (beleg-form.js buildTextBlockAdds); mit Text oder
   offenem Eingabefenster zeigt sich wieder das Feld */
#belegSheet .be-tb-add { white-space: normal; margin: 1mm 0; }
#belegSheet .be-tb-free { border: 0; background: none; padding: 0; font: inherit; font-size: 12px; color: #6c757d; text-decoration: underline dotted; cursor: pointer; }
#belegSheet .be-tb-free:hover { color: #0d6efd; }
#belegSheet .be-field[data-be-tb]:has(> .be-field-text:empty):not(:has(.be-pop)) { display: none; }
#belegSheet .be-field[data-be-tb]:has(> .be-field-text:not(:empty)) + .be-tb-add,
#belegSheet .be-field[data-be-tb]:has(.be-pop) + .be-tb-add { display: none; }
/* Gesamtrabatt im Summenblock: erst beim Ueberfahren der Summen sichtbar */
#belegSheet .be-discount-row { opacity: .35; transition: opacity .15s; }
#belegSheet table:hover .be-discount-row, #belegSheet .be-discount-row:focus-within, #belegSheet .be-discount-row.has-value { opacity: 1; }
#belegSheet .be-discount-input {
    width: 4.6em; text-align: right; font: inherit; color: inherit; background: #fff; border: 0; border-radius: 3px;
    box-shadow: inset 0 0 0 1px #ced4da; padding: 0 3px; outline: 0;
}
#belegSheet .be-discount-input:focus { box-shadow: inset 0 0 0 1.5px #0d6efd; }
/* Drag-Geist am Body (Zeile ausserhalb der Tabelle): als Tabelle darstellen */
body > .item-row.sortable-fallback { display: table; background: #eaf2ff; border: 1px solid #0d6efd; border-radius: 4px; box-shadow: 0 6px 18px rgba(0, 0, 0, .18); font: 11pt 'Helvetica Neue', Arial, sans-serif; color: #1a1a1a; }
body > .item-row.sortable-fallback td { padding: 1.5mm 2mm; vertical-align: top; }
body > .item-row.sortable-fallback .form-control, body > .item-row.sortable-fallback .form-select {
    border: 0; background: transparent; background-image: none; font: inherit; color: inherit; padding: 0 1px; height: auto; min-height: 0; box-shadow: none; width: 100%;
}
body > .item-row.sortable-fallback .be-row-drag, body > .item-row.sortable-fallback .be-row-remove, body > .item-row.sortable-fallback .article-search-dropdown { display: none; }
#belegSheet .item-row:hover .be-row-drag, #belegSheet .item-row:hover .be-row-remove,
#belegSheet .item-row:focus-within .be-row-drag, #belegSheet .item-row:focus-within .be-row-remove,
#belegSheet .be-row-drag:hover, #belegSheet .be-row-remove:hover { opacity: 1; }
/* Ziehen: die Zeile als ganzes hervorheben */
#belegSheet .sortable-chosen td { background: #dbe7ff; }
#belegSheet .sortable-ghost td { background: #dbe7ff; }
/* Artikel-Suche im Blatt: Dropdown in App-Optik, breiter als die Zelle */
#belegSheet .article-search-wrapper { position: relative; }
#belegSheet .article-search-dropdown {
    min-width: 135mm; max-width: 175mm; font: 14px system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; text-align: left;
    border-radius: 6px; overflow-x: hidden; border: 1px solid #ced4da;
}
/* App-Bedienelemente, die IM Blatt haengen, duerfen keine Textformatierung der
   Druckvorlage erben: .pt-text setzt white-space: pre-wrap (dann druckt der Browser
   die Einrueckung des Markups mit), Abschnittstitel setzen uppercase/letter-spacing.
   Gilt fuer die Artikelsuche in der Zeile UND das Kopfdaten-Fenster. */
#belegSheet .article-search-dropdown, .be-pop {
    white-space: normal; text-indent: 0; letter-spacing: normal; word-spacing: normal; text-transform: none;
}
/* Trefferliste: Ecken sauber (Eintraege ohne eigene Rundung, Container rundet und schneidet) */
#belegSheet .article-search-dropdown .list-group-item, .be-pop .customer-search-dropdown .list-group-item { border-radius: 0; }
#belegSheet .article-search-dropdown .list-group-item:first-child, .be-pop .customer-search-dropdown .list-group-item:first-child { border-top: 0; }
#belegSheet .article-search-dropdown .list-group-item:last-child, .be-pop .customer-search-dropdown .list-group-item:last-child { border-bottom: 0; }
/* Eingabefenster fuer Kopfdaten */
#belegSheet .be-field { position: relative; }
#belegSheet .be-field:has(.be-pop) { background: #eaf2ff; border-bottom-color: #0d6efd; }
#belegSheet .be-field[data-need]:has(.be-pop) { background: #eaf2ff; border-color: #0d6efd; }
.be-pop {
    position: absolute; left: 0; top: 100%; margin-top: 4px; cursor: default; text-align: left; font-weight: normal;
    z-index: 1050; background: #fff; border: 1px solid #ced4da; border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .18); padding: 10px 12px; min-width: 300px; max-width: 460px;
    font: 14px system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
}
.be-pop.be-pop-right { left: auto; right: 0; }
#belegSheet .be-field.be-date-open { visibility: hidden; }
/* Datumsfeld ueber dem Datum auf dem Blatt: Anker fuer den Datepicker des Browsers. Haengt am
   <body> (fixed, Lage/Groesse setzt beleg-form.js: openDatePicker) - im skalierten Blatt bzw.
   unsichtbar oeffnete Chrome den Kalender links oben im Fenster. Blatt = Papier, immer hell. */
.be-date-picker {
    position: fixed; z-index: 1060; margin: 0; padding: 0 4px; width: 9.5em; box-sizing: border-box;
    font: 13px 'Helvetica Neue', Arial, sans-serif; color: #1a1a1a; background: #fff;
    border: 1px solid #0d6efd; border-radius: 3px; box-shadow: 0 0 0 3px rgba(13, 110, 253, .15);
    color-scheme: light;
}
.be-pop.be-pop-customer { min-width: 420px; }
/* Fenster fuer laengere Texte (Einleitung/Schlusstext): breit genug zum Schreiben */
.be-pop.be-pop-text { min-width: min(560px, 88vw); max-width: min(680px, 92vw); }
.be-pop.be-pop-text textarea { min-height: 180px; resize: vertical; }
.be-pop .customer-search-dropdown { border-radius: 6px; overflow-x: hidden; border: 1px solid #ced4da; font-size: 14px; }
.be-pop label { font-size: 12px; color: #6c757d; margin-bottom: 4px; display: block; }
/* Kopfdaten-Fenster: letzte Karte ohne Aussenabstand */
#beHeadModalBody .be-head-card:last-child { margin-bottom: 0 !important; }
.be-pop textarea { min-height: 90px; }
.be-pop .customer-search-dropdown { min-width: 100%; }
/* Status-Stempel (ENTWURF): klein im oberen Blattrand rechts, nicht ueber dem
   Arbeitsbereich (wie beim Druck, rechnungen/print.php) */
.be-stamp {
    position: absolute; top: 5mm; right: 15mm; font: bold 9pt Arial, sans-serif; letter-spacing: .15em;
    color: #6c757d; pointer-events: none; z-index: 2;
}
.be-viewbar .btn.active { background: #6c757d; color: #fff; }
/* Beleg-Ansicht auf der Belegseite: die Druckansicht im Blatt-Rahmen.
   Breite 180mm = A4 minus der 15mm Raender, die der Rahmen selbst stellt. */
.be-sheet-frame { padding: 15mm 15mm 10mm; }
.be-sheet-frame iframe { display: block; width: 180mm; height: 260mm; border: 0; overflow: hidden; scrollbar-width: none; }
.be-sheet-frame iframe::-webkit-scrollbar { display: none; }
/* Noch nicht vergebene Belegnummer */
#belegSheet .be-pending { font-style: italic; font-weight: normal; color: #8a8f94; }

/* ==========================================================================
   Zahlenblock der Scan-Seiten (ScanPage.keypadHtml/bindKeypad)
   Liegt hier statt im Scan-Layout, weil ihn auch Seiten im Standard-Layout
   nutzen (Inventur). Optik der Aktionsleiste bleibt in layout/scan.php.
   ========================================================================== */
.pscan-qty { font-size: 1.7rem; text-align: right; font-family: var(--bs-font-monospace); padding: .3rem .6rem; }
.pscan-qty[readonly] { background: var(--dm-bg-ffffff, #fff); }
.pscan-keys { display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem; margin-top: .5rem; }
.pscan-keys .btn { font-size: 1.3rem; padding: .4rem 0; font-family: var(--bs-font-monospace); -webkit-tap-highlight-color: transparent; }
/* Touch: Hover/Fokus klebt nach dem Tippen an der Taste und sieht wie
   „gedrueckt" aus (User-Meldung 2026-09-08) - auf Geraeten ohne Maus keinen
   Hover-Zustand zeichnen, Fokus-Ring nur bei Tastaturbedienung. */
@media (hover: none) {
    .pscan-keys .btn:hover:not(:active) { background-color: transparent; color: var(--bs-btn-color); }
}
.pscan-keys .btn:focus:not(:focus-visible) { box-shadow: none; }

/* =====================================================================
   Schnellsuche-Fenster (partials/global_search_modal.php, global-search.js):
   Standard-Modal (Kopf/Body/Fuss). Im Body: Suchleiste, darunter Reiter je
   Quelle (Pills, umbrechend) mit Zaehler bzw. Kreisel und EINE Liste
   verlinkter Treffer als eigener Scroll-Kasten.
   ===================================================================== */
#globalSearchModal .gs-tabs { gap: .25rem; margin-bottom: .75rem; }
#globalSearchModal .gs-tab { padding: .25rem .6rem; font-size: .875rem; white-space: nowrap; }
#globalSearchModal .gs-tab.gs-empty:not(.active) { color: var(--dm-fg-adb5bd, #adb5bd); }
#globalSearchModal .gs-tab .gs-count { background: #6c757d; margin-left: .25rem; }
#globalSearchModal .gs-tab.active .gs-count { background: rgba(255, 255, 255, .35); }
#globalSearchModal .gs-tab .gs-spin { width: .8rem; height: .8rem; border-width: .15em; margin-left: .25rem; vertical-align: -.1em; }
#globalSearchModal .gs-list {
    max-height: 55vh; overflow-y: auto;
    border: 1px solid var(--dm-bd-dee2e6, #dee2e6); border-radius: .375rem;
}
#globalSearchModal .gs-item {
    display: block; padding: .5rem .9rem; color: inherit; text-decoration: none;
    border-bottom: 1px solid var(--dm-bd-f0f0f0, #f0f0f0);
}
#globalSearchModal .gs-item:last-child { border-bottom: 0; }
#globalSearchModal .gs-item:hover,
#globalSearchModal .gs-item.active { background: var(--dm-bg-e7f1ff, #e7f1ff); color: inherit; }
#globalSearchModal .gs-title { font-weight: 500; }
#globalSearchModal .gs-sub { font-size: .8rem; color: var(--dm-fg-6c757d, #6c757d); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#globalSearchModal .gs-status { padding: 1rem; text-align: center; color: var(--dm-fg-6c757d, #6c757d); }
#globalSearchModal .gs-more { display: block; padding: .6rem .9rem; text-align: center; font-size: .875rem; border-top: 1px solid var(--dm-bd-f0f0f0, #f0f0f0); }

/* =====================================================================
   Explorer-Layout (Seitenleiste + Liste): Schaltplaene UND Archiv-Baum
   (Jahr -> Dokumentart -> Monat) teilen sich diese Klassen.
   ===================================================================== */
.splan-nav { padding: .35rem 0; font-size: .925rem; }
/* Seitenleiste klebt am PC; am Handy (html.ae-handy) ist sie ein Klappbereich (.splan-nav-collapse) */
html:not(.ae-handy) .splan-nav { position: sticky; top: 4.5rem; }
html:not(.ae-handy) .splan-nav-collapse { display: block !important; height: auto !important; }
.splan-nav-row {
    display: flex; align-items: center; gap: .15rem;
    padding: .2rem .5rem .2rem .25rem; color: inherit;
}
.splan-nav-row:hover { background: var(--dm-bg-f4f6f8, #f4f6f8); }
.splan-nav-row.active { background: var(--dm-bg-e7f1ff, #e7f1ff); color: var(--dm-fg-084298, #084298); font-weight: 500; }
.splan-nav-row.splan-nav-ungrouped { border-top: 1px solid var(--dm-bd-eef0f2, #eef0f2); margin-top: .25rem; padding-top: .35rem; color: var(--dm-fg-6c757d, #6c757d); }
.splan-nav-child { padding-left: 1.25rem; }
.splan-nav-child2 { padding-left: 2.5rem; }
.splan-nav-toggle {
    flex: 0 0 1.35rem; width: 1.35rem; height: 1.35rem; padding: 0; border: 0; background: none;
    color: var(--dm-fg-6c757d, #6c757d); display: inline-flex; align-items: center; justify-content: center; border-radius: .25rem;
}
.splan-nav-toggle:not(.splan-nav-toggle-empty):hover { background: var(--dm-bg-dee2e6, #dee2e6); color: var(--dm-fg-212529, #212529); }
.splan-nav-toggle .bi { transition: transform .15s; display: inline-block; font-size: .8rem; }
.splan-nav-link {
    flex: 1 1 auto; min-width: 0; color: inherit; text-decoration: none;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: .1rem .15rem;
}
.splan-nav-link:hover { color: inherit; text-decoration: underline; }
.splan-nav-count { flex: 0 0 auto; color: var(--dm-fg-6c757d, #6c757d); font-size: .8rem; font-weight: 400; min-width: 1.5rem; text-align: right; }
.splan-nav-row.active .splan-nav-count { color: var(--dm-fg-084298, #084298); }
.splan-nav-open {
    flex: 0 0 auto; font-size: .7rem; line-height: 1; padding: .15rem .35rem; border-radius: 1rem;
    background: var(--dm-bg-fff3cd, #fff3cd); color: var(--dm-fg-664d03, #664d03); font-weight: 500;
}
.splan-dot { display: inline-block; width: .6rem; height: .6rem; border-radius: 50%; vertical-align: middle; }
/* Plan-Ansicht (schaltplan/show.php): runde Blaetter-Pfeile ueber dem Bild, Fundstellen-Marker */
.splan-pagearrow {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 20;
    width: 46px; height: 46px; border-radius: 50%; opacity: .85;
    display: flex; align-items: center; justify-content: center;
}
.splan-pagearrow-prev { left: 8px; }
.splan-pagearrow-next { right: 8px; }
.splan-hit { pointer-events: none; } /* PC: Marker nur Optik (title), am Handy tippbar (s. Handy-Block) */
/* Lade-Hinweis des Viewers über dem leeren Canvas (show.php entfernt ihn nach dem Zeichnen) */
.splan-loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    line-height: 1.4; font-size: .9rem; pointer-events: none; }
.splan-doclist .splan-col-status { width: 1.75rem; padding-right: 0; text-align: center; }
.splan-doclist .splan-section td { background: var(--dm-bg-f8f9fa, #f8f9fa); font-weight: 600; font-size: .875rem; padding-top: .45rem; padding-bottom: .45rem; }
.splan-doclist .badge { vertical-align: middle; }
.splan-group-table .splan-group-name { min-width: 14rem; }
.splan-group-table .splan-group-parent { width: 13rem; }
.splan-group-table tr.splan-group-child td { background: var(--dm-bg-fcfcfd, #fcfcfd); }

/* Textbausteine-Seite (/textbausteine, text-blocks-page.js) */
.tbp-content { resize: vertical; field-sizing: content; min-height: 4.5rem; }
.tbp-handle { cursor: grab; }
.tbp-block-new { border-style: dashed !important; }
.tbp-paper {
    background: var(--bs-body-bg); color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color); border-radius: .25rem;
    box-shadow: 0 .125rem .5rem rgba(0, 0, 0, .15);
    padding: 2rem 2.25rem; font-size: .9rem;
}
.tbp-paper-text { white-space: pre-line; }
.tbp-paper-text:empty { display: none; }

/* ===== Wartungsplan-Editor (kdv/plans/show.php, kdv-plan-editor.js) =====
   Eine Zeile je Taetigkeit, Teile als Schild. Farben nur aus den
   Bootstrap-Variablen, damit der Dunkelmodus mitgeht. */
.kp-search { flex: 1 1 260px; max-width: 420px; }
.kp-ghead { display: flex; align-items: center; gap: .5rem; padding: .4rem .6rem; }
.kp-toggle { display: flex; align-items: center; gap: .45rem; min-width: 0; border: 0; background: none; padding: .15rem 0; color: inherit; font-weight: 600; text-align: left; }
.kp-toggle .bi-chevron-down { transition: transform .15s; font-size: .8rem; }
.kp-collapsed .kp-toggle .bi-chevron-down { transform: rotate(-90deg); }
.kp-gcount { font-weight: 400; color: var(--bs-secondary-color); font-variant-numeric: tabular-nums; }
.kp-collapsed .kp-body, .kp-collapsed .kp-rename-form { display: none; }
#kpEditor.kp-filtering .kp-collapsed .kp-body { display: block; }
.kp-hide { display: none !important; }
.kp-rename-form { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; padding: 0 .6rem .5rem 2rem; }
.kp-rename-form[hidden] { display: none; }
.kp-rename-form input[type=text] { max-width: 320px; }
.kp-tasks { min-height: 4px; }
.kp-row { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; padding: .3rem .6rem; border-top: 1px solid var(--bs-border-color); cursor: pointer; }
.kp-row:hover, .kp-row:focus-visible { background: var(--bs-tertiary-bg); }
.kp-row[hidden] { display: none; }
.kp-text { flex: 1 1 260px; min-width: 0; }
.kp-grip { color: var(--bs-secondary-color); cursor: grab; touch-action: none; }
.kp-pen { color: var(--bs-secondary-color); opacity: 0; }
.kp-row:hover .kp-pen, .kp-row:focus-visible .kp-pen { opacity: 1; }
.kp-chip { font-size: .8rem; font-variant-numeric: tabular-nums; white-space: nowrap; padding: .05rem .45rem; border-radius: .3rem; background: var(--bs-primary-bg-subtle); color: var(--bs-primary-text-emphasis); }
.kp-chip-alt { background: var(--bs-secondary-bg); color: var(--bs-secondary-color); }
.kp-chip-text { outline: 1px dashed var(--bs-warning-border-subtle); background: var(--bs-warning-bg-subtle); color: var(--bs-warning-text-emphasis); }
.kp-empty { padding: .3rem .6rem .5rem 2rem; border-top: 1px solid var(--bs-border-color); }
.kp-empty[hidden] { display: none; }
.kp-edit { display: flex; flex-direction: column; gap: .4rem; padding: .6rem; border-top: 1px solid var(--bs-border-color); background: var(--bs-primary-bg-subtle); }
.kp-line { display: flex; gap: .4rem; align-items: center; flex-wrap: wrap; }
.kp-line[hidden] { display: none; }
.kp-line > input[name=text] { flex: 1 1 100%; }
.kp-lbl { flex: 0 0 4.5rem; font-size: .8rem; color: var(--bs-secondary-color); }
.kp-line .article-search-wrapper { flex: 0 1 13rem; }
/* Trefferliste breiter als das schmale Nummernfeld (w-100 kaeme sonst auf 13rem) */
.kp-line .article-search-wrapper .article-search-dropdown { width: min(34rem, calc(100vw - 3rem)) !important; }
.kp-line .kp-name { flex: 1 1 12rem; }
.kp-line .kp-qty { flex: 0 0 5.5rem; }
.kp-line .kp-basis-select { flex: 0 0 7.5rem; width: auto; }
.kp-basis { font-size: .7rem; opacity: .75; }
.sortable-ghost.kp-row, .sortable-ghost.kp-group { opacity: .4; }
.kp-dialog-body, .kp-dialog-body > form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; overflow: hidden; }
.kp-detect-label { flex: 0 0 3.5rem; }
.kp-detect-link[hidden] { display: none; }

/* ------------------------------------------------------------------
 * Kundendienst: Kalkulation des Servicevertrags (kdv-kalkulation.js,
 * kdv/kalkulation/_tabelle.php)
 * ------------------------------------------------------------------ */
.kk-head { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; align-items: flex-start; margin-bottom: .75rem; }
.kk-meta > .small, .kk-meta > label { display: block; margin-bottom: .15rem; line-height: 1.2; }
.kk-meta > .fw-semibold { min-height: calc(1.5em + .5rem + 2px); display: flex; align-items: center; }
.kk-table .kk-artnr { width: 10rem; }
.kk-table .article-search-wrapper .article-search-dropdown { width: min(34rem, calc(100vw - 3rem)) !important; }
.kk-ig { width: 8.5rem; }
.kk-sec { margin-bottom: .75rem; }
.kk-sec-title { display: flex; align-items: baseline; gap: .5rem; padding: .35rem .25rem; border-bottom: 1px solid var(--bs-border-color); }
.kk-toggle { cursor: pointer; user-select: none; border-radius: .3rem; }
.kk-toggle:hover { background: var(--bs-tertiary-bg); }
.kk-chev { font-size: .8rem; transition: transform .15s; color: var(--bs-secondary-color); }
.kk-open .kk-chev { transform: rotate(90deg); }
.kk-sec-body[hidden] { display: none; }
.kk-sec-sum { font-variant-numeric: tabular-nums; color: var(--bs-secondary-color); font-size: .9rem; }
.kk-table td, .kk-table th { vertical-align: middle; }
.kk-table .kk-in { width: 5.5rem; display: inline-block; }
.kk-table .kk-in-price { width: 7rem; }
.kk-table tr.kk-off td { color: var(--bs-secondary-color); }
.kk-table tr.kk-off td:nth-child(3) { text-decoration: line-through; }
.kk-table tr.kk-work td { background: var(--bs-tertiary-bg); }
.kk-totals { display: grid; grid-template-columns: 1fr auto; gap: .15rem 1.5rem; max-width: 30rem; margin-left: auto; margin-top: .75rem; }
.kk-totals .kk-sep { grid-column: 1 / -1; border-top: 1px solid var(--bs-border-color); margin: .25rem 0; }
.kk-totals .kk-big { font-size: 1.15rem; font-weight: 700; color: var(--bs-primary-text-emphasis); }
.kk-totals .kk-totals-h { grid-column: 1 / -1; font-weight: 600; border-bottom: 1px solid var(--bs-border-color); padding-bottom: .25rem; margin-bottom: .25rem; }
.kk-totals .kk-auf { display: flex; align-items: center; gap: .5rem; }
.kk-ig-auf { width: 6.5rem; }
.kk-static .kk-head { margin-bottom: .5rem; }
.kk-static .kk-totals { margin-top: .75rem; }
.tabular { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Drop-Ziele beim Ziehen von Dateien - EINE Darstellung (User-Vorgabe
   2026-10-07): Anhaenge an Rechnung/Angebot (beleg-anhaenge.js) und alle
   Drop-Ziele der Projektseite (projekte/show.php, projekt-intern.js) */
#belegAnhaenge.beleg-anhaenge-drop,
.projekt-drop-active {
    outline: 2px dashed var(--bs-primary);
    outline-offset: -2px;
    background-color: var(--bs-primary-bg-subtle);
}
/* card-body hat selbst keine Rundung: die der Karte uebernehmen */
.card-body.projekt-drop-active { border-radius: inherit; }

/* ---- Layoutbreite (User-Vorgabe 2026-10-06) --------------------------------
   Einheitsbreite: jede Seite im Standard-Container (Listen, Stammblaetter,
   Masken, Belegformulare) waechst ab 1400px Fenster bis 1500px statt der
   1320px von container-xxl - bewusst ueberall gleich, damit die Breite beim
   Wechsel Liste <-> Karte <-> Maske nicht springt. Beleg-Ansicht bleibt Papier,
   Dashboard + Terminplanung volle Breite. Das Auftrags-Modal (Detail + Anlegen,
   .modal-ae-order) bekommt 1400px statt 1140px (modal-xl). Fest vorgegeben,
   kein Benutzer-Schalter. */
@media (min-width: 1400px) {
    main.container-xxl { max-width: min(1500px, 100% - 3rem); }
}
@media (min-width: 1460px) {
    .modal-ae-order { --bs-modal-width: 1400px; }
}

/* ---- Listen: Kopf + Blaettern festgeheftet (User-Vorgabe 2026-10-06) --------
   <div class="list-sticky-top"> Titelzeile + Filterkarte </div> klebt unter der
   Navbar, <div class="list-sticky-bottom"> ui_pagination() </div> am unteren
   Rand, die Kopfzeile der Tabelle (ui_table) direkt unter dem Kopfblock - so
   bleiben Knoepfe, Suche, Reiter und das Blaettern beim Scrollen sichtbar.
   --list-sticky-h = gemessene Hoehe des Kopfblocks (assets/js/list-sticky.js).
   Der Seitengrund deckt die Zeilen hinter dem Block ab (--list-sticky-bg = gemessene
   Hintergrundfarbe des <body>, list-sticky.js - die Farbe kommt je nach Modus aus
   Bootstrap .bg-light, dark.css oder Kontrast-Regeln, nicht aus --apple-bg); der Rand
   unter der Filterkarte (mb-3) liegt als padding IM Block, sonst scheinen die
   Zeilen in der Luecke durch. Am Handy und im Druck klebt nichts.
   Kein Weg bis zum Festkleben (Fehlerbild 2026-10-08: Kopf sprang beim ersten
   Scrollen ~16px hoch und beim Zurueckscrollen wieder runter): der Block beginnt
   schon an der Unterkante der Navbar (main py-4 = 1.5rem wird als negativer Rand
   zurueckgenommen und als padding-top wieder aufgefuellt) und klebt genau dort -
   er steht also festgeklebt exakt wie in Ruhe. 1px Ueberlappung mit der Navbar
   (die liegt darueber), weil --navbar-h ganzzahlig gemessen wird und bei Browser-
   Zoom sonst ein Pixelspalt bleibt, in dem Zeilen durchscheinen. Bewusst KEIN
   box-shadow fuer den Streifen darueber: der Schatten lag auch seitlich neben
   der Filterkarte und verdunkelte deren Rand im festgeklebten Zustand. */
.list-sticky-top {
    position: sticky; top: calc(var(--navbar-h, 56px) - 1px); z-index: 20;
    background-color: var(--list-sticky-bg, var(--bs-body-bg));
    margin-top: calc(-1.5rem - 1px); padding-top: calc(1.5rem + 1px); padding-bottom: 1rem;
    /* bis an die Container-Raender: die Tabellenkarte schiebt sich beim Scrollen
       hinter den Block, ihr Schatten ragt aber seitlich ueber die Karte hinaus -
       ohne diese Verbreiterung stand er als dunkler Rand neben der Filterkarte
       (Fehlerbild 2026-10-08 "Filterkarte abgehoben") */
    margin-left: calc(var(--bs-gutter-x, 1.5rem) * -.5); margin-right: calc(var(--bs-gutter-x, 1.5rem) * -.5);
    padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5); padding-right: calc(var(--bs-gutter-x, 1.5rem) * .5);
}
.list-sticky-top > :last-child { margin-bottom: 0 !important; }
.list-sticky-bottom {
    position: sticky; bottom: 0; z-index: 20;
    background-color: var(--list-sticky-bg, var(--bs-body-bg));
    padding: .5rem 0;
}
.list-sticky-bottom > nav { margin-top: 0 !important; }
/* Die Kopfzeile kann nur kleben, wenn kein Scroll-Container dazwischen liegt:
   table-responsive am PC ohne overflow (eine vom User sehr breit gezogene
   Tabelle ragt dann ueber die Karte hinaus statt in der Karte zu scrollen).
   Hintergrund: apple-theme.css macht thead.table-light transparent (!important) -
   klebend muss der Kopf die Zeilen dahinter abdecken, deshalb hier die Kartenfarbe
   (--apple-surface = Karten hell/dunkel) mit hoeherer Spezifitaet.
   Die Linie unter dem Kopf gehoert bei border-collapse der Tabelle, nicht der
   Zelle - sie bleibt beim Festkleben zurueck (Fehlerbild 2026-10-08: gescrollt
   fehlte die Trennlinie unter den Spaltenkoepfen). Deshalb Zellrand aus und die
   Linie als innerer Schatten in der Tabellen-Linienfarbe auf der Zelle selbst
   (beides zusammen gaebe in Ruhe zwei Linien). Der deckende Zellhintergrund
   wuerde die runden Ecken der Karte abschneiden - deshalb aussen die Ecken der
   Karte mitrunden (ohne card-header beginnt die Karte mit dem Tabellenkopf). */
.list-sticky-top ~ * .table-responsive { overflow: visible; }
.list-sticky-top ~ * table[data-table-key] > thead > tr > th {
    position: sticky; top: calc(var(--navbar-h, 56px) - 1px + var(--list-sticky-h, 0px)); z-index: 5;
    background-color: var(--apple-surface, var(--bs-body-bg)) !important;
    border-bottom-width: 0;
    box-shadow: inset 0 -1px 0 var(--bs-table-border-color, var(--bs-border-color));
}
/* Beginnt die Karte direkt mit der Tabelle (kein card-header), uebernimmt der
   Spaltenkopf die Oberkante der Karte: Kartenrand oben weg, Linie + runde Ecken
   am Kopf selbst. Sonst steht der Kopf in Ruhe 1px (Kartenrand) tiefer als
   festgeklebt und springt beim ersten Scrollen (Fehlerbild 2026-10-08). Festgeklebt
   liegt die (weisse) Karte hinter der runden Ecke - ein Pseudo-Element zeichnet den
   Seitengrund ausserhalb des Viertelkreises nach (in Ruhe unsichtbar). */
html:not(.ae-handy) .list-sticky-top ~ .card:not(:has(> .card-header)):has(> .table-responsive > table[data-table-key]) { border-top-width: 0 !important; }
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th {
    box-shadow: inset 0 1px 0 var(--bs-card-border-color, rgba(0, 0, 0, .12)), inset 0 -1px 0 var(--bs-table-border-color, var(--bs-border-color));
}
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th:first-child { border-top-left-radius: var(--bs-card-inner-border-radius, .375rem); }
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th:last-child { border-top-right-radius: var(--bs-card-inner-border-radius, .375rem); }
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th:first-child::before,
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th:last-child::after {
    content: ''; position: absolute; top: 0; pointer-events: none;
    /* um die Randbreite breiter: neben der runden Ecke lief sonst der gerade
       Kartenrand (border-left/right der Karte) nach oben weiter (User 2026-10-08) */
    width: calc(var(--bs-card-inner-border-radius, .375rem) + var(--bs-border-width, 1px)); height: var(--bs-card-inner-border-radius, .375rem);
}
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th:first-child::before {
    left: calc(-1 * var(--bs-border-width, 1px));
    background: radial-gradient(circle at 100% 100%, transparent calc(var(--bs-card-inner-border-radius, .375rem) - 1px), var(--list-sticky-bg, var(--bs-body-bg)) var(--bs-card-inner-border-radius, .375rem));
}
.list-sticky-top ~ .card:not(:has(> .card-header)) > .table-responsive > table[data-table-key] > thead > tr > th:last-child::after {
    right: calc(-1 * var(--bs-border-width, 1px));
    background: radial-gradient(circle at 0 100%, transparent calc(var(--bs-card-inner-border-radius, .375rem) - 1px), var(--list-sticky-bg, var(--bs-body-bg)) var(--bs-card-inner-border-radius, .375rem));
}
/* Absolut positionierte Kinder (span.visually-hidden in Status-Badges u.a.)
   beziehen sich auf den Scroll-Container der Tabelle - sonst lagen sie am
   Handy rechts ausserhalb und machten die ganze Seite breiter (452 px bei
   390 px Fenster, /rechnungen). Klebender Kopf + Ecken bleiben unberuehrt
   (sticky/::before haengen an der Zelle, nicht am Container). */
.table-responsive { position: relative; }
/* Spaltenwaehler im letzten Spaltenkopf (ui_table-Option chooser) */
.ui-th-chooser-wrap { display: inline-block; margin-left: .35rem; vertical-align: middle; }
.ui-th-chooser-wrap .btn { padding: 0 .3rem; line-height: 1.15; font-size: .8rem; }
.ui-table-chooser-modal { font-weight: 400; text-transform: none; letter-spacing: normal; }
html.ae-handy .list-sticky-top,
html.ae-handy .list-sticky-bottom,
html.ae-handy .list-sticky-top ~ * table[data-table-key] > thead > tr > th { position: static; box-shadow: none !important; border-bottom-width: 1px; border-radius: 0 !important; }
html.ae-handy .list-sticky-top { margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }
html.ae-handy .list-sticky-top ~ * table[data-table-key] > thead > tr > th::before,
html.ae-handy .list-sticky-top ~ * table[data-table-key] > thead > tr > th::after { display: none !important; }
html.ae-handy .list-sticky-top ~ * .table-responsive { overflow-x: auto; }
@media print {
    .list-sticky-top, .list-sticky-bottom,
    .list-sticky-top ~ * table[data-table-key] > thead > tr > th { position: static; box-shadow: none !important; border-bottom-width: 1px; border-radius: 0 !important; }
    .list-sticky-top { margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }
    .list-sticky-top ~ * table[data-table-key] > thead > tr > th::before,
    .list-sticky-top ~ * table[data-table-key] > thead > tr > th::after { display: none !important; }
    .list-sticky-top ~ .card { border-top-width: 1px !important; }
}

/* Beleg: aus einer Artikelliste übernommene Zeilen kurz hervorheben (beleg-form.js) */
@keyframes beRowAdded { from { background-color: var(--bs-success-bg-subtle); } to { background-color: transparent; } }
.item-row.be-row-added > td { animation: beRowAdded 2.5s ease-out; }

/* Abzurechnen: einklappbare Abschnitte (assets/js/billing-sections.js); Anker landen unter der klebenden Navbar */
.billing-section { scroll-margin-top: 4.5rem; }
.billing-section-head { cursor: pointer; user-select: none; }
.billing-section-chevron { transition: transform .15s ease; }

/* Bestellerfassung Schritt 1 + 2 (purchases/_erfassung.php): Seite /purchases UND
   Fenster "Bestellen" aus dem Artikel (partials/purchase_add_modal.php) */
/* Artikel-Such-Bereich (Hero) */
.article-hero {
    background: var(--dm-bg-f0f5f1, #f0f5f1);
    border: 2px solid #1a4d2e;
    border-radius: 8px;
    padding: 18px 20px;
    margin-bottom: 1rem;
}
.article-hero .article-hero-title {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--dm-fg-1a4d2e, #1a4d2e);
    font-weight: 700;
    margin-bottom: 8px;
}
.article-hero .form-control-lg {
    font-size: 1.15rem;
}
/* Selected Article Preview */
.selected-article-card {
    background: var(--dm-bg-ffffff, #fff);
    border: 1px solid #1a4d2e;
    border-radius: 6px;
    padding: 12px 14px;
    margin-top: 10px;
}
.selected-article-card .art-name { font-weight: 700; font-size: 1.1rem; }
.selected-article-card .art-meta { font-size: 0.85rem; color: var(--dm-fg-6c757d, #6c757d); }
.selected-article-card .supplier-info {
    display: flex; align-items: center; gap: 6px;
    flex-wrap: wrap; /* schmal (Handy-Fenster): "Lieferant wechseln" rutscht in die naechste Zeile */
    background: var(--dm-bg-fff8dc, #fff8dc);
    padding: 8px 12px;
    border-radius: 4px;
    margin-top: 10px;
    font-weight: 600;
}
.selected-article-card .supplier-info.no-default {
    background: var(--dm-bg-f8d7da, #f8d7da);
    color: var(--dm-fg-842029, #842029);
}
/* Mindestliefermenge - kompakt */
.min-order-box {
    display: flex; align-items: center; gap: 8px;
    background: var(--dm-bg-ffe69c, #ffe69c);
    border: 1px solid #ff8800;
    padding: 6px 12px;
    border-radius: 4px;
    margin-top: 8px;
    font-size: 0.95rem;
    color: var(--dm-fg-663c00, #663c00);
}
.min-order-box i { font-size: 1.1rem; color: #cc6600; }
.min-order-box strong { font-weight: 700; }
.min-order-box .small-note {
    font-weight: 400; font-size: 0.8rem; color: var(--dm-fg-663c00, #663c00); margin-left: auto;
}
.min-order-box.warning-active {
    background: var(--dm-bg-f8d7da, #f8d7da);
    border-color: #dc3545;
    color: var(--dm-fg-842029, #842029);
    animation: pulseWarn 1s ease-in-out infinite alternate;
}
.min-order-box.warning-active i { color: var(--dm-fg-842029, #842029); }
@keyframes pulseWarn {
    from { box-shadow: 0 0 0 rgba(220,53,69,0.0); }
    to   { box-shadow: 0 0 12px rgba(220,53,69,0.5); }
}
/* Letzte Bestellung - prominenter Hinweis, damit der User die Info auch
   im Vorbeigehen lesen kann (Scanner-Workflow). */
.last-purchase-box {
    display: flex; align-items: center; gap: 12px;
    background: var(--dm-bg-cfe2ff, #cfe2ff);
    border: 1px solid #0d6efd;
    border-left-width: 6px;
    padding: 12px 16px;
    border-radius: 4px;
    margin-top: 8px;
    font-size: 1.15rem;
    color: var(--dm-fg-052c65, #052c65);
}
.last-purchase-box strong { font-size: 1.3rem; font-weight: 700; }
.last-purchase-box .ps-line > i { font-size: 1.3rem; color: #0d6efd; }
.last-purchase-box .ps-line + .ps-line { margin-top: 4px; }
.last-purchase-box .ps-as, .last-purchase-box .badge { font-size: .85rem; }
.last-purchase-box a { font-weight: 600; }
.last-purchase-box.never {
    border-left-color: #adb5bd;
    color: var(--dm-fg-6c757d, #6c757d);
    font-style: italic;
}
.last-purchase-box.never .ps-line > i { color: var(--dm-fg-adb5bd, #adb5bd); }
/* Schon im Entwurf / noch nicht geliefert: Gefahr einer Doppelbestellung */
.last-purchase-box.warn {
    background: var(--dm-bg-ffe69c, #ffe69c);
    border-color: #ff8800;
    color: var(--dm-fg-663c00, #663c00);
}
.last-purchase-box.warn .ps-draft > i { color: #cc6600; }

/* Einstellungen (/admin/settings, docs/SETTINGS.md): Speichern-Leiste je Reiter bleibt beim Scrollen
   unten im Blick (wie list-sticky-bottom); Hintergrund = Karte, damit nichts durchscheint. */
.settings-save-bar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    background: var(--bs-card-bg, var(--bs-body-bg));
}

/* Projektnummer vor dem Titel (project_label_html(), helpers.php): gedämpfte
   Monospace-Kennung, bricht nie um; Farbe folgt dem Dunkelmodus über --dm-fg-6c757d. */
.project-no {
    font-family: var(--bs-font-monospace);
    font-size: .875em;
    font-weight: 400;
    color: var(--dm-fg-6c757d, #6c757d);
    white-space: nowrap;
}

/* Kopf von Artikel-Stammblatt und -Maske (articles/_kopf.php, Variante G 2026-10-28): Artikelnummer und
   Bezeichnung gleichrangig in beschrifteten Spalten, ab der zweiten Spalte mit Trennstrich. Am Handy
   (Spalten untereinander) ohne Strich. */
.art-kopf-label {
    font-size: .7rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--dm-fg-6c757d, #6c757d);
}
.art-kopf-col + .art-kopf-col {
    border-left: 1px solid var(--bs-border-color);
    padding-left: 1.5rem;
    margin-left: .5rem;
}
/* Bezeichnung bricht NEBEN der Nummer um (2026-11-04), statt als Ganzes in die naechste Zeile zu springen */
.art-kopf-name { flex: 1 1 20rem; min-width: 0; }
.art-kopf-name h1 { overflow-wrap: anywhere; }
@media (max-width: 575.98px) {
    .art-kopf-col + .art-kopf-col { border-left: 0; padding-left: 0; margin-left: 0; }
}
/* Dauerrechnung: Positionen wie das Lieferschein-Formular (rechnungen/dauer/form.php + beleg-form.js,
   automatisches Tabellen-Layout wie delivery_notes/form.php) */
#recInvForm #itemsTable td { overflow: visible !important; position: relative; }
#recInvForm #itemsTable .article-search-dropdown { z-index: 9999 !important; }
/* Einzelpreis + Knopf "Artikelpreis" teilen sich die schmale Preisspalte */
#recInvForm #itemsTable .row-unit-price { min-width: 0; }
/* Schildchen "manuell"/"fest" auf der Oberkante der Zelle - ragen nicht in die Kopfzeile */
#recInvForm #itemsTable .row-manual-badge { top: 0; }
/* Fester Preis (assets/js/recurring-invoice-form.js): Feld hervorgehoben + Schildchen "fest" */
#recInvForm .item-row.ri-price-fixed .row-unit-price {
    background-color: var(--dm-bg-fff3cd, #fff3cd); border-color: var(--dm-bd-ffe69c, #ffe69c); font-weight: 600;
}
#recInvForm .item-row .ri-fixed-badge {
    position: absolute; top: 0; left: 6px; z-index: 2; cursor: help;
    font: 600 9px/1 system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; letter-spacing: .02em;
    padding: 2px 5px; border-radius: 8px; white-space: nowrap;
    background: var(--dm-bg-fff3cd, #fff3cd); color: var(--dm-fg-664d03, #664d03);
    border: 1px solid var(--dm-bd-ffe69c, #ffe69c);
}
.ri-fixed-badge-static, .ri-manual-badge-static {
    background: var(--dm-bg-fff3cd, #fff3cd); color: var(--dm-fg-664d03, #664d03);
    border: 1px solid var(--dm-bd-ffe69c, #ffe69c); cursor: help;
}
