/* Project navigation sidebar */
.project-sidebar {
    background: #ffffff;
    border: 1px solid var(--tm-border);
    border-radius: 8px;
    overflow: hidden;
    position: sticky;
    top: calc(var(--app-header-h, 56px) + 1.5rem);
    max-height: calc(100dvh - var(--app-header-h, 56px) - 44px);
    display: flex;
    flex-direction: column;
}

.project-sidebar-header {
    padding: 1rem;
    border-bottom: 1px solid var(--tm-border);
    background: var(--tm-surface-alt);
}

.project-sidebar-header h6 {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
}

.project-sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem 0;
}

.project-sidebar-link {
    display: flex;
    align-items: center;
    padding: 0.4rem 1rem;
    color: var(--tm-text);
    text-decoration: none;
    transition: all 0.2s ease;
    border-left: 3px solid transparent;
    gap: 0.75rem;
}

.project-sidebar-link:hover {
    background: var(--tm-surface-alt);
    color: var(--tm-text);
}

.project-sidebar-link.active {
    background: var(--tm-accent-soft);
    color: var(--tm-accent);
    border-left-color: var(--tm-accent);
    font-weight: 500;
}

.project-status-indicator {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.project-status-indicator.status-active {
    background: var(--tm-success);
}

.project-status-indicator.status-completed {
    background: var(--tm-accent);
}

.project-status-indicator.status-archived {
    background: var(--tm-text-muted);
}

.project-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
}

.project-sidebar-footer {
    padding: 1rem;
    border-top: 1px solid var(--tm-border);
    background: var(--tm-surface-alt);
}

/* Project detail cards */
.project-details-card {
    border: 1px solid var(--tm-border);
    border-radius: 8px;
    box-shadow: none;
    transition: box-shadow 0.2s ease;
}

.project-details-card:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.project-details-card .card-header {
    background: #ffffff;
    border-bottom: 1px solid var(--tm-border);
    padding: 1rem 1.25rem;
}

.project-details-card .card-title {
    font-size: 1rem;
    font-weight: 500;
    color: var(--tm-text);
}

.project-details-card .card-title i {
    color: var(--tm-text-muted);
}

.project-details-card .card-body {
    padding: 1.25rem;
}

.project-details-card .card-footer {
    background: var(--tm-surface-alt);
    border-top: 1px solid var(--tm-border);
    padding: 1rem 1.25rem;
}

.badge-status {
    font-weight: 500;
    padding: 0.35em 0.75em;
    font-size: 0.75rem;
    border-radius: 4px;
}

.badge-status.status-active {
    background: #e7f3ee;
    color: var(--tm-success);
}

.badge-status.status-completed {
    background: var(--tm-accent-soft);
    color: var(--tm-accent);
}

.badge-status.status-archived {
    background: var(--tm-surface-alt);
    color: var(--tm-text-muted);
}

.detail-label {
    font-size: 0.75rem;
    color: var(--tm-text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.5rem;
}

.detail-value {
    color: var(--tm-text);
    font-size: 0.95rem;
}

.avatar-circle {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--tm-success) 0%, #186e4c 100%);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: 0.875rem;
    flex-shrink: 0;
}

.member-name {
    font-weight: 500;
    color: var(--tm-text);
    font-size: 0.95rem;
}

.member-role {
    color: var(--tm-text-muted);
    font-size: 0.8rem;
}

.stat-item {
    padding: 0.5rem 0;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--tm-text);
    margin-bottom: 0.25rem;
}

.stat-label {
    color: var(--tm-text-muted);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.project-details-card .list-group-item {
    border-left: none;
    border-right: none;
    padding: 1rem 1.25rem;
    background: transparent;
    transition: background-color 0.2s ease;
}

.project-details-card .list-group-item:first-child {
    border-top: none;
}

.project-details-card .list-group-item:last-child {
    border-bottom: none;
}

.project-details-card .list-group-item:hover {
    background: var(--tm-surface-alt);
}

.module-list-item {
    border-left: 3px solid transparent;
    transition: all 0.2s ease;
}

.module-list-item:hover {
    border-left-color: var(--tm-accent);
    background: var(--tm-surface-alt) !important;
}

.module-list-item .drag-handle {
    opacity: 0.3;
    transition: opacity 0.2s ease;
}

.module-list-item:hover .drag-handle {
    opacity: 1;
}

.module-list-item .badge {
    font-size: 0.75rem;
    font-weight: 500;
}

@media (max-width: 992px) {
    .project-sidebar {
        position: relative;
        top: 0;
        max-height: none;
        margin-bottom: 2rem;
    }
}

/* Task forms */
.form-section {
    margin-bottom: 2rem;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--tm-border);
}

.form-section:last-child {
    border-bottom: none;
    margin-bottom: 0;
}

.section-header {
    margin-bottom: 1rem;
    font-weight: 600;
    color: var(--tm-text);
}

.assignment-item {
    background-color: var(--tm-surface-alt);
    border: 1px solid var(--tm-border);
    border-radius: 0.375rem;
    padding: 0.75rem;
    margin-bottom: 0.75rem;
}

.recurring-options {
    padding: 1rem;
    background-color: var(--tm-surface-alt);
    border-radius: 0.375rem;
    margin-top: 1rem;
}

.markdown-help {
    font-size: 0.875rem;
    color: var(--tm-text-muted);
}

.priority-preview {
    width: 4px;
    height: 20px;
    display: inline-block;
    margin-right: 0.5rem;
    border-radius: 2px;
}

.priority-urgent {
    background-color: var(--tm-danger);
}

.priority-high {
    background-color: var(--tm-warning);
}

.priority-normal {
    background-color: var(--tm-text-muted);
}

.priority-low {
    background-color: var(--tm-success);
}

.task-priority-urgent {
    border-left: 5px solid var(--tm-danger);
}

.task-priority-high {
    border-left: 5px solid var(--tm-warning);
}

.task-priority-normal {
    border-left: 5px solid var(--tm-text-muted);
}

.task-priority-low {
    border-left: 5px solid var(--tm-success);
}

.status-badge {
    font-size: 0.875rem;
    padding: 0.5rem 1rem;
}

/* Dashboard and Kanban */
.quick-task-modal .form-label {
    font-size: 0.875rem;
    margin-bottom: 0.25rem;
}

.quick-task-modal .form-control,
.quick-task-modal .form-select {
    font-size: 0.875rem;
    padding: 0.375rem 0.75rem;
}

.quick-task-modal .btn {
    font-size: 0.875rem;
}

.priority-badge {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    margin-right: 0.5rem;
}

.priority-very_low {
    background-color: var(--tm-text-faint);
}

.priority-low {
    background-color: var(--tm-success);
}

.priority-normal {
    background-color: var(--tm-accent);
}

.priority-high {
    background-color: var(--tm-warning);
}

.priority-very_high {
    background-color: var(--tm-danger);
}

#backboard-project-filter {
    font-size: 0.75rem;
    border: 1px solid var(--tm-border);
    background-color: var(--tm-surface-alt);
    transition: all 0.2s ease;
    opacity: 0.7;
}

#backboard-project-filter:hover,
#backboard-project-filter:focus {
    opacity: 1;
    border-color: var(--tm-text-faint);
}

#backboard-project-filter option {
    font-size: 0.875rem;
}

.hours-summary {
    font-family: monospace;
    font-size: 0.75rem;
    font-weight: 500;
}

.kanban-card.drag-over-top {
    border-top: 3px solid var(--tm-accent);
}

.kanban-card.drag-over-bottom {
    border-bottom: 3px solid var(--tm-accent);
}

.kanban-card.task-done {
    opacity: 0.7;
}

.kanban-card.task-done .card-title,
.kanban-card.task-done .text-muted,
.kanban-card.task-done .small {
    color: var(--tm-text-muted) !important;
}

.kanban-card.task-done .card {
    background-color: var(--tm-surface-alt);
}

.editable-hours {
    cursor: pointer;
    border-bottom: 1px dashed var(--tm-text-faint);
    transition: all 0.2s;
}

.editable-hours:hover {
    color: var(--tm-accent);
    border-bottom-color: var(--tm-accent);
    background-color: var(--tm-accent-soft);
}

.editable-hours-input {
    width: 60px;
    padding: 0 4px;
    font-size: inherit;
    border: 1px solid var(--tm-accent);
    border-radius: 3px;
    outline: none;
}

/* Inline-Editing im Task-Detail-Modal: Klick-to-Edit-Werte (Termine, Soll-Stunden) */
.inline-editable {
    cursor: pointer;
    border-bottom: 1px dashed var(--tm-text-faint);
    transition: all 0.2s;
}

.inline-editable:hover {
    color: var(--tm-accent);
    border-bottom-color: var(--tm-accent);
    background-color: var(--tm-accent-soft);
}

.quick-task-trigger {
    cursor: pointer;
}

/* Das kleine Plus im Spaltenkopf: Hauptfarbe statt des frueheren
   Grau-auf-Weiss (praktisch unsichtbar). Ruhig im Grundzustand, beim
   Ueberfahren voll da und einen Hauch groesser — die Einladung "hier
   entsteht etwas" darf man spueren, ohne dass sie schreit. Bewusst auf
   .kanban-header begrenzt: Der grosse Toolbar-Knopf traegt dieselbe
   Klasse und hat sein eigenes Kleid. */
.kanban-header .quick-task-trigger {
    font-size: 1rem;
    color: var(--tm-success);
    opacity: 0.65;
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.kanban-header .quick-task-trigger:hover,
.kanban-header .quick-task-trigger:focus-visible {
    opacity: 1;
    transform: scale(1.15);
}

.btn.navbar-quick-task-trigger,
#userFilterDropdown {
    border-radius: var(--tm-radius-pill);
}

.navbar-quick-task-trigger {
    color: #fff !important;
    text-shadow: none;
}

.navbar-quick-task-trigger:hover,
.navbar-quick-task-trigger:focus {
    color: var(--tm-success) !important;
    background-color: #fff;
    border-color: var(--tm-success);
}

.task-detail-trigger,
.task-status-toggle,
.timer-toggle {
    cursor: pointer;
}

.dashboard-project-name {
    max-width: 150px;
}

/* Kanban navigation.
   Die frueheren rgba-Weisstoene samt backdrop-filter stammten aus der Zeit
   eines dunklen Headers — auf der heutigen weissen Leiste waren die Knoepfe
   praktisch randlos. Jetzt die normalen Flaechen-Tokens. Keine
   Einblend-Animation mehr: Die Navigation wird bei jedem AJAX-Tageswechsel
   neu eingesetzt (dashboard-navigate.js), die Animation lief also bei jedem
   Wechsel erneut und liess die Leiste flackern. */
.kanban-nav-card {
    position: relative;
}

.kanban-nav-card .btn-group {
    background: var(--tm-surface);
    border-radius: var(--tm-radius-sm);
    border: 1px solid var(--tm-border);
}

.kanban-nav-btn,
.kanban-nav-today {
    border: none !important;
    color: var(--tm-text) !important;
    font-weight: 500;
    transition: background-color 0.15s ease;
    min-width: 40px;
    background-color: transparent !important;
}

.kanban-nav-btn i,
.kanban-nav-today i {
    color: var(--tm-text-muted) !important;
}

/* Kein translateY beim Hover: Knoepfe, die unter dem Zeiger wegruecken,
   wirken unruhig und verfehlen Klicks. Betonung nur ueber Flaeche. */
.kanban-nav-btn:hover,
.kanban-nav-today:hover {
    background-color: var(--tm-surface-alt) !important;
}

.kanban-nav-btn:hover i,
.kanban-nav-today:hover i {
    color: var(--tm-text) !important;
}

/* "Heute" bei offset 0: als aktueller Standort markiert. */
.kanban-nav-today.active,
.kanban-nav-today.btn-light {
    background-color: var(--tm-accent-soft) !important;
    color: var(--tm-accent) !important;
    font-weight: 600;
}

.kanban-nav-today.active:hover {
    background-color: var(--tm-accent-soft) !important;
    color: var(--tm-accent) !important;
}

@media (max-width: 575.98px) {
    .kanban-nav-card .btn-group {
        border-radius: 0.375rem;
    }

    .kanban-nav-btn,
    .kanban-nav-today {
        min-width: 35px;
        font-size: 0.8rem;
    }
}


/* History timeline */
.history-timeline {
    position: relative;
    padding-left: 2rem;
}

.history-timeline::before {
    content: '';
    position: absolute;
    left: 0.5rem;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--tm-border);
}

.history-item {
    position: relative;
    padding-bottom: 1.5rem;
}

.history-item::before {
    content: '';
    position: absolute;
    left: -1.3rem;
    top: 0.25rem;
    width: 0.75rem;
    height: 0.75rem;
    background: var(--tm-text-muted);
    border-radius: 50%;
    border: 2px solid #fff;
}

.history-item.history-created::before {
    background: var(--tm-success);
}

.history-item.history-updated::before {
    background: var(--tm-warning);
}

.history-item.history-completed::before {
    background: var(--tm-accent);
}

.history-item.history-commented::before {
    background: #6f42c1;
}

.task-detail-page .history-item::before {
    left: -0.5rem;
}

/* Tiptap editor toolbar - klassenbasiert, damit Detailseite UND die
   Task-Modals (task-form-editor.js) dieselbe Optik teilen. */
.tiptap-toolbar {
    border: 1px solid var(--tm-border);
    border-bottom: none;
    border-radius: 0.375rem 0.375rem 0 0;
    padding: 0.5rem;
    background: var(--tm-surface-alt);
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
}

.tiptap-toolbar button {
    padding: 0.375rem 0.75rem;
    border: 1px solid var(--tm-border);
    background: var(--tm-surface);
    border-radius: 0.25rem;
    cursor: pointer;
    font-size: 0.875rem;
    transition: all 0.2s;
}

.tiptap-toolbar button:hover {
    background: var(--tm-border);
}

.tiptap-toolbar button.is-active {
    background: var(--tm-accent);
    color: white;
    border-color: var(--tm-accent);
}

/* Folgt der Editor direkt auf eine Toolbar, schliessen beide buendig ab. */
.tiptap-toolbar + .tiptap-editor {
    border-radius: 0 0 0.375rem 0.375rem;
}

/* Tiptap-Placeholder (extension-placeholder setzt data-placeholder +
   .is-empty auf den ersten leeren Absatz). */
.tiptap-editor p.is-empty:first-child::before {
    content: attr(data-placeholder);
    color: var(--tm-text-muted);
    float: left;
    height: 0;
    pointer-events: none;
}

#tiptap-container .tiptap-editor {
    border: 1px solid var(--tm-border);
    border-radius: 0 0 0.375rem 0.375rem;
    padding: 0.75rem;
    min-height: 400px;
    background: var(--tm-surface);
}

#tiptap-container .tiptap-editor:focus-within {
    outline: none;
    border-color: #86b7fe;
    box-shadow: 0 0 0 0.25rem rgba(79, 91, 213, 0.18);
}

.tiptap-color-input {
    width: 32px;
    height: 32px;
    border: 1px solid var(--tm-border);
    border-radius: 0.25rem;
    cursor: pointer;
    padding: 2px;
}

/* Navbar project dropdown */
.projects-dropdown-menu {
    min-width: 300px;
}

.project-dropdown-name {
    max-width: 180px;
}

/* Kompaktere Links im Projekt-Dropdown; erste Zeile (dropdown-header) und
   Badge-Text bleiben bewusst unverändert. */
.projects-dropdown-menu .dropdown-item {
    font-size: 0.85rem;
}

.projects-dropdown-menu .badge {
    font-size: 0.7rem;
}

.dropdown-item {
    transition: background-color 0.15s ease-in-out;
}

.dropdown-item:hover,
.dropdown-item:focus {
    background-color: var(--tm-surface-alt);
    color: var(--tm-text) !important;
}

.dropdown-item.active {
    background-color: var(--tm-accent-soft);
    color: var(--tm-accent) !important;
}

.dropdown-item.active:hover,
.dropdown-item.active:focus {
    background-color: var(--tm-accent-soft);
    color: var(--tm-accent) !important;
}

.badge-sm {
    font-size: 0.65em;
}

.dropdown-menu {
    border: 1px solid var(--tm-border);
    border-radius: var(--tm-radius-sm);
    box-shadow: var(--tm-shadow-md);
}

@media (max-width: 768px) {
    .dropdown-menu {
        min-width: 250px !important;
    }
}

/* Recurring project tasks */
.recurring-group-card {
    margin-bottom: 1.5rem;
}

.recurring-group-card .card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.recurring-task-row {
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.recurring-task-row:hover {
    background-color: #f1f5ff;
}

.recurring-meta {
    font-size: 0.85rem;
}

#recurEditHint {
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    transition: opacity 0.4s ease, max-height 0.4s ease, margin 0.4s ease;
    margin-bottom: 0 !important;
}

#recurEditHint.is-visible {
    opacity: 1;
    max-height: 200px;
    margin-bottom: 1rem !important;
}

/* Task create */
#recurringOptions {
    display: none;
}

#recurringOptions.show {
    display: block;
}

/* Task edit */
.changed-field {
    background-color: #fff3cd;
    border-color: #ffeaa7 !important;
    box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.25) !important;
    transition: all 0.3s ease;
}

.changed-assignments {
    border: 2px solid var(--tm-warning);
    border-radius: 0.375rem;
    background-color: #fff3cd;
}

.changed-assignments .card-header {
    background-color: var(--tm-warning);
    color: var(--tm-text);
    font-weight: 600;
}

/* Task list */
.task-list-table tbody tr {
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.task-list-table tbody tr:hover {
    background-color: rgba(0, 0, 0, 0.02);
}

.task-list-table .border-start.border-danger.border-3,
.task-list-table .border-start.border-warning.border-3 {
    border-left-width: 4px !important;
}

@media (max-width: 768px) {
    .task-list-table-wrapper {
        font-size: 0.875rem;
    }

    .task-list-table td small {
        font-size: 0.75rem;
    }
}

    /* Task detail */
    .border-purple {
        border-color: #6f42c1 !important;
    }

    .attachment-item {
        transition: all 0.2s ease;
    }

    .attachment-item:hover {
        background-color: var(--tm-surface-alt);
    }

    .task-section {
        margin-bottom: 2rem;
    }

    .application-link {
        transition: all 0.2s ease;
    }

    .application-link:hover {
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }

    .tiptap-editor {
        border: 1px solid var(--tm-border);
        border-radius: 0.375rem;
        padding: 0.75rem;
        min-height: 200px;
        background: white;
        outline: none;
    }

    .tiptap-editor:focus {
        border-color: #86b7fe;
        box-shadow: 0 0 0 0.25rem rgba(79, 91, 213, 0.18);
    }

    .tiptap-editor p {
        margin: 0 0 1rem 0;
    }

    .tiptap-editor p:last-child {
        margin-bottom: 0;
    }

    .tiptap-editor ul[data-type="taskList"] {
        list-style: none;
        padding: 0;
    }

    .tiptap-editor ul[data-type="taskList"] li {
        display: flex;
        align-items: flex-start;
        margin-bottom: 0.5rem;
    }

    .tiptap-editor ul[data-type="taskList"] li label {
        display: flex;
        align-items: center;
        cursor: pointer;
        margin-right: 0.5rem;
        margin-bottom: 0;
    }

    .tiptap-editor ul[data-type="taskList"] li input[type="checkbox"] {
        margin-right: 0.5rem;
    }

    .tiptap-editor ul[data-type="taskList"] li div {
        flex: 1;
    }

/* =========================================================================
   Globale Theme- & Layout-Styles
   (aus dem Inline-<style> in app/Views/layouts/main.php hierher verschoben)
   ========================================================================= */

:root {
    --tm-bg: #F7F7F6;
    --tm-surface: #FFFFFF;
    --tm-surface-muted: #FAFAF9;
    --tm-surface-alt: #F0F0EE;
    --tm-border: #E6E6E2;
    --tm-border-subtle: #EFEFEC;
    --tm-text: #1A1B1E;
    --tm-text-muted: #6E7076;
    --tm-text-faint: #9A9CA3;
    --tm-primary: #24262B;
    --tm-primary-hover: #34363C;
    --tm-accent: #4F5BD5;
    --tm-accent-soft: rgba(79, 91, 213, .08);
    --tm-success: #1F8A5F;
    --tm-success-soft: rgba(31, 138, 95, .08);
    --tm-warning: #B7791F;
    --tm-danger: #C4392F;
    --tm-radius: 10px;
    --tm-radius-sm: 6px;
    --tm-radius-pill: 999px;
    --tm-shadow-xs: 0 1px 2px rgba(20, 20, 20, .05);
    --tm-shadow-sm: 0 1px 3px rgba(20, 20, 20, .06);
    --tm-shadow-md: 0 4px 10px rgba(20, 20, 20, .07);

    /* Aliase für bestehende Referenzen im Rest der Datei */
    --primary-color: var(--tm-primary);
    --success-color: var(--tm-success);
    --warning-color: var(--tm-warning);
    --danger-color: var(--tm-danger);
    --info-color: var(--tm-accent);
    --light-bg: var(--tm-surface-muted);
    --dark-bg: var(--tm-text);

    /* Bootstraps eigene RGB-Variablen umbiegen: .bg-*/.text-bg-*/.border-*
       Utility-Klassen (u. a. Badges wie "badge bg-warning") referenzieren
       diese global, anders als .btn-*/.alert-*, die feste Hex-Fallbacks
       backen (dafür gibt es die separaten Overrides weiter unten).
       --bs-primary-rgb bewusst auf Success-Grün gemappt: dadurch werden
       .text-primary/.bg-primary/.border-primary (Headline-Icons, Card-Header,
       Badges) grün, während .btn-primary (echte CTA-Buttons) unverändert
       über --tm-primary weiterhin nahschwarz bleibt. */
    --bs-primary-rgb: 31, 138, 95;
    --bs-secondary-rgb: 110, 112, 118;
    --bs-success-rgb: 31, 138, 95;
    --bs-danger-rgb: 196, 57, 47;
    --bs-warning-rgb: 183, 121, 31;
    --bs-info-rgb: 79, 91, 213;
    --bs-light-rgb: 240, 240, 238;
    --bs-dark-rgb: 26, 27, 30;
}

body {
    background-color: var(--tm-bg);
    color: var(--tm-text);
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    /* Kein padding-top mehr: Der Header ist sticky (im Dokumentfluss) und
       reserviert seinen Platz selbst — auch wenn er bei Zoom umbricht. */
}

/* Tastatur-Fokus ueberall gleich sichtbar. Bootstrap deckt nur einen Teil
   der Bedienelemente mit Fokus-Schatten ab; die App ist inzwischen stark
   tastaturbedient (QuickHelp, Pfeiltasten, Kuerzel). */
:focus-visible {
    outline: 2px solid var(--tm-accent);
    outline-offset: 2px;
}

/* Flash-Message-Alerts: gedämpfte Töne statt Bootstrap-Signalfarben */
.alert {
    border-radius: var(--tm-radius-sm);
    border-width: 1px;
}

.alert-success {
    --bs-alert-color: #145c40;
    --bs-alert-bg: #eaf5f0;
    --bs-alert-border-color: #cde7dc;
}

.alert-danger {
    --bs-alert-color: #8a271f;
    --bs-alert-bg: #fbebe9;
    --bs-alert-border-color: #f2cfcb;
}

.alert-warning {
    --bs-alert-color: #7a4f0f;
    --bs-alert-bg: #fbf1e2;
    --bs-alert-border-color: #f1ddb8;
}

.alert-info {
    --bs-alert-color: #33399b;
    --bs-alert-bg: #eeeffb;
    --bs-alert-border-color: #d4d7f5;
}

.navbar-brand {
    font-weight: 700;
    font-size: 1.25rem;
    display: flex;
    align-items: center;
    padding: 0.375rem 0;
}

/* Platzhalter-Marke: einfarbige Kachel statt Bild, bis eine endgueltige
   Marke feststeht (Redesign A/B geparkt). Das Zeichen ist bewusst Text,
   kein Asset — austauschen heisst: ein Zeichen aendern. */
.brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--tm-radius-sm);
    background: var(--tm-success);
    color: #fff;
    font-size: 1.25rem;
    line-height: 1;
    user-select: none;
}

/* Zweizeilige Kopfzeile: klebt als Ganzes oben, die Hoehe ist
   inhaltsgetrieben (misst js/common/header-height.js in --app-header-h).
   Bootstraps .sticky-top liefert position/top; z-index ueber den Karten
   und dem Kalender. */
.app-header {
    z-index: 1030;
    background: var(--tm-surface);
    border-bottom: 1px solid var(--tm-border);
}

/* Zeile 2: Board-Werkzeuge, optisch leicht abgesetzt von der Navigation.
   Eine linksbuendige Reihe (Projekt, Filter, "+", Tagesumschalter) —
   Zentrierung ist raus (Entscheidung Titus, 02.08.2026), die Werkzeuge
   stehen am Lese-Anfang und brechen bei Platzmangel einfach um. */
.dashboard-toolbar {
    background: var(--tm-surface-muted);
    border-top: 1px solid var(--tm-border-subtle);
}

.dashboard-toolbar .dashboard-toolbar-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    column-gap: 0.75rem;
    row-gap: 0.25rem;
}

.navbar .navbar-nav .nav-link {
    padding: 0.375rem 0.75rem;
    color: var(--tm-text-muted);
}

.navbar .navbar-nav .nav-link:hover,
.navbar .navbar-nav .nav-link:focus,
.navbar .navbar-nav .nav-link.active {
    color: var(--tm-success);
}

.navbar .dropdown-item.active,
.navbar .dropdown-item.active:hover,
.navbar .dropdown-item.active:focus {
    background-color: rgba(31, 138, 95, .08);
    color: var(--tm-success) !important;
}

.main-content {
    /* Der sticky Header reserviert seinen Platz selbst — hier nur noch
       Atemraum, kein Ausgleich einer fixierten Leiste. */
    padding-top: 0.75rem;
    padding-bottom: 2rem;
}

.card {
    border: 1px solid var(--tm-border);
    border-radius: var(--tm-radius);
    box-shadow: var(--tm-shadow-xs);
    transition: box-shadow 0.2s ease;
}

.card:hover {
    box-shadow: var(--tm-shadow-sm);
}

.btn {
    border-radius: var(--tm-radius-sm);
    font-weight: 500;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.btn-primary {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--tm-primary);
    --bs-btn-border-color: var(--tm-primary);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--tm-primary-hover);
    --bs-btn-hover-border-color: var(--tm-primary-hover);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--tm-primary-hover);
    --bs-btn-active-border-color: var(--tm-primary-hover);
    --bs-btn-disabled-bg: var(--tm-primary);
    --bs-btn-disabled-border-color: var(--tm-primary);
    --bs-btn-focus-shadow-rgb: 36, 38, 43;
}

.btn-outline-primary {
    --bs-btn-color: var(--tm-primary);
    --bs-btn-border-color: var(--tm-primary);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--tm-primary);
    --bs-btn-hover-border-color: var(--tm-primary);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--tm-primary);
    --bs-btn-active-border-color: var(--tm-primary);
}

.btn-secondary,
.btn-outline-secondary {
    --bs-btn-color: var(--tm-text-muted);
    --bs-btn-bg: var(--tm-surface);
    --bs-btn-border-color: var(--tm-border);
    --bs-btn-hover-color: var(--tm-text);
    --bs-btn-hover-bg: var(--tm-surface-alt);
    --bs-btn-hover-border-color: var(--tm-border);
    --bs-btn-active-color: var(--tm-text);
    --bs-btn-active-bg: var(--tm-surface-alt);
    --bs-btn-active-border-color: var(--tm-border);
}

.btn-success {
    --bs-btn-bg: var(--tm-success);
    --bs-btn-border-color: var(--tm-success);
    --bs-btn-hover-bg: #186e4c;
    --bs-btn-hover-border-color: #186e4c;
    --bs-btn-active-bg: #186e4c;
    --bs-btn-active-border-color: #186e4c;
}

.btn-danger {
    --bs-btn-bg: var(--tm-danger);
    --bs-btn-border-color: var(--tm-danger);
    --bs-btn-hover-bg: #a52e26;
    --bs-btn-hover-border-color: #a52e26;
    --bs-btn-active-bg: #a52e26;
    --bs-btn-active-border-color: #a52e26;
}

.footer {
    background-color: var(--dark-bg);
    color: white;
    padding: 1rem 0;
    margin-top: auto;
}

.min-vh-100 {
    display: flex;
    flex-direction: column;
}

/* Kanban Board Styles.

   SPALTENBREITEN: Die drei Werte unten sind die EINZIGE Quelle. Sie stehen
   als CSS-Variablen hier, weil sie von drei Seiten gelesen werden — vom
   Layout selbst, vom Platz-Abgleich (dashboard-columns.js) und vom
   Ziehgriff (dashboard-column-resize.js). Wer eine davon aendert, aendert
   alle drei Verhalten konsistent; frueher standen dieselben Zahlen als
   Konstanten im JavaScript und drifteten auseinander.

   Die Grenzen (--tm-col-*-min/max) sind bewusst ebenfalls Variablen: Der
   Vertragstest BoardColumnWidthContractTest liest sie hier aus und
   vergleicht sie mit den Werten im JavaScript. */
.kanban-board {
    /* Zwei Ebenen, mit Absicht:
       *-default = die Vorgabe des Entwurfs (Grundlage jedes Zuruecksetzens),
       *-user    = die gezogene Breite, gesetzt auf :root.
       Getrennt, weil sonst zweierlei kaputtgeht: Das Kopf-Skript
       (js/common/board-widths-early.js) setzt die Nutzerbreite VOR dem
       ersten Zeichnen — laege sie auf derselben Variablen, haette das
       Ziehskript die Vorgabe nie gesehen und "Zuruecksetzen" wuerde auf den
       zuletzt gezogenen Wert zuruecksetzen statt auf den Entwurf. */
    --tm-col-day-default: 250px;
    --tm-col-backboard-default: 250px;
    /* 221 = 260 * 0,85: Der Tageskalender ist bei jedem Zuruecksetzen
       bewusst 15 % schmaler als frueher — er ist Beiwerk, die Tagesspalten
       sind die Arbeitsflaeche (Entscheidung 02.08.2026). */
    --tm-col-calendar-default: 221px;

    --tm-col-day: var(--tm-col-day-user, var(--tm-col-day-default));
    --tm-col-backboard: var(--tm-col-backboard-user, var(--tm-col-backboard-default));
    --tm-col-calendar: var(--tm-col-calendar-user, var(--tm-col-calendar-default));

    /* 170 = 200 * 0,85: Die Mindestbreite einer Tagesspalte ist bewusst ein
       weiteres Mal um 15 % gesunken (Entscheidung 02.08.2026). Sie ist seither
       nicht mehr nur eine Untergrenze fuers Ziehen, sondern die Grundlage der
       AUTOMATISCHEN Obergrenze: Wie viele Tagesspalten das Board anbietet,
       ergibt sich aus der Frage, wie viele bei dieser Breite nebeneinander
       passen. Wer hier hoeher geht, nimmt dem Board Spalten weg. */
    --tm-col-day-min: 170px;
    --tm-col-day-max: 460px;
    --tm-col-backboard-min: 200px;
    --tm-col-backboard-max: 460px;
    --tm-col-calendar-min: 180px;
    --tm-col-calendar-max: 520px;

    display: flex;
    /* 12 px: exakt die Breite des Ziehgriffs. Damit liegt er vollstaendig
       IM Spalt und nicht auf der Spalte — sonst deckt er die Bildlaufleiste
       der Kartenliste ab und schluckt Klicks am Spaltenrand. */
    gap: 0.75rem;
    overflow-x: auto;
    padding: 0;
    height: calc(100dvh - var(--app-header-h, 56px));
}

.kanban-column {
    /* Tagesspalten: Die eingestellte Breite ist die UNTERGRENZE, nicht das
       Endmass — flex-grow verteilt den Rest gleichmaessig, damit neben dem
       angepinnten Kalender keine Luecke entsteht. Wer breiter zieht,
       bekommt darum irgendwann eine Spalte weniger (Platz-Abgleich), nie
       einen Leerraum. */
    flex: 1 1 var(--tm-col-day);
    min-width: var(--tm-col-day);
    position: relative;
    background-color: var(--tm-surface-muted);
    border-radius: var(--tm-radius);
    border: 1px solid var(--tm-border);
    display: flex;
    flex-direction: column;
    height: 100%;
}

/* Sobald der Nutzer eine Tagesbreite gezogen hat, ist sie eine ZUSAGE:
   flex-grow aus, gezogen == gerendert. Ohne diese Klasse strecken sich die
   Spalten sofort wieder ueber den Restplatz — man zieht auf 300 px und
   bekommt 340, die Breite waere nur ein Vorschlag. Ohne eigene Breite
   bleibt flex-grow an, damit das Board im Auslieferungszustand sauber
   ausgefuellt ist statt mit einem Rand zu enden.

   Die beiden :not() sind nicht kosmetisch: Ohne sie traf dieser Selektor
   (0-3-0) auch Kalender und Backboard und schlug deren eigene Regeln
   (0-2-0). Die Randbereiche haben ihre Breite als Ansage des Nutzers, nicht
   als Restverteilung — ihr flex-grow steht in ihrer eigenen Regel und
   gehoert nicht hierher. Festgenagelt von BoardColumnWidthContractTest. */
.kanban-board.has-day-width .kanban-column:not(.calendar-column):not([data-date="backboard"]) {
    flex-grow: 0;
}

/* Backboard und Kalender behalten ihre gezogene Breite exakt (kein
   flex-grow): Sie sind Randbereiche, ihre Groesse ist eine Ansage des
   Nutzers und keine Restverteilung. */
.kanban-column[data-date="backboard"] {
    flex: 0 0 var(--tm-col-backboard);
    min-width: var(--tm-col-backboard);
}

/* Heutige Spalte: gruene Oberkante als Standort-Anker. */
.kanban-column.is-today {
    border-top: 3px solid var(--tm-success);
}

/* Spaltenanzahl-Steuerung in der Werkzeugzeile: bewusst klein und ruhig —
   sie steht neben der Tagesnavigation und darf ihr nicht die Schau stehlen.
   Der Reset traegt als einziger die volle Hauptfarbe, weil er nur auftaucht,
   wenn es etwas zurueckzusetzen gibt. */
.board-column-controls {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    padding: 0.1rem 0.25rem;
    border: 1px solid var(--tm-border);
    border-radius: var(--tm-radius-pill);
    background: var(--tm-surface);
}

/* Gestapelt gibt es kein "nebeneinander": Alle Spalten sind sichtbar, die
   Anzahl ist keine Frage mehr, und die Schritt-Knoepfe waeren dauerhaft
   grau. Ein Bedienelement, das nie etwas tun kann, gehoert weg. */
@media (max-width: 768px) {
    .board-column-controls {
        display: none;
    }
}

.board-columns-step {
    --bs-btn-padding-x: 0.4rem;
    --bs-btn-padding-y: 0.05rem;
    color: var(--tm-success);
    border: 0;
    background: none;
    line-height: 1;
}

.board-columns-step:hover,
.board-columns-step:focus-visible {
    color: #fff;
    background: var(--tm-success);
}

.board-columns-count {
    min-width: 2.6rem;
    text-align: center;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    color: var(--tm-text-muted);
    user-select: none;
}

.board-columns-reset {
    --bs-btn-padding-x: 0.4rem;
    --bs-btn-padding-y: 0.05rem;
    line-height: 1;
    border-radius: var(--tm-radius-pill);
}

/* =========================================================================
   Eingeblendete Tastenkuerzel (Haken neben QuickHelp, js/common/key-hints.js).

   Das Abzeichen zeigt `data-key-hint` des Elements — dasselbe Attribut, ueber
   das die Kuerzel-Skripte ihr Ziel finden. Es kann also nichts behaupten, was
   nicht auch passiert.

   Absichtlich auffaellig (Modul-Gruen, weisse Schrift) und absichtlich
   ueberlappend an der Ecke: Das ist ein Lernmodus, kein Dauerzustand — man
   schaltet ihn ein, prägt sich zwei Tasten ein und wieder aus. Ein dezentes
   Abzeichen haette diesen Zweck verfehlt.
   ========================================================================= */
.tm-show-key-hints [data-key-hint] {
    position: relative;
    overflow: visible;
}

.tm-show-key-hints [data-key-hint]::after {
    content: attr(data-key-hint);
    position: absolute;
    top: -0.35rem;
    right: -0.35rem;
    z-index: 20;
    padding: 0 0.25rem;
    min-width: 1.05rem;
    border-radius: 0.25rem;
    background: var(--tm-success);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: 0.02em;
    text-align: center;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 1px 3px rgba(20, 20, 20, 0.35);
}

/* In der Kopfzeile sitzen die Elemente dicht an dicht — dort rueckt das
   Abzeichen nach innen, damit es nicht ueber den Nachbarn haengt. */
.tm-show-key-hints .navbar-nav [data-key-hint]::after,
.tm-show-key-hints .kanban-nav-card [data-key-hint]::after {
    top: -0.15rem;
    right: -0.15rem;
}

/* Der Haken selbst: klein und ruhig, er steht neben QuickHelp und soll
   dessen Knopf nicht die Schau stehlen. */
.key-hints-switch {
    font-size: 0.78rem;
    color: var(--tm-text-muted);
    padding-left: 2.2em;
}

.key-hints-switch .form-check-input:checked {
    background-color: var(--tm-success);
    border-color: var(--tm-success);
}

.key-hints-switch .form-check-label {
    cursor: pointer;
    user-select: none;
}

@media (max-width: 991.98px) {
    /* Auf schmalen Geraeten gibt es keine Tastatur, an die sich die
       Abzeichen richten koennten. */
    .key-hints-switch {
        display: none;
    }
}

/* Schritt-Knoepfe an ihrer Grenze: sichtbar wirkungslos statt stumm
   wirkungslos. Bis 0.4.3 sahen sie immer gleich aus und quittierten den
   Klick je nach Lage mit einer Meldung oder mit gar nichts. */
.board-columns-step:disabled,
.board-columns-step[aria-disabled="true"] {
    color: var(--tm-text-faint);
    background: none;
    opacity: 0.55;
    cursor: default;
}

/* Tageskalender an/aus. Eingeschaltet traegt der Knopf die Hauptfarbe wie
   die uebrigen Board-Werkzeuge, ausgeschaltet ist er blass und
   durchgestrichen — der Zustand muss ohne Tooltip ablesbar sein. */
.board-calendar-toggle {
    --bs-btn-padding-x: 0.4rem;
    --bs-btn-padding-y: 0.05rem;
    position: relative;
    color: var(--tm-success);
    border: 0;
    background: none;
    line-height: 1;
}

.board-calendar-toggle:hover,
.board-calendar-toggle:focus-visible {
    color: #fff;
    background: var(--tm-success);
}

/* Der Hintergrund MUSS hier mit zurueckgenommen werden: Diese Regel steht
   nach :hover und gewinnt bei gleicher Spezifitaet — ohne die Zeile blieb
   beim Ueberfahren des ausgeschalteten Schalters graues Icon auf gruenem
   Grund stehen (Kontrast 1,6:1, der Strich verschwand mit). */
.board-calendar-toggle.is-off,
.board-calendar-toggle.is-off:hover,
.board-calendar-toggle.is-off:focus-visible {
    color: var(--tm-text-faint);
    background: none;
}

.board-calendar-toggle.is-off:hover,
.board-calendar-toggle.is-off:focus-visible {
    color: var(--tm-text-muted);
}

.board-calendar-toggle.is-off::after {
    content: '';
    position: absolute;
    left: 15%;
    right: 15%;
    top: 50%;
    border-top: 2px solid currentColor;
    transform: rotate(-20deg);
    pointer-events: none;
}

/* =========================================================================
   Ziehgriff fuer die Spaltenbreite (dashboard-column-resize.js).

   Sichtbarkeit ist hier die eigentliche Entwurfsfrage: Ein Griff, den man
   nur bei Hover sieht, findet niemand — einer, der staendig ins Auge
   springt, macht das Board unruhig. Kompromiss: ein schmaler, blasser
   Steg, der IMMER da ist, beim Ueberfahren in die Hauptfarbe wechselt und
   waechst. Die Trefferflaeche ist mit 12 px deutlich groesser als der
   sichtbare Steg (2 px) und liegt im Spaltenabstand, nicht auf dem Inhalt.
   ========================================================================= */
.kanban-col-resize {
    position: absolute;
    top: 0;
    bottom: 0;
    right: -12px;
    width: 12px;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: col-resize;
    /* Ohne touch-action rollt der Finger die Seite, statt zu ziehen. */
    touch-action: none;
    background: none;
    border: 0;
    padding: 0;
}

/* Waehrend ein Karten-Drag laeuft, ist der Griff DURCHLAESSIG. Grund:
   dragover/drop haengen an `.kanban-cards`; der Griff ist dessen
   Geschwister und liegt darueber. Ein paar Pixel Ueberlappung reichten
   sonst, damit eine Karte sichtbar an die Stelle wandert, das Drop-Ereignis
   aber nie ankommt — die Verschiebung waere optisch geglueckt und in
   Wahrheit nie gespeichert worden. */
.kanban-board.is-card-dragging .kanban-col-resize {
    pointer-events: none;
}

/* Kalenderspalte klebt rechts — ihr Griff gehoert an die linke Kante. */
.kanban-col-resize--left {
    right: auto;
    left: -12px;
}

/* Die letzte sichtbare Tagesspalte bekommt keinen eigenen Griff: Ihr Spalt
   gehoert bereits dem Kalendergriff, zwei Griffe im selben Spalt waeren
   ein Glueckstreffer, welcher reagiert. Markiert wird sie im Platz-Abgleich
   (dashboard-columns.js). Bleibt nur EINE Tagesspalte uebrig, behaelt sie
   ihren Griff — sonst liesse sich die Tagesbreite gar nicht mehr ziehen.

   Die Begruendung haengt vollstaendig am Kalendergriff — ist der Kalender
   abgeschaltet, belegt den Spalt niemand mehr, und die Unterdrueckung
   naehme dem Board stumm die Moeglichkeit, am rechten Rand zu ziehen.
   Deshalb das :not() auf der Wurzel. */
html:not(.tm-board-no-calendar) .kanban-board:not(.has-single-day) .kanban-column.is-last-visible-day > .kanban-col-resize {
    display: none;
}

/* OHNE KALENDER liegt die letzte Tagesspalte an der rechten Boardkante —
   ihr Griff behaelt seine Aufgabe (rechts davon kommt nichts mehr, was ihn
   uebernehmen koennte), muss aber nach INNEN rutschen.
   Bliebe er bei `right: -12px`, ragte er 12 px ueber die Kante hinaus und
   ginge damit in `scrollWidth` ein: Das Board meldete dauerhaft Ueberlauf,
   die Gegenprobe in dashboard-columns.js blendete daraufhin Spalte um
   Spalte aus — bis eine uebrig war — und eine waagerechte Bildlaufleiste
   bliebe trotzdem stehen. Ein absolut positionierter Nachfahre zaehlt zum
   Scroll-Bereich seines Containers, auch wenn er nur ein Griff ist. */
.tm-board-no-calendar .kanban-column.is-last-visible-day > .kanban-col-resize {
    right: 0;
}

.kanban-col-resize::before {
    content: '';
    width: 2px;
    height: 26px;
    border-radius: 1px;
    background: var(--tm-border);
    transition: background-color 0.15s ease, height 0.15s ease, width 0.15s ease;
}

.kanban-col-resize:hover::before,
.kanban-col-resize:focus-visible::before,
.kanban-col-resize.is-resizing::before {
    background: var(--tm-success);
    width: 3px;
    height: 52px;
}

/* Der Fokusring gehoert an den Steg, nicht an die unsichtbare Trefferflaeche. */
.kanban-col-resize:focus {
    outline: none;
}

.kanban-col-resize:focus-visible::before {
    box-shadow: 0 0 0 2px var(--tm-success-soft);
}

/* Waehrend des Ziehens: Cursor ueberall gleich, keine Textauswahl, keine
   Hover-Effekte auf Karten (die sonst unter dem Zeiger aufblinken). */
body.is-col-resizing,
body.is-col-resizing * {
    /* !important begruendet: Karten, Knoepfe und Links bringen eigene
       Cursor mit. Waehrend des Zugs muss der Zeiger ueberall derselbe
       bleiben, sonst flackert er beim Ueberfahren der Spalten. */
    cursor: col-resize !important;
    user-select: none;
}

body.is-col-resizing .kanban-card:hover .card {
    box-shadow: var(--tm-shadow-xs);
    border-color: var(--tm-border);
}

/* Unter dem Mobil-Umbruch stapeln sich die Spalten — eine Breite zu ziehen
   ergibt dort keinen Sinn. */
@media (max-width: 768px) {
    .kanban-col-resize {
        display: none;
    }
}

/* Vom Platz-Abgleich ausgeblendete Tagesspalten (dashboard-columns.js):
   Die Einstellung "Anzahl der Tagesspalten" ist eine OBERGRENZE, sichtbar
   ist nur, was neben Backboard und Kalender vollstaendig passt. Damit
   scrollt das Board nie horizontal — der angepinnte Kalender kann weder
   abgeschnitten werden noch eine Spalte ueberdecken. */
.kanban-column.is-overflow-hidden {
    display: none;
}

/* Backboard und Tagesübersicht sind sekundäre Bereiche: das Board (die
   Tagesspalten) soll den visuellen Fokus behalten. NUR die Flaechenfarbe
   ist beiden gemeinsam — alles Weitere gehoert dem Kalender allein.
   (Bis 0.4.2 stand hier ein gemeinsamer Block mit `position: sticky` und
   der Kalenderbreite: Das Backboard war damit ebenfalls rechts angepinnt
   und uebernahm die falsche Breite, weil diese Regel spaeter steht als
   seine eigene.) */
.kanban-column[data-date="backboard"],
.kanban-column.calendar-column {
    background-color: var(--tm-surface-alt);
}

/* Angepinnt am rechten Rand des scrollenden Boards: Der Tageskalender war
   je nach Zoom/Fensterbreite halb abgeschnitten — als waere die Ansicht
   kaputt. Jetzt bleibt er vollstaendig sichtbar, der Schattenwurf links
   zeigt die Kante.

   DIE BEIDEN BREITENZEILEN SIND DER KERN VON 0.4.4. Bis dahin gab es sie
   nicht: --tm-col-calendar war deklariert, wurde vom Ziehgriff beschrieben,
   vom Platz-Abgleich eingerechnet — und von keiner einzigen CSS-Eigenschaft
   gelesen. Der Kalender erbte damit aus `.kanban-column` die TAGESbreite und
   wuchs mit ihr; jede Rechnung, die mit 221 px kalkulierte, lag um
   (Tagesbreite − 221) daneben. Genau deshalb lief das Board ueber, sobald
   die Spalten breiter wurden, und der klebende Kalender legte sich ueber die
   letzte Tagesspalte. min-width MUSS mit gesetzt werden: die Basisregel
   bindet sie sonst weiter an --tm-col-day, und die flex-Zeile allein bliebe
   wirkungslos.

   margin-left: auto haelt den Kalender am rechten Rand, wenn der Platz nicht
   restlos aufgeht — der Rest fuellt dann die Luecke VOR ihm statt einen
   leeren Streifen hinter ihm zu lassen.

   z-index 5 statt 3: Die Ziehgriffe liegen bei 4 und bilden mit dem Kalender
   denselben Stapelkontext (die Spalten sind zwar `relative`, aber ohne
   z-index). Bei 3 zeichneten sich die Griffe der Tagesspalten quer ueber
   dem angepinnten Kalender ab und fingen dort die Klicks ab. */
.kanban-column.calendar-column {
    position: sticky;
    right: 0;
    flex: 0 0 var(--tm-col-calendar);
    min-width: var(--tm-col-calendar);
    margin-left: auto;
    z-index: 5;
    box-shadow: -8px 0 14px -10px rgba(20, 20, 20, 0.25);
}

/* Tageskalender abgeschaltet (Werkzeugzeile bzw. Taste K). Die Klasse sitzt
   auf <html>, weil sie schon das Kopf-Skript (js/common/board-widths-early.js)
   vor dem ersten Zeichnen setzt — sonst blitzte der Kalender bei jedem
   Seitenaufruf kurz auf. Der Platz-Abgleich behandelt ihn dann als NICHT
   VORHANDEN, es passen also entsprechend mehr Tagesspalten. */
.tm-board-no-calendar .kanban-column.calendar-column {
    display: none;
}

.kanban-column[data-date="backboard"] .kanban-header,
.kanban-column.calendar-column .kanban-header {
    padding: 0.75rem;
}

.kanban-header {
    padding: 1rem;
    background-color: var(--tm-surface);
    border-bottom: 1px solid var(--tm-border);
    border-radius: var(--tm-radius) var(--tm-radius) 0 0;
    text-align: center;
}

.kanban-header h5 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--tm-text);
}

.kanban-cards {
    flex: 1;
    padding: 0.5rem;
    min-height: 200px;
    overflow-y: auto;
}

.kanban-card {
    margin-bottom: 0.5rem;
    cursor: move;
    font-size: 0.8rem;
    line-height: 1.25;
    transition: box-shadow 0.15s ease;
}

.kanban-card .card {
    border: 1px solid var(--tm-border);
    border-radius: var(--tm-radius-sm);
    box-shadow: var(--tm-shadow-xs);
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

/* Hover: die Karte unter dem Zeiger hebt sich spuerbar ab — nur ueber
   Schatten und Kante, KEIN transform: Karten, die beim Anfassen wegruecken,
   stoeren das Ziehen (Drag & Drop) und die FLIP-Animationen. */
.kanban-card:hover .card {
    box-shadow: var(--tm-shadow-md);
    border-color: var(--tm-text-faint);
}

/* =========================================================================
   Belohnungs-Momente (docs/REWARD_MOMENTS.md, dashboard-reward.js).
   Animationen auf dem INNEREN .card-Element bzw. Icon — das aeussere
   .kanban-card gehoert Drag & Drop und den FLIP-Animationen.
   ========================================================================= */

/* Aufgabe erledigt: kurzes gruenes Aufleuchten der Karte … */
@keyframes reward-card-glow {
    0%   { box-shadow: var(--tm-shadow-xs); }
    30%  { box-shadow: 0 0 0 3px var(--tm-success-soft), 0 2px 10px rgba(31, 138, 95, 0.35); border-color: var(--tm-success); }
    100% { box-shadow: var(--tm-shadow-xs); }
}

/* … und ein Haekchen, das kurz ueber sich hinauswaechst. */
@keyframes reward-check-pop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.45); }
    70%  { transform: scale(0.92); }
    100% { transform: scale(1); }
}

.kanban-card.reward-complete .card {
    animation: reward-card-glow 0.65s ease;
}

.kanban-card.reward-complete .task-status-toggle {
    display: inline-block;
    animation: reward-check-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Tag geschafft: der Spaltenkopf atmet einmal gruen durch … */
@keyframes reward-day-glow {
    0%   { background-color: var(--tm-surface); }
    25%  { background-color: var(--tm-success-soft); }
    100% { background-color: var(--tm-surface); }
}

.kanban-column.reward-day-done .kanban-header {
    animation: reward-day-glow 1.5s ease;
}

/* … und traegt fuer einen Moment den Chip. Er faehrt weich ein, bleibt
   kurz stehen und loest sich auf; nicht interaktiv, verdeckt nichts. */
@keyframes reward-chip {
    0%   { opacity: 0; transform: translateY(6px) scale(0.9); }
    15%  { opacity: 1; transform: translateY(0) scale(1.04); }
    22%  { transform: scale(1); }
    80%  { opacity: 1; }
    100% { opacity: 0; transform: translateY(-4px); }
}

.reward-day-chip {
    position: absolute;
    left: 50%;
    top: 100%;
    transform: translateX(-50%);
    margin-top: 0.35rem;
    padding: 0.3rem 0.75rem;
    border-radius: var(--tm-radius-pill);
    background: var(--tm-success);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: var(--tm-shadow-md);
    pointer-events: none;
    z-index: 5;
    animation: reward-chip 2.2s ease forwards;
}

/* Der Chip positioniert sich relativ zum Spaltenkopf. */
.kanban-header {
    position: relative;
}

/* Wer reduzierte Bewegung wuenscht, bekommt Ergebnis statt Inszenierung:
   Der Chip erscheint und verschwindet ohne Fahrt, alles andere entfaellt. */
@media (prefers-reduced-motion: reduce) {
    .kanban-card.reward-complete .card,
    .kanban-card.reward-complete .task-status-toggle,
    .kanban-column.reward-day-done .kanban-header {
        animation: none;
    }

    .reward-day-chip {
        animation: none;
        opacity: 1;
    }
}

.kanban-card.calendar-task:not(.task-done) .card {
    background-color: var(--bs-success-bg-subtle);
    border-color: var(--bs-success-border-subtle);
    border-left: 4px solid var(--bs-success);
}

.kanban-card.calendar-task .calendar-task-icon {
    color: var(--bs-success);
}

.kanban-card .card-body {
    padding: 0.4rem 0.5rem !important;
}

.kanban-card .card-title {
    font-size: 0.8rem;
    line-height: 1.2;
    margin-bottom: 0.35rem !important;
}

.kanban-card .small,
.kanban-card small {
    font-size: 0.7rem;
    line-height: 1.2;
}

.kanban-card .mb-2 {
    margin-bottom: 0.35rem !important;
}

.kanban-card:hover .card {
    box-shadow: var(--tm-shadow-sm);
}

/* ---------------------------------------------------------------
 * Skeleton-Zustand (Task-Detail-Modal): waehrend des Ladens werden die
 * Inhalte ausgeblendet und schimmernde Platzhalter-Zeilen gezeigt -
 * statt leerer Flaeche oder der Daten der zuvor geoeffneten Aufgabe.
 * --------------------------------------------------------------- */
.modal-body.tm-skeleton {
    position: relative;
    min-height: 340px;
    overflow: hidden;
}

.modal-body.tm-skeleton > * {
    visibility: hidden;
}

/* Platzhalter-Zeilen: mehrere graue Balken unterschiedlicher Breite */
.modal-body.tm-skeleton::before {
    content: "";
    position: absolute;
    inset: 1rem;
    background-image:
        linear-gradient(var(--tm-surface-alt), var(--tm-surface-alt)),
        linear-gradient(var(--tm-surface-alt), var(--tm-surface-alt)),
        linear-gradient(var(--tm-surface-alt), var(--tm-surface-alt)),
        linear-gradient(var(--tm-surface-alt), var(--tm-surface-alt)),
        linear-gradient(var(--tm-surface-alt), var(--tm-surface-alt)),
        linear-gradient(var(--tm-surface-alt), var(--tm-surface-alt));
    background-size:
        45% 18px,
        100% 72px,
        90% 12px,
        75% 12px,
        60% 12px,
        100% 96px;
    background-position:
        0 0,
        0 34px,
        0 126px,
        0 150px,
        0 174px,
        0 210px;
    background-repeat: no-repeat;
    border-radius: 6px;
}

/* Schimmer-Effekt, der ueber die Platzhalter laeuft */
.modal-body.tm-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.65), transparent);
    transform: translateX(-100%);
    animation: tm-skeleton-sweep 1.2s ease-in-out infinite;
}

@keyframes tm-skeleton-sweep {
    to {
        transform: translateX(100%);
    }
}

/* ---------------------------------------------------------------
 * Speichern-Indikator pro Karte: dezenter pulsierender Punkt, solange
 * ein Write (Verschieben, Status-Toggle) fuer die Karte aussteht.
 * Vertrauen ohne Blockieren - die Karte bleibt voll bedienbar.
 * --------------------------------------------------------------- */
.kanban-card.is-saving .card {
    position: relative;
}

.kanban-card.is-saving .card::after {
    content: "";
    position: absolute;
    top: 6px;
    right: 6px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--tm-accent);
    animation: tm-saving-pulse 1s ease-in-out infinite;
}

@keyframes tm-saving-pulse {
    50% {
        opacity: 0.25;
    }
}

/* Tagesspalten waehrend des AJAX-Spaltenwechsels (dashboard-navigate.js):
   dezent gedimmt, nicht bedienbar - der Wechsel selbst dauert nur kurz. */
.kanban-column.is-swapping {
    opacity: 0.5;
    pointer-events: none;
    transition: opacity 0.15s ease;
}

/* Optimistisch angelegte Karte (Quick-Task): sichtbar "unterwegs", bis der
   Server bestaetigt. Nicht interaktiv - die echte Karte kommt vom Server. */
.kanban-card--pending {
    opacity: 0.65;
    pointer-events: none;
}

.kanban-card--pending .card {
    border-style: dashed;
}

/* Sanftes Erscheinen neuer Karten (optimistisches Anlegen). */
@keyframes tm-card-enter {
    from {
        opacity: 0;
        transform: translateY(-6px) scale(0.98);
    }
    to {
        /* opacity bewusst ohne Zielwert: endet auf dem Basiswert der Karte
           (1 bzw. 0.65 bei --pending) statt sichtbar zu springen. */
        transform: none;
    }
}

.kanban-card-enter {
    animation: tm-card-enter 200ms ease-out;
}

/* Waehrend des Ziehens wird die Karte in der Liste zum "Platzhalter":
   gestrichelte Kontur in Akzentfarbe zeigt die Einfuegestelle deutlich an. */
.kanban-card.dragging {
    opacity: 0.55;
}

.kanban-card.dragging .card {
    border-style: dashed;
    border-color: var(--tm-accent);
    background-color: var(--tm-accent-soft);
    box-shadow: none;
}

/* Kleine Zeit-Fortschrittsanzeige (Ist-/Soll-Minuten) */
.task-progress {
    height: 3px;
    border-radius: 999px;
    background: var(--tm-surface-alt);
    overflow: hidden;
    margin-bottom: 0.4rem;
}

.task-progress-bar {
    height: 100%;
    background: var(--tm-accent);
    border-radius: 999px;
}

.task-progress-bar.is-over {
    background: var(--tm-warning);
}

@media (max-width: 768px) {
    .kanban-board {
        flex-wrap: wrap;
        overflow-x: visible;
        /* Gestapelt ist das Board eine Liste, keine Bildschirmflaeche: Die
           Vollhoehe aus der Basisregel haette die Spalten in einen zu
           kleinen Kasten gezwungen, aus dem sie sichtbar herausquellen. */
        height: auto;
    }

    /* min-width MUSS hier mit zurueckgenommen werden: Die Basisregel setzt
       sie auf die Tagesbreite, und eine gespeicherte 460-px-Breite haette
       den gestapelten Umbruch auf schmalen Geraeten sonst wieder
       ueberlaufen lassen. */
    .kanban-column,
    .kanban-column[data-date="backboard"],
    .kanban-column.calendar-column {
        flex: 1 1 100%;
        min-width: 0;
        margin-bottom: 1rem;
        /* Gestapelt gibt es keine Zeilenhoehe zu fuellen: Die 100 % aus der
           Basisregel beziehen sich auf die feste Boardhoehe, jede Spalte
           haette also die volle Bildschirmhoehe beansprucht und waere aus
           dem Board herausgequollen. */
        height: auto;
    }

    /* Der Kalender ist hier eine gestapelte Spalte wie jede andere: Ohne
       horizontalen Scrollport gibt es keine Kante, an der er kleben, und
       keine, die ein Schatten zeigen koennte. Diese vier Zeilen fehlten bis
       0.4.4 — das Anpinnen blieb auf Mobilgeraeten stehen. */
    .kanban-column.calendar-column {
        position: static;
        margin-left: 0;
        z-index: auto;
        box-shadow: none;
    }
}

/* TinyMCE/Tiptap Content Styles - vereinfacht */
.tinymce-content,
.tiptap-content {
    line-height: 1.6;
    color: #333;
}

.tiptap-content ul[data-type="taskList"],
.tiptap-editor ul[data-type="taskList"] {
    list-style: none !important;
    padding-left: 0 !important;
}

.tiptap-content ul[data-type="taskList"] li,
.tiptap-editor ul[data-type="taskList"] li {
    display: flex !important;
    align-items: flex-start !important;
    gap: 0.5rem !important;
}

.tiptap-content ul[data-type="taskList"] input[type="checkbox"]:checked + div,
.tiptap-editor ul[data-type="taskList"] input[type="checkbox"]:checked + div {
    text-decoration: line-through;
    color: var(--tm-text-muted);
}

/* ---------------------------------------------------------------
 * CSP-Bereinigung (SAMMELMASSNAHMENPLAN M7): Utility-Klassen statt
 * Inline-Style-Attributen. Farbwerte selbst bleiben dynamisch (aus der DB,
 * z. B. Company-/Kalenderfarben) und werden per data-color-bg per JS
 * gesetzt (siehe js/common/inline-style-bridge.js) - hier nur die feste
 * Groesse der Farb-Punkte.
 * --------------------------------------------------------------- */
.tm-color-dot-sm {
    display: inline-block;
    width: 14px;
    height: 14px;
}

.tm-color-dot-md {
    display: inline-block;
    width: 18px;
    height: 18px;
}

.tm-mw-260 { max-width: 260px; }
.tm-mw-340 { max-width: 340px; }
.tm-mw-360 { max-width: 360px; }
.tm-mw-520 { max-width: 520px; }
.tm-mw-600 { max-width: 600px; }
.tm-mw-640 { max-width: 640px; }
.tm-mw-760 { max-width: 760px; }
.tm-mw-860 { max-width: 860px; }
.tm-mw-960 { max-width: 960px; }

.tm-w-42 { width: 42px; }
.tm-w-44 { width: 44px; height: 44px; }
.tm-w-46 { width: 46px; height: 46px; }

.tm-col-w-5  { width: 5%; }
.tm-col-w-10 { width: 10%; }
.tm-col-w-12 { width: 12%; }
.tm-col-w-15 { width: 15%; }
.tm-col-w-30 { width: 30%; }
.tm-col-w-35 { width: 35%; }

.tm-cursor-pointer { cursor: pointer; }
.tm-minw-0 { min-width: 0; }
.tm-pre-wrap { white-space: pre-wrap; }
.tm-max-h-260 { max-height: 260px; }
.tm-recovery-dropdown { z-index: 1050; max-height: 260px; overflow-y: auto; }
.tm-select-narrow { width: auto; min-width: 110px; }
.tm-progress-thin { height: 5px; }
.tm-progress-init { width: 0; }

/* =========================================================================
   QuickHelp — Knopf in der Navigationsleiste (links neben der
   Benutzeranzeige) und das Fenster mit der Tastatursteuerung.
   Markup: app/Views/components/quickhelp_button.php + quickhelp_modal.php
   ========================================================================= */

.quickhelp-trigger {
    border: 1px solid var(--tm-border);
    border-radius: var(--tm-radius-pill);
    background-color: var(--tm-surface);
    color: var(--tm-text-muted);
    font-size: 0.8125rem;
    line-height: 1.35;
    white-space: nowrap;
}

.quickhelp-trigger:hover,
.quickhelp-trigger:focus {
    border-color: var(--tm-accent);
    background-color: var(--tm-accent-soft);
    color: var(--tm-accent);
}

.quickhelp-intro {
    margin-bottom: 1.25rem;
    color: var(--tm-text-muted);
    font-size: 0.875rem;
}

.quickhelp-group + .quickhelp-group {
    margin-top: 1.5rem;
}

.quickhelp-group-title {
    margin-bottom: 0.35rem;
    color: var(--tm-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.quickhelp-group-hint {
    margin-left: 0.35rem;
    color: var(--tm-text-faint);
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
}

.quickhelp-row {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--tm-border-subtle);
}

.quickhelp-row:last-child {
    border-bottom: 0;
}

.quickhelp-row-keys {
    flex: 0 0 10.5rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.2rem;
}

.quickhelp-row-desc {
    flex: 1;
    min-width: 0;
}

kbd.quickhelp-key {
    display: inline-block;
    min-width: 1.75rem;
    padding: 0.1rem 0.4rem;
    border: 1px solid var(--tm-border);
    border-bottom-width: 2px;
    border-radius: var(--tm-radius-sm);
    background-color: var(--tm-surface-alt);
    box-shadow: var(--tm-shadow-xs);
    color: var(--tm-text);
    font-family: inherit;
    font-size: 0.8125rem;
    text-align: center;
}

.quickhelp-sep {
    color: var(--tm-text-faint);
    font-size: 0.75rem;
}

.quickhelp-full-help {
    color: var(--tm-text-muted);
    font-size: 0.875rem;
    text-decoration: none;
}

.quickhelp-full-help:hover,
.quickhelp-full-help:focus {
    color: var(--tm-accent);
}

@media (max-width: 575.98px) {
    .quickhelp-row {
        flex-direction: column;
        gap: 0.2rem;
    }

    .quickhelp-row-keys {
        flex: 0 0 auto;
    }
}

/* ---------------------------------------------------------------
 * Barrierefreiheit: Nutzer mit reduzierter Bewegung (OS-Einstellung)
 * bekommen keine Transitions/Animationen. Betrifft u. a. die
 * Kanban-Einblendung und alle Hover-Uebergaenge.
 * --------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}
