OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

tickets.css

78 KB
/* ================================================================
   Tickets – shared styles for index.php and show.php
   ================================================================ */

/* ── Farb-Variablen für Status / Priorität / Fälligkeit / SLA ──
   Zentrale Single-Source-of-Truth — wenn jemand "Warteschlange" von
   Gelb auf Orange umstellt, ändert sich das hier einmal und greift
   sowohl in der Listenansicht (.tk-s-*) als auch im Header-Pill
   (.ts-pill-status-*) und in der Bubble-Meta. */
:root {
    /* Status */
    --ticket-status-new-bg:     var(--blue-100);  --ticket-status-new-fg:     var(--blue-800);
    --ticket-status-open-bg:    var(--emerald-100);  --ticket-status-open-fg:    var(--emerald-800);
    --ticket-status-waiting-bg: var(--amber-100);  --ticket-status-waiting-fg: var(--amber-800);
    --ticket-status-solved-bg:  var(--indigo-100);  --ticket-status-solved-fg:  var(--indigo-800);
    --ticket-status-closed-bg:  var(--gray-200);  --ticket-status-closed-fg:  var(--gray-700);

    /* Priorität */
    --ticket-prio-1-bg: var(--red-100);  --ticket-prio-1-fg: var(--red-800);  /* Kritisch */
    --ticket-prio-2-bg: var(--gray-100);  --ticket-prio-2-fg: var(--gray-700);  /* Normal   */
    --ticket-prio-3-bg: var(--emerald-50);  --ticket-prio-3-fg: var(--emerald-800);  /* Niedrig  */

    /* Fälligkeit + SLA — teilen sich semantische Slots mit Status/Prio,
       z. B. ist "überfällig" dasselbe Rot wie "kritisch". */
    --ticket-overdue-bg: var(--red-100); --ticket-overdue-fg: var(--red-800);
    --ticket-warning-bg: var(--amber-100); --ticket-warning-fg: var(--amber-800);
    --ticket-info-bg:    var(--blue-100); --ticket-info-fg:    var(--blue-800);
    --ticket-success-bg: var(--emerald-100); --ticket-success-fg: var(--emerald-800);
    --ticket-late-bg:    var(--orange-200); --ticket-late-fg:    var(--orange-800);
    --ticket-muted-bg:   var(--gray-100); --ticket-muted-fg:   var(--gray-700);
}

a { text-decoration: none; }
a:hover { text-decoration: none; }

/* ── Status pills ── */
.tk-status { display:inline-flex; align-items:center; gap:0.3rem; padding:0.2rem 0.6rem; border-radius:9999px; font-size:0.72rem; font-weight:700; white-space:nowrap; }
.tk-s-new      { background:var(--ticket-status-new-bg);     color:var(--ticket-status-new-fg); }
.tk-s-open     { background:var(--ticket-status-open-bg);    color:var(--ticket-status-open-fg); }
.tk-s-waiting  { background:var(--ticket-status-waiting-bg); color:var(--ticket-status-waiting-fg); }
.tk-s-solved   { background:var(--ticket-status-solved-bg);  color:var(--ticket-status-solved-fg); }
.tk-s-closed   { background:var(--ticket-status-closed-bg);  color:var(--ticket-status-closed-fg); }

/* ── Status dropdown (manual status change) ──
   Der Status-Toggle muss als Button erkennbar sein. Ohne sichtbares
   Affordance (Hover-Shift, Chevron, Cursor-Pointer) klicken viele
   neue Bearbeiter nicht drauf und suchen den Status-Wechsel woanders. */
.tk-status-dropdown { position:relative; display:inline-block; }
.tk-status-toggle {
    border:none;
    cursor:pointer;
    display:inline-flex;
    align-items:center;
    gap:0.3rem;
    transition:filter .15s, box-shadow .15s, transform .05s;
}
.tk-status-toggle:hover  { filter:brightness(0.95); box-shadow:0 1px 4px rgba(0,0,0,0.12); }
.tk-status-toggle:active { transform:translateY(1px); }
.tk-status-toggle:focus-visible { outline:2px solid var(--color-primary); outline-offset:2px; }
.tk-status-chev { opacity:0.7; transition:transform .15s; flex-shrink:0; }
.tk-status-toggle[aria-expanded="true"] .tk-status-chev { transform:rotate(180deg); opacity:1; }

.tk-status-dropdown .tk-status-menu { display:none !important; position:absolute; top:100%; right:0; margin-top:0.35rem; background:var(--color-bg); border:1px solid var(--gray-200); border-radius:0.5rem; box-shadow:0 4px 12px rgba(0,0,0,.12); padding:0.3rem; z-index:50; white-space:nowrap; }
.tk-status-dropdown .tk-status-menu.tk-status-menu--open { display:flex !important; flex-direction:column; gap:0.15rem; }
.tk-status-menu__item { display:flex; border:none; background:none; padding:0.3rem 0.4rem; cursor:pointer; border-radius:0.35rem; }
.tk-status-menu__item:hover { background:var(--gray-100); }

/* ── Priority badges ── */
.tk-priority { display:inline-flex; align-items:center; gap:0.2rem; padding:0.15rem 0.45rem; border-radius:9999px; font-size:0.68rem; font-weight:700; white-space:nowrap; }
.tk-p-1 { background:var(--ticket-prio-1-bg); color:var(--ticket-prio-1-fg); }
.tk-p-2 { background:var(--ticket-prio-2-bg); color:var(--ticket-prio-2-fg); }
.tk-p-3 { background:var(--ticket-prio-3-bg); color:var(--ticket-prio-3-fg); }

/* ── Due-date indicator ── */
.tk-due { font-size:0.72rem; white-space:nowrap; }
.tk-due.overdue  { color:var(--red-600); font-weight:700; }
.tk-due.due-soon { color:var(--amber-600); font-weight:600; }
.tk-due.ok       { color:var(--gray-500); }

/* ================================================================
   INDEX – Ticket List
   ================================================================ */

.tk-wrap { padding: 0; }

/* Status tabs */
.tk-tabs { display:flex; gap:0.15rem; padding:0.4rem 1rem 0; border-bottom:1px solid var(--gray-200); background:var(--color-bg); flex-wrap:wrap; }
.tk-tab { padding:0.3rem 0.7rem; font-size:0.82rem; font-weight:600; border-radius:0.375rem 0.375rem 0 0;
    color:var(--gray-500); text-decoration:none; display:flex; align-items:center; gap:0.3rem; border-bottom:2px solid transparent; margin-bottom:-1px; }
.tk-tab:hover { color:var(--color-primary-deep); }
.tk-tab.active { color:var(--color-primary-deep); border-bottom-color:var(--color-primary); }
.tk-tab-count { background:var(--gray-200); color:var(--gray-500); font-size:0.7rem; font-weight:700; padding:0.1rem 0.4rem; border-radius:9999px; }
.tk-tab.active .tk-tab-count { background:var(--color-primary-soft); color:var(--blue-800); }

/* Body */
.tk-body { padding:0.65rem 1rem 2rem; background:var(--gray-50); }

/* Table */
.tk-table-wrap { background:var(--color-bg); border:1px solid var(--gray-200); border-radius:0.25rem; overflow:hidden; overflow-x:auto; }
.tk-table { width:100%; border-collapse:collapse; min-width:480px; }
.tk-table th { padding:0.4rem 0.75rem; font-size:0.72rem; font-weight:700; text-transform:uppercase; letter-spacing:0.05em; color:var(--gray-400); background:var(--gray-50); border-bottom:1px solid var(--gray-100); text-align:left; }
.tk-table td { padding:0.45rem 0.75rem; font-size:0.84rem; border-bottom:1px solid var(--gray-50); vertical-align:middle; }
.tk-table tr:last-child td { border-bottom:none; }
.tk-table tr:hover td { background:var(--gray-50); }
.tk-row-critical td { background:var(--red-50); }
.tk-row-critical:hover td { background:var(--red-100); }
.tk-row-low td { background:var(--green-50); }
.tk-row-low:hover td { background:var(--green-100); }
.tk-row-link { display:contents; }

.tk-id { font-size:0.75rem; font-weight:700; color:var(--gray-400); }
.tk-subject { font-weight:600; color:var(--gray-900); max-width:300px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:block; }
.tk-subject:hover { color:var(--color-primary); }
.tk-subject.unread { color:var(--color-primary-deep); }
.tk-subject.unread::before { content:''; display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--color-primary); margin-right:5px; vertical-align:middle; }
.tk-from { font-size:0.78rem; color:var(--gray-500); }

/* ── Herkunft ──
   Auf welchem Weg das Ticket entstanden ist. Bewusst zurückhaltend: eine
   ruhige Marke vor dem Melder, keine zweite Status-Farbe in der Zeile.
   Die drei Gruppen aus TicketManager::SOURCES teilen sich je einen Slot. */
.tk-src {
    display:inline-flex; align-items:center; gap:0.25rem;
    margin-right:0.35rem; padding:0.05rem 0.4rem; border-radius:9999px;
    font-size:0.68rem; font-weight:700; white-space:nowrap; vertical-align:baseline;
    background:var(--ticket-muted-bg); color:var(--ticket-muted-fg);
}
/* Im Backend erfasst: bewusst die ruhige Grundfarbe – das ist der Normalfall
   im Arbeitsalltag der IT und soll die Zeile nicht beanspruchen. */
.tk-src-backend { background:var(--ticket-muted-bg); color:var(--ticket-muted-fg); }
.tk-src-portal { background:var(--ticket-success-bg); color:var(--ticket-success-fg); }
.tk-src-mail   { background:var(--ticket-info-bg);    color:var(--ticket-info-fg); }
/* Automatisch entstandene Tickets: dieselbe Marke, damit sie sich von dem
   abheben, was ein Mensch gemeldet oder erfasst hat. */
.tk-src-api,
.tk-src-monitoring,
.tk-src-maintenance,
.tk-src-isms,
.tk-src-xdr,
.tk-src-recurring { background:var(--ticket-warning-bg); color:var(--ticket-warning-fg); }
.tk-sentiment { display:inline-block; margin-right:5px; font-size:1rem; line-height:1; vertical-align:middle; cursor:default; }
.tk-assignee { font-size:0.78rem; color:var(--gray-700); }
.tk-meta     { font-size:0.72rem; color:var(--gray-400); }
.tk-empty { text-align:center; padding:3rem 1rem; color:var(--gray-400); font-size:0.88rem; }

/* Bulk selection */
.tk-bulk-bar { display:none; align-items:center; gap:0.75rem; padding:0.5rem 1rem; background:var(--blue-50); border-bottom:1px solid var(--blue-200); font-size:0.82rem; color:var(--blue-800); flex-wrap:wrap; }
.tk-bulk-bar.active { display:flex; }
.tk-bulk-count { font-weight:700; }
.tk-bulk-btn { padding:0.3rem 0.75rem; border-radius:0.25rem; font-size:0.78rem; font-weight:600; cursor:pointer; border:1px solid; }
.tk-bulk-btn-assign { background:var(--color-primary); color:var(--color-on-accent); border-color:var(--color-primary-dark); }
.tk-bulk-btn-close  { background:var(--red-100); color:var(--red-600); border-color:var(--red-300); }
.tk-bulk-btn-cat    { background:var(--gray-100); color:var(--gray-700); border-color:var(--gray-300); }

/* Pagination */
.tk-pagination { display:flex; align-items:center; justify-content:space-between; padding:0.75rem 1rem; border-top:1px solid var(--gray-100); background:var(--gray-50); font-size:0.82rem; color:var(--gray-500); flex-wrap:wrap; gap:0.5rem; }
.tk-page-links { display:flex; gap:0.25rem; }
.tk-page-link { padding:0.3rem 0.65rem; border:1px solid var(--gray-200); border-radius:0.25rem; color:var(--gray-700); font-size:0.8rem; text-decoration:none; }
.tk-page-link:hover { background:var(--gray-100); }
.tk-page-link.active { background:var(--color-primary); color:var(--color-on-accent); border-color:var(--color-primary); }
.tk-page-link.disabled { pointer-events:none; opacity:0.4; }

/* Live-search loading spinner */
.tk-search-wrap { position:relative; }
.tk-search-spinner { display:none; position:absolute; right:0.5rem; top:50%; transform:translateY(-50%); width:14px; height:14px; border:2px solid var(--gray-200); border-top-color:var(--color-primary); border-radius:50%; animation:tk-spin 0.6s linear infinite; }
@keyframes tk-spin { to { transform:translateY(-50%) rotate(360deg); } }

/* Toast notification */
.tk-toast { position:fixed; bottom:1.5rem; right:1.5rem; background:var(--color-primary-deep); color:var(--color-on-accent); padding:0.65rem 1.1rem; border-radius:0.375rem; font-size:0.85rem; font-weight:600; z-index:9999; box-shadow:0 4px 16px rgba(0,0,0,.25); display:none; animation:tk-toast-in 0.2s ease; gap:0.75rem; align-items:center; }
.tk-toast.visible { display:inline-flex; }
.tk-toast-btn { background:rgba(255,255,255,0.18); color:var(--color-on-accent); border:1px solid rgba(255,255,255,0.35); border-radius:0.3rem; padding:0.2rem 0.65rem; font-size:0.78rem; font-weight:600; cursor:pointer; }
.tk-toast-btn:hover { background:rgba(255,255,255,0.3); }
@keyframes tk-toast-in { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }

/* Sortable column headers */
.tk-table thead th { user-select:none; }
.tk-sort { color:inherit; text-decoration:none; display:inline-flex; align-items:center; gap:0.3rem; }
.tk-sort:hover { color:var(--color-primary-deep); }
.tk-sort-arrow { font-size:0.65rem; color:var(--gray-400); line-height:1; }
.tk-sort-active { color:var(--color-primary-deep); }
.tk-sort-active .tk-sort-arrow { color:var(--color-primary); }

@media(max-width:960px) {
    /* Spalten: ☑(1) #(2) Betreff(3) Status(4) Kategorie(5) Zugewiesen(6) Fälligkeit(7) Erstellt(8)
       Ohne manage: #(1) Betreff(2) Status(3) Kategorie(4) Zugewiesen(5) Fälligkeit(6) Erstellt(7) */
    .tk-body { padding:0.5rem 1rem 1.5rem; }
    .tk-tabs { padding:0.25rem 1rem 0; }
    .tk-table td:nth-child(5), .tk-table th:nth-child(5),
    .tk-table td:nth-child(6), .tk-table th:nth-child(6) { display:none; }
}
@media(max-width:600px) {
    /* Zusätzlich Fälligkeit + Erstellt ausblenden; Priorität-Dot bleibt im Betreff sichtbar */
    .tk-table { min-width:0; }
    .tk-table td:nth-child(7), .tk-table th:nth-child(7),
    .tk-table td:nth-child(8), .tk-table th:nth-child(8) { display:none; }
    .tk-table td, .tk-table th { padding:0.35rem 0.5rem; }
    .tk-subject { font-size:0.82rem; }
    .tk-from    { display:none; }
    .tk-tabs { gap:0; padding:0.2rem 0.5rem 0; }
    .tk-tab  { padding:0.3rem 0.5rem; font-size:0.77rem; }
    .tk-body { padding:0.4rem 0.5rem 1.5rem; }
}

/* Filter collapse */
.tk-filter-header { display:flex; align-items:center; justify-content:space-between; padding:0.45rem 1rem; cursor:pointer; font-size:0.78rem; font-weight:600; color:var(--gray-500); user-select:none; border-bottom:1px solid var(--gray-200); }
.tk-filter-header:hover { color:var(--gray-700); }
.tk-filter-chevron { font-size:0.6rem; transition:transform 0.2s ease; display:inline-block; }
#tk-filter-card.collapsed .tk-filter-chevron { transform:rotate(180deg); }
#tk-filter-card.collapsed .filter-card-body { display:none; }

/* ── Create-Ticket Modal ── */
.tkm-overlay { display:none; position:fixed; inset:0; background:rgba(15,23,42,0.55); z-index:8000; align-items:center; justify-content:center; padding:1rem; }
.tkm-overlay.open { display:flex; }
.tkm-dialog { background:var(--color-bg); border-radius:0.25rem; width:100%; max-width:620px; max-height:90vh; overflow-y:auto; box-shadow:0 20px 60px rgba(0,0,0,0.25); animation:tkm-in 0.18s ease; }
@keyframes tkm-in { from { opacity:0; transform:translateY(-12px) scale(0.98); } to { opacity:1; transform:none; } }
.tkm-header { display:flex; align-items:center; justify-content:space-between; padding:1.25rem 1.5rem 1rem; border-bottom:1px solid var(--gray-100); }
.tkm-title { font-size:1.1rem; font-weight:800; color:var(--color-primary-deep); }
.tkm-close { background:none; border:none; font-size:1.2rem; color:var(--gray-400); cursor:pointer; padding:0.25rem 0.5rem; border-radius:0.375rem; line-height:1; }
.tkm-close:hover { background:var(--gray-100); color:var(--gray-700); }
.tkm-body { padding:1.25rem 1.5rem 1.5rem; }
.tkm-group { margin-bottom:1.1rem; }
.tkm-label { display:block; font-size:0.82rem; font-weight:600; color:var(--gray-700); margin-bottom:0.3rem; }
.tkm-label .req { color:var(--red-500); margin-left:2px; }
.tkm-input, .tkm-select, .tkm-textarea { width:100%; padding:0.5rem 0.75rem; border:1px solid var(--gray-300); border-radius:0.25rem; font-size:0.875rem; color:var(--gray-900); background:var(--color-bg); outline:none; box-sizing:border-box; }
.tkm-input:focus, .tkm-select:focus, .tkm-textarea:focus { border-color:var(--color-primary); box-shadow:0 0 0 3px rgba(var(--color-primary-rgb), 0.15); }
.tkm-textarea { resize:vertical; min-height:110px; line-height:1.6; }
.tkm-row { display:grid; grid-template-columns:1fr 1fr; gap:0.875rem; }
.tkm-section { font-size:0.68rem; font-weight:700; text-transform:uppercase; letter-spacing:0.08em; color:var(--gray-400); margin:1.1rem 0 0.65rem; }
.tkm-divider { border:none; border-top:1px solid var(--gray-100); margin:1.1rem 0; }
.tkm-hint { font-size:0.73rem; color:var(--gray-400); margin-top:0.25rem; }
.tkm-error { display:flex; align-items:flex-start; gap:0.5rem; background:var(--red-50); border:1px solid var(--red-200); border-radius:0.25rem; padding:0.65rem 0.875rem; font-size:0.82rem; color:var(--red-800); margin-bottom:1rem; }
.tkm-actions { display:flex; gap:0.625rem; justify-content:flex-end; margin-top:1.25rem; }
.tkm-btn-cancel { padding:0.5rem 1.1rem; border:1px solid var(--gray-300); border-radius:0.25rem; font-size:0.85rem; font-weight:600; color:var(--gray-500); background:var(--color-bg); cursor:pointer; }
.tkm-btn-cancel:hover { background:var(--gray-50); }
.tkm-btn-submit { padding:0.5rem 1.4rem; border:none; border-radius:0.25rem; font-size:0.85rem; font-weight:700; color:var(--color-on-accent); background:var(--color-primary); cursor:pointer; }
.tkm-btn-submit:hover { background:var(--color-primary-dark); }
.tkm-btn-submit:disabled { opacity:0.6; cursor:not-allowed; }

/* Person-search dropdown */
.ps-wrap { position:relative; }
.ps-badge { display:inline-flex;align-items:center;gap:0.35rem;margin-top:0.3rem;font-size:0.75rem;background:var(--color-primary-soft);color:var(--color-primary);padding:0.15rem 0.5rem;border-radius:1rem; }
.ps-badge-clear { border:none;background:none;cursor:pointer;color:var(--color-primary);font-size:0.9rem;line-height:1;padding:0; }
.ps-dropdown { position:absolute;top:100%;left:0;right:0;z-index:9000;background:var(--color-bg);border:1px solid var(--gray-200);border-radius:0.375rem;box-shadow:0 4px 16px rgba(0,0,0,.15);display:none;max-height:220px;overflow-y:auto; }
.ps-dropdown.open { display:block; }
.ps-item { padding:0.5rem 0.75rem;cursor:pointer;border-bottom:1px solid var(--gray-50); }
.ps-item:hover { background:var(--violet-50); }
.ps-item-name { font-weight:600;font-size:0.875rem; }
.ps-item-sub { font-size:0.75rem;color:var(--gray-400); }
.ps-item-badge { font-size:0.68rem;padding:0.1rem 0.35rem;border-radius:0.25rem;font-weight:700;margin-left:0.3rem; }
.ps-item-badge.entra  { background:var(--color-primary-soft);color:var(--color-primary-dark); }
.ps-item-badge.ldap   { background:var(--emerald-100);color:var(--emerald-800); }
.ps-item-badge.manual { background:var(--gray-100);color:var(--gray-700); }
.ps-no-results { padding:0.5rem 0.75rem;color:var(--gray-400);font-size:0.875rem; }

/* ================================================================
   SHOW – Single Ticket Detail
   ================================================================ */

.ts-wrap { padding:0; display:flex; flex-direction:column; flex:1; min-height:0; }

.ts-status { display:inline-flex; align-items:center; gap:0.3rem; padding:0.2rem 0.6rem; border-radius:9999px; font-size:0.78rem; font-weight:700; background:var(--blue-100); color:var(--color-primary-strong); }
.ts-btn { display:inline-flex; align-items:center; gap:0.35rem; padding:0.45rem 1rem; border-radius:0.25rem; font-size:0.82rem; font-weight:600; cursor:pointer; border:1px solid var(--gray-200); background:var(--gray-100); color:var(--gray-700); text-decoration:none; transition:background 0.15s; }
.ts-btn:hover { background:var(--gray-200); }
.ts-btn-green { background:var(--green-600); color:var(--color-on-accent); border-color:var(--green-600); }
.ts-btn-green:hover { background:var(--green-700); }
.ts-btn-blue  { background:var(--color-primary); color:var(--color-on-accent); border-color:var(--color-primary); }
.ts-btn-blue:hover { background:var(--color-primary-strong); border-color:var(--color-primary-strong); }
.ts-btn-red   { background:none; color:var(--red-600); border:1px solid var(--red-600); }
.ts-btn-red:hover { background:var(--red-600); color:var(--color-on-accent); }

/* Viewport-Lock NUR auf der Ticket-Detail-Ansicht: dort hat .ts-thread
   einen eigenen overflow-y:auto und wir wollen, dass nur der Thread und die
   Sidebar scrollen, nicht die ganze Seite. In der Ticketliste (/tickets/)
   gibt es kein .ts-layout – dort soll body ganz normal scrollen, sonst
   verschwinden Zeilen unter dem Viewport-Rand und der User kann nicht
   nach unten rollen. :has() ist in allen aktuellen Browsern (Chrome 105+,
   Safari 15.4+, Firefox 121+) verfügbar; ohne :has() fällt der Lock weg
   – dann ist die Detailansicht visuell etwas weniger schick, aber
   funktional ok. */
html:has(.ts-layout), body:has(.ts-layout) { height:100%; overflow:hidden; }
body:has(.ts-layout) .wrapper              { min-height:unset !important; height:100%; }
body:has(.ts-layout) .content-wrapper      { min-height:unset !important; height:100%; overflow:hidden; }
body:has(.ts-layout) .main-footer          { display:none; }
body:has(.ts-layout) .main-content         { overflow:hidden; padding:0 !important; flex:1; min-height:0; display:flex; flex-direction:column; }

.ts-layout { display:grid; grid-template-columns:1fr 280px; gap:1.5rem; padding:1.5rem 2.5rem 0; background:var(--slate-50); flex:1; min-height:0; overflow:hidden; align-items:stretch; box-sizing:border-box; }
.ts-content-col { display:flex; flex-direction:column; min-height:0; padding-bottom:0; }
.ts-thread { flex:1 1 0; overflow-y:auto; min-height:0; padding-bottom:1rem; }
.ts-reply-card { flex-shrink:0; }
.ts-sidebar { overflow-y:auto; padding-bottom:2rem; min-height:0; }

/* Sprechblasen-Thread */
.ts-thread { display:flex; flex-direction:column; gap:0.9rem; margin-bottom:1.25rem; }
.ts-bubble-row { display:flex; align-items:flex-end; gap:0.65rem; }
.ts-bubble-row.customer { flex-direction:row; }
.ts-bubble-row.staff    { flex-direction:row-reverse; }

.ts-avatar { width:38px; height:38px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:0.72rem; font-weight:800; flex-shrink:0; align-self:flex-end; letter-spacing:0.02em; }
.ts-avatar-customer { background:var(--amber-200); color:var(--amber-800); }
.ts-avatar-staff    { background:var(--blue-100); color:var(--color-primary-strong); }
.ts-avatar-photo    { object-fit:cover; }

.ts-bubble { max-width:87%; border-radius:1.1rem; overflow:hidden; }
.ts-bubble-customer { background:var(--color-bg); border:1.5px solid var(--gray-200); border-radius:1.1rem 1.1rem 1.1rem 0.3rem; }
.ts-bubble-staff    { background:var(--blue-50); border:1.5px solid var(--blue-200); border-radius:1.1rem 1.1rem 0.3rem 1.1rem; }
.ts-bubble-original { background:var(--slate-50); border:1.5px solid var(--slate-300); border-radius:1.1rem 1.1rem 1.1rem 0.3rem; }

/* Bubble-Meta: zweizeilig — Autor + Badge oben, Datum als kleine graue Zeile
   darunter. Vorher floss alles in eine Zeile mit flex-wrap, was bei langen
   Namen das Datum hässlich umbrach. */
.ts-bubble-meta { padding:0.55rem 1.1rem 0.3rem; display:flex; flex-direction:column; align-items:flex-start; gap:0.15rem; }
.ts-bubble-row.staff .ts-bubble-meta { align-items:flex-end; }
.ts-bubble-author { font-size:0.82rem; font-weight:800; color:var(--gray-700); display:flex; align-items:center; gap:0.35rem; flex-wrap:wrap; }
.ts-bubble-date   { font-size:0.71rem; color:var(--gray-400); white-space:nowrap; }

.ts-staff-badge    { font-size:0.65rem; background:var(--color-primary); color:var(--color-on-accent); padding:0.1rem 0.45rem; border-radius:9999px; font-weight:700; }
.ts-customer-badge { font-size:0.65rem; background:var(--amber-600); color:var(--color-on-accent); padding:0.1rem 0.45rem; border-radius:9999px; font-weight:700; }
.ts-original-badge { font-size:0.65rem; background:var(--slate-500); color:var(--color-on-accent); padding:0.1rem 0.45rem; border-radius:9999px; font-weight:700; }

.ts-bubble-body { padding:0.25rem 1.1rem 0.85rem; font-size:0.88rem; color:var(--gray-700); line-height:1.55; white-space:pre-wrap; word-break:break-word; }
.ts-bubble-body.ts-html { white-space:normal; }
.ts-bubble-body.ts-html img { max-width:100%; height:auto; border-radius:0.375rem; margin:0.25rem 0; }
.ts-bubble-body.ts-html a { color:var(--color-primary); text-decoration:underline; }
.ts-bubble-body.ts-html ul, .ts-bubble-body.ts-html ol { padding-left:1.5rem; margin:0.25rem 0; }
/* !important nötig, weil eingehende Outlook-/Word-Mails Inline-Margins
   liefern, die unsere CSS-Defaults sonst überrennen. normalizeMailWhitespace
   kappt zwar Werte ab, aber bei z. B. style="margin:12pt 0" steht trotzdem
   noch margin am Element – das überschreiben wir hier final. */
.ts-bubble-body.ts-html p,
.ts-bubble-body.ts-html div { margin:0 0 0.4rem 0 !important; padding:0 !important; }
.ts-bubble-body.ts-html p:last-child,
.ts-bubble-body.ts-html div:last-child { margin-bottom:0 !important; }
.ts-bubble-body.ts-html br + br { line-height:1; }
.ts-bubble-body.ts-html blockquote { border-left:3px solid var(--gray-300); margin:0.5rem 0; padding:0.25rem 0.75rem; color:var(--gray-500); }
.ts-bubble-body.ts-html pre { background:var(--gray-100); border-radius:0.375rem; padding:0.5rem 0.75rem; font-size:0.82rem; overflow-x:auto; }

.ts-bubble-attachments { display:flex; flex-wrap:wrap; gap:0.5rem; padding:0.2rem 1.1rem 0.85rem; }
.ts-attachment-chip {
    display:inline-flex;
    align-items:center;
    gap:0.65rem;
    padding:0.55rem 0.85rem;
    border-radius:0.5rem;
    background:var(--slate-50);
    border:1px solid var(--slate-300);
    color:var(--gray-800);
    font-size:0.875rem;
    text-decoration:none;
    min-width:200px;
    max-width:340px;
    transition:background-color 0.15s, border-color 0.15s;
}
.ts-attachment-chip:hover { background:var(--slate-200); border-color:var(--slate-400); color:var(--gray-800); }
.ts-attachment-icon { font-size:1.45rem; line-height:1; flex-shrink:0; }
.ts-attachment-meta {
    /* min-width:0 ist Pflicht, damit der ellipsende Name den Flex-Parent
       nicht über die max-width hinaus aufbläht. */
    display:flex;
    flex-direction:column;
    min-width:0;
    flex:1 1 auto;
    line-height:1.2;
}
.ts-attachment-name {
    font-weight:500;
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
}
.ts-attachment-size {
    color:var(--gray-500);
    font-size:0.75rem;
    margin-top:0.15rem;
    /* Größe steht in eigener Zeile – kein nowrap-Cut mehr. */
}
/* Bild-/PDF-Anhänge öffnen in der Lightbox – Zoom-Cursor als Affordance. */
.ts-attachment-chip--preview { cursor:zoom-in; }
/* Anhang aus einer eingefügten Antwortvorlage (wird automatisch mitgesendet) */
.ts-attachment-chip--canned { background:var(--blue-50); border-color:var(--blue-200); color:var(--blue-800); }
.ts-attachment-chip--canned:hover { background:var(--blue-100); border-color:var(--blue-300); }
.ts-bubble-body img { cursor:zoom-in; }

/* ── Vorschau-Lightbox (Bilder & PDFs) ──────────────────────────── */
.ts-image-modal { position:fixed; inset:0; z-index:1080; display:flex; align-items:center; justify-content:center; padding:2.5rem 4rem; }
.ts-image-modal[hidden] { display:none; }
.ts-image-modal-backdrop { position:absolute; inset:0; background:rgba(0,0,0,0.82); cursor:zoom-out; }
.ts-image-modal-figure { position:relative; z-index:1; margin:0; display:flex; flex-direction:column; align-items:center; gap:0.6rem; max-width:100%; max-height:100%; }
.ts-image-modal-img { max-width:100%; max-height:calc(100vh - 7rem); border-radius:0.4rem; box-shadow:0 12px 40px rgba(0,0,0,0.5); background:var(--color-bg); }
.ts-image-modal-img[hidden], .ts-image-modal-frame[hidden] { display:none; }
.ts-image-modal-frame { width:min(960px, 90vw); height:calc(100vh - 7rem); border:none; border-radius:0.4rem; box-shadow:0 12px 40px rgba(0,0,0,0.5); background:var(--color-bg); }
.ts-image-modal-caption { display:flex; align-items:center; gap:1rem; max-width:100%; color:var(--gray-200); font-size:0.85rem; }
.ts-image-modal-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:500; }
.ts-image-modal-open { color:var(--blue-300); text-decoration:none; white-space:nowrap; flex-shrink:0; }
.ts-image-modal-open:hover { color:var(--blue-200); text-decoration:underline; }
.ts-image-modal-btn { position:absolute; z-index:2; background:rgba(255,255,255,0.12); border:none; color:var(--color-on-accent); cursor:pointer; border-radius:999px; display:flex; align-items:center; justify-content:center; transition:background-color 0.15s; }
.ts-image-modal-btn:hover { background:rgba(255,255,255,0.25); }
.ts-image-modal-close { top:1.1rem; right:1.1rem; width:2.4rem; height:2.4rem; font-size:1.6rem; line-height:1; }
.ts-image-modal-nav { top:50%; transform:translateY(-50%); width:2.8rem; height:2.8rem; font-size:1.3rem; }
.ts-image-modal-prev { left:1rem; }
.ts-image-modal-next { right:1rem; }
@media (max-width:640px) {
    .ts-image-modal { padding:1rem; }
    .ts-image-modal-nav { width:2.2rem; height:2.2rem; }
    .ts-image-modal-prev { left:0.25rem; }
    .ts-image-modal-next { right:0.25rem; }
}

/* Internal note */
.ts-bubble-internal { background:repeating-linear-gradient(-45deg,var(--yellow-50),var(--yellow-50) 10px,var(--yellow-100) 10px,var(--yellow-100) 20px); border:1.5px dashed var(--yellow-600); border-radius:1.1rem 1.1rem 0.3rem 1.1rem; }
.ts-internal-badge { font-size:0.65rem; background:var(--yellow-600); color:var(--color-on-accent); padding:0.1rem 0.45rem; border-radius:9999px; font-weight:700; }
.ts-avatar-internal { background:var(--yellow-200); color:var(--yellow-900); }

/* Reply mode toggle */
.ts-reply-mode-toggle { display:flex; gap:0; border:1px solid var(--gray-200); border-radius:0.25rem; overflow:hidden; }
.ts-mode-btn { padding:0.3rem 0.7rem; border:none; background:var(--gray-50); font-size:0.8rem; font-weight:600; color:var(--gray-500); cursor:pointer; display:flex; align-items:center; justify-content:center; gap:0.35rem; transition:background 0.15s, color 0.15s; }
.ts-mode-btn + .ts-mode-btn { border-left:1px solid var(--gray-200); }
.ts-mode-btn.active-reply    { background:var(--blue-50); color:var(--color-primary); }
.ts-mode-btn.active-internal { background:var(--yellow-50); color:var(--yellow-600); }
.ts-mode-btn.active-ki       { background:var(--violet-50); color:var(--violet-600); }

/* Tools-Bereich rechts in der Reply-Toolbar (Vorlage, später Snippets …)
   Optisch klar getrennt von den Modus-Buttons, damit Modus vs. Werkzeug
   nicht zur Knopfreihe verschwimmen. */
.ts-reply-tools { display:flex; align-items:center; gap:0.3rem; }
.ts-tool-btn {
    display:inline-flex; align-items:center; justify-content:center;
    width:30px; height:30px; padding:0;
    background:transparent; border:1px solid var(--gray-200); border-radius:0.35rem;
    color:var(--gray-600); cursor:pointer;
    transition:background-color .15s, border-color .15s, color .15s;
}
.ts-tool-btn:hover { background:var(--gray-100); border-color:var(--gray-300); color:var(--gray-800); }
.ts-tool-btn:focus-visible { outline:2px solid var(--color-primary); outline-offset:1px; }
.ts-canned-wrap { position:relative; display:inline-block; }
#ts-ki-editor-wrap.wysiwyg-editor-container { border:none; border-radius:0; background:transparent; }
#ts-ki-editor-wrap .wysiwyg-toolbar { padding:0.25rem 0.5rem; background:var(--purple-50); border-top:1px solid var(--purple-200); border-bottom:1px solid var(--purple-200); }
#ts-ki-editor-wrap .wysiwyg-editor  { min-height:90px; max-height:260px; overflow-y:auto; font-size:0.875rem; padding:0.55rem 0.7rem; }

/* Reply box */
.ts-reply-card { background:var(--color-bg); border:1px solid var(--gray-200); border-radius:0.25rem; overflow:hidden; }
.ts-reply-body { padding:0.5rem 0.6rem 0.6rem; display:flex; flex-direction:column; gap:0.4rem; }
.ts-reply-toolbar { display:flex; align-items:center; justify-content:space-between; gap:0.5rem; }
.ts-textarea { width:100%; min-height:70px; padding:0.45rem 0.6rem; border:1px solid var(--gray-300); border-radius:0.25rem; font-size:0.85rem; font-family:inherit; resize:vertical; outline:none; box-sizing:border-box; }
.ts-textarea:focus { border-color:var(--color-primary); box-shadow:0 0 0 2px rgba(var(--color-primary-rgb), 0.15); }
.ts-submit-btn { padding:0.3rem 0.9rem; background:var(--color-primary); color:var(--color-on-accent); border:none; border-radius:0.25rem; font-size:0.82rem; font-weight:700; cursor:pointer; white-space:nowrap; display:flex; align-items:center; gap:0.3rem; }
.ts-submit-btn:hover { background:var(--color-primary-strong); }

/* Reply wysiwyg container */
#ts-reply-editor-wrap.wysiwyg-editor-container { border:none; border-radius:0; background:transparent; }
#ts-reply-editor-wrap .wysiwyg-toolbar { padding:0.25rem 0.5rem; background:var(--slate-50); border-top:1px solid var(--gray-200); border-bottom:1px solid var(--gray-200); }
#ts-reply-editor-wrap .toolbar-group { padding-right:0.4rem; border-right-color:var(--color-gray-300); }
#ts-reply-editor-wrap .toolbar-btn { width:28px; height:28px; font-size:0.82rem; }
#ts-reply-editor-wrap .toolbar-select { height:28px; font-size:0.78rem; }
#ts-reply-editor-wrap .wysiwyg-editor { min-height:90px; max-height:260px; overflow-y:auto; font-size:0.875rem; padding:0.55rem 0.7rem; }

/* Attachment upload strip */
.ts-attachment-upload { display:flex; align-items:center; gap:0.5rem; padding:0.3rem 0.6rem 0; flex-wrap:wrap; }
.ts-attachment-upload-label { font-size:0.78rem; color:var(--gray-500); cursor:pointer; display:inline-flex; align-items:center; gap:0.3rem; padding:0.2rem 0.55rem; border:1px dashed var(--gray-300); border-radius:0.25rem; }
.ts-attachment-upload-label:hover { border-color:var(--color-primary); color:var(--color-primary); }
.ts-attachment-chips-preview { display:flex; flex-wrap:wrap; gap:0.3rem; }
.ts-attachment-preview-chip { display:inline-flex; align-items:center; gap:0.25rem; font-size:0.73rem; background:var(--slate-100); border:1px solid var(--slate-200); border-radius:9999px; padding:0.15rem 0.45rem; color:var(--gray-700); }
.ts-attachment-remove { border:none; background:none; cursor:pointer; color:var(--gray-400); font-size:0.85rem; line-height:1; padding:0; }
.ts-attachment-remove:hover { color:var(--red-600); }

/* Sidebar */
/* overflow:visible, damit absolut positionierte Dropdowns (Bearbeiter-
   Multiselect, Such-Panels für Verknüpfungen/Assets/Klassifizierung) aus
   der Karte herausragen dürfen statt am Rahmen abgeschnitten zu werden.
   Die abgerundeten Ecken kommen von Karte + Header (eigener border-radius),
   nicht vom Clipping. */
.ts-card { background:var(--color-bg); border:1px solid var(--gray-200); border-radius:0.25rem; margin-bottom:0.45rem; overflow:visible; }
.ts-card:last-child { margin-bottom:0; }

/* Telefon-Pills im Einreicher-Header: sitzen neben dem "Einreicher"-Badge
   in der Bubble-Meta und sind direkt klickbare tel:-Links (Quickdial).
   Höhere Spezifität gegen .ts-bubble-author (font-weight:800) und gegen
   die globale a-Farbe aus app.css. */
.ts-bubble-author a.ts-phone-pill,
a.ts-phone-pill {
    display:inline-flex;
    align-items:center;
    gap:0.3rem;
    font-size:0.72rem;
    font-weight:600;
    padding:0.18rem 0.6rem;
    border-radius:9999px;
    text-decoration:none;
    line-height:1.3;
    white-space:nowrap;
    letter-spacing:normal;
    transition:background-color 0.15s, color 0.15s;
}
.ts-bubble-author a.ts-phone-pill-tel,
a.ts-phone-pill-tel    { background:var(--blue-100); color:var(--blue-800); border:1px solid var(--blue-200); }
.ts-bubble-author a.ts-phone-pill-tel:hover,
a.ts-phone-pill-tel:hover    { background:var(--blue-200); color:var(--blue-900); text-decoration:none; }
.ts-bubble-author a.ts-phone-pill-mobile,
a.ts-phone-pill-mobile { background:var(--emerald-100); color:var(--emerald-800); border:1px solid var(--emerald-200); }
.ts-bubble-author a.ts-phone-pill-mobile:hover,
a.ts-phone-pill-mobile:hover { background:var(--emerald-200); color:var(--emerald-900); text-decoration:none; }
.ts-phone-pill-icon { font-size:0.78rem; line-height:1; opacity:0.9; }
.ts-card-header { padding:0.3rem 0.65rem; border-bottom:1px solid var(--gray-100); font-size:0.7rem; font-weight:700; text-transform:uppercase; letter-spacing:0.06em; color:var(--gray-400); background:var(--gray-50); border-radius:0.25rem 0.25rem 0 0; display:flex; align-items:center; justify-content:space-between; gap:0.4rem; }
.ts-card-header-actions { display:flex; align-items:center; gap:0.25rem; }
.ts-card-section { font-size:0.65rem; font-weight:700; text-transform:uppercase; letter-spacing:0.06em; color:var(--gray-400); margin:0 0 0.25rem; }
.ts-card-divider { border:none; border-top:1px solid var(--gray-100); margin:0.45rem -0.65rem; }
.ts-card-body { padding:0.5rem 0.65rem; overflow:visible; }
/* Kompakte Verknüpfungen-Karte: kleines Zähler-Badge im Header und ein
   dezenter Text-Link fürs Zusammenführen statt eines vollbreiten Buttons –
   selten genutzte Aktion, soll optisch nicht dominieren. */
.ts-card-count { display:inline-flex; align-items:center; justify-content:center; min-width:1.05rem; height:1.05rem; padding:0 0.3rem; margin-left:0.15rem; border-radius:999px; background:var(--gray-200); color:var(--gray-600); font-size:0.66rem; font-weight:700; text-transform:none; letter-spacing:0; }
.ts-card-body--links { padding-top:0.4rem; padding-bottom:0.4rem; }
.ts-merge-link { display:inline-flex; align-items:center; gap:0.3rem; margin-top:0.45rem; padding:0.22rem 0.4rem; background:none; border:none; border-radius:0.3rem; color:var(--gray-500); font-size:0.76rem; font-weight:500; cursor:pointer; transition:background-color 0.15s, color 0.15s; }
.ts-merge-link:hover { background:var(--gray-100); color:var(--gray-700); }
.ts-field { margin-bottom:0.4rem; }
.ts-field:last-child { margin-bottom:0; }
.ts-field-label { font-size:0.72rem; font-weight:600; color:var(--gray-500); margin-bottom:0.2rem; }
.ts-field-value { font-size:0.85rem; color:var(--gray-700); }
.ts-select { width:100%; max-width:100%; min-width:0; box-sizing:border-box; padding:0.3rem 0.5rem; border:1px solid var(--gray-300); border-radius:0.35rem; font-size:0.82rem; background:var(--color-bg); }
.ts-save-btn { width:100%; padding:0.4rem; background:var(--color-primary); color:var(--color-on-accent); border:1px solid var(--color-primary-dark); border-radius:0.35rem; font-size:0.78rem; font-weight:600; cursor:pointer; margin-top:0.4rem; }

/* ── Kompakte Meta-Grid (Klassifizierung): Label links, Control rechts ── */
.ts-meta-grid { display:grid; grid-template-columns:75px minmax(0,1fr); gap:0.35rem 0.55rem; align-items:center; }
.ts-meta-grid > label { font-size:0.74rem; font-weight:600; color:var(--gray-500); line-height:1.2; }
.ts-meta-grid > .ts-select,
.ts-meta-grid > .ts-input,
.ts-meta-grid > .ss-wrap { margin:0; min-width:0; }

/* ── Inline-Toggle-Button im Card-Header (für „+ hinzufügen"-Pattern) ── */
.ts-card-header-btn {
    border:none; background:transparent; color:var(--gray-500);
    cursor:pointer; padding:0.15rem 0.4rem;
    font-size:0.85rem; line-height:1; border-radius:0.25rem;
    font-weight:700;
}
.ts-card-header-btn:hover { background:var(--gray-100); color:var(--gray-800); }
.ts-card-header-btn.is-open { background:var(--indigo-100); color:var(--indigo-800); }

/* ── Melder & Ersteller (Sidebar-Card) ────────────────────────── */
.ts-person-row { display:flex; align-items:center; gap:0.5rem; min-width:0; }
.ts-person-row + .ts-person-row { margin-top:0.45rem; padding-top:0.45rem; border-top:1px dashed var(--gray-200); }
.ts-person-avatar {
    flex:none; width:28px; height:28px; border-radius:50%;
    display:inline-flex; align-items:center; justify-content:center;
    background:var(--indigo-100); color:var(--indigo-800);
    font-size:0.68rem; font-weight:700;
}
.ts-person-avatar-photo { object-fit:cover; }
.ts-person-avatar-muted { background:var(--gray-100); color:var(--gray-500); font-size:0.8rem; }
.ts-person-info { display:flex; flex-direction:column; gap:0.05rem; min-width:0; }
.ts-person-name { font-size:0.85rem; font-weight:600; color:var(--gray-800); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ts-person-mail { font-size:0.73rem; color:var(--gray-500); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Rufnummern des Melders: umbrechen bei schmaler Sidebar, Pills bleiben ganz. */
.ts-person-phones { display:flex; flex-wrap:wrap; gap:0.3rem; margin-top:0.25rem; }
.ts-person-row-muted .ts-person-name { font-weight:500; color:var(--gray-600); }
.ts-person-badge {
    display:inline-block; margin-left:0.3rem; padding:0.05rem 0.4rem;
    border-radius:9999px; font-size:0.58rem; font-weight:700;
    text-transform:uppercase; letter-spacing:0.04em; vertical-align:1px;
    background:var(--indigo-100); color:var(--indigo-800);
}
.ts-person-badge-muted { background:var(--gray-100); color:var(--gray-500); }

/* ── Chip-Row für Watcher / Verknüpfungen / Assets ────────────── */
.ts-chip-row { display:flex; flex-wrap:wrap; gap:0.3rem; margin:0; padding:0; list-style:none; }
.ts-chip {
    display:inline-flex; align-items:center; gap:0.25rem;
    background:var(--slate-100); color:var(--slate-700);
    border:1px solid var(--slate-200);
    border-radius:9999px;
    padding:0.1rem 0.55rem;
    font-size:0.76rem; line-height:1.4;
    max-width:100%;
}
.ts-chip a { color:inherit; text-decoration:none; max-width:160px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-block; vertical-align:middle; }
.ts-chip a:hover { text-decoration:underline; }
.ts-chip .ts-chip-remove {
    border:none; background:transparent; color:var(--slate-400);
    cursor:pointer; padding:0 0.1rem; font-size:0.95rem; line-height:1;
}
.ts-chip .ts-chip-remove:hover { color:var(--red-600); }
.ts-chip--incoming { background:var(--yellow-100); border-color:var(--amber-200); color:var(--amber-900); }
.ts-chip--asset    { background:var(--cyan-50); border-color:var(--cyan-200); color:var(--cyan-800); }
.ts-empty-hint { font-size:0.76rem; color:var(--gray-400); margin:0; }
.ts-save-btn:hover { background:var(--color-primary-dark); }

/* ── Zeiterfassung: Liste der erfassten Zeiten ──────────────────────
   Eine Zeile je Erfassung: Person, Dauer, Stift. Das Eingabefeld
   erscheint erst auf Klick, damit die Liste auch bei vielen Einträgen
   ruhig bleibt. */
.ts-te-list { list-style:none; margin:0.4rem 0 0; padding:0; display:flex; flex-direction:column; gap:0.2rem; font-size:0.75rem; }
.ts-te { padding:0.25rem 0.4rem; background:var(--gray-50); border-radius:0.3rem; }
.ts-te-row { display:flex; align-items:baseline; gap:0.4rem; }
.ts-te-name { flex:1; min-width:0; font-weight:600; color:var(--gray-700); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ts-te-min { color:var(--indigo-800); font-weight:700; white-space:nowrap; }
.ts-te-edit-btn {
    border:none; background:transparent; color:var(--slate-400);
    cursor:pointer; padding:0 0.1rem; font-size:0.68rem; line-height:1;
}
.ts-te-edit-btn:hover { color:var(--color-primary); }
.ts-te-meta { color:var(--gray-500); margin-top:0.05rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ts-te-form { display:none; align-items:center; gap:0.3rem; margin-top:0.25rem; }
/* Höhe folgt den übrigen Bedienelementen der Karte; nur die Breiten sind
   auf den Inhalt abgestimmt – Platz für die Minuten, knapp für den Knopf. */
.ts-te-form .ts-te-input { width:5.5rem; padding:0.15rem 0.3rem; }
.ts-te-form .ts-te-save { margin:0; padding:0.15rem 0.35rem; }
.ts-te-cancel { border:none; background:transparent; color:var(--slate-400); cursor:pointer; padding:0 0.2rem; font-size:0.72rem; }
.ts-te-cancel:hover { color:var(--red-600); }
.ts-te.is-editing .ts-te-form { display:flex; }
.ts-te.is-editing .ts-te-meta,
.ts-te.is-editing .ts-te-min,
.ts-te.is-editing .ts-te-edit-btn { display:none; }

/* Herkunft eines Zeiteintrags: führt zur Antwort im Verlauf */
.ts-time-origin { color:var(--gray-500); text-decoration:underline dotted; }
.ts-time-origin:hover { color:var(--color-primary); }

/* Multi-select dropdown */
.ts-multiselect { position:relative; }
.ts-multiselect-trigger { display:flex; align-items:center; justify-content:space-between; padding:0.4rem 0.65rem; border:1px solid var(--gray-300); border-radius:0.35rem; background:var(--color-bg); cursor:pointer; font-size:0.85rem; user-select:none; min-height:2.1rem; }
.ts-multiselect-trigger:hover { border-color:var(--gray-400); }
.ts-multiselect-trigger.open   { border-color:var(--color-primary); box-shadow:0 0 0 2px rgba(var(--color-primary-rgb), .15); }
.ts-multiselect-tags { display:flex; flex-wrap:wrap; gap:0.25rem; flex:1; min-width:0; }
.ts-multiselect-tag  { display:inline-flex; align-items:center; gap:0.2rem; background:var(--blue-100); color:var(--blue-800); border-radius:9999px; padding:0.1rem 0.5rem; font-size:0.75rem; font-weight:600; white-space:nowrap; }
.ts-multiselect-placeholder { color:var(--gray-400); font-size:0.85rem; }
.ts-multiselect-chevron { flex-shrink:0; margin-left:0.4rem; color:var(--gray-400); transition:transform .15s; }
.ts-multiselect-trigger.open .ts-multiselect-chevron { transform:rotate(180deg); }
.ts-multiselect-panel { display:none; position:absolute; z-index:200; left:0; right:0; top:calc(100% + 3px); background:var(--color-bg); border:1px solid var(--gray-200); border-radius:0.35rem; box-shadow:0 6px 18px rgba(0,0,0,.1); overflow:hidden; }
.ts-multiselect-panel.open { display:block; }
.ts-multiselect-search { width:100%; padding:0.4rem 0.65rem; border:none; border-bottom:1px solid var(--gray-100); font-size:0.83rem; font-family:inherit; box-sizing:border-box; outline:none; }
.ts-multiselect-options { max-height:200px; overflow-y:auto; }
.ts-multiselect-option { display:flex; align-items:center; gap:0.5rem; padding:0.4rem 0.7rem; font-size:0.85rem; cursor:pointer; }
.ts-multiselect-option:hover { background:var(--gray-100); }
.ts-multiselect-option input[type=checkbox] { flex-shrink:0; accent-color:var(--color-primary); }
.ts-multiselect-empty { padding:0.6rem 0.7rem; font-size:0.82rem; color:var(--gray-400); }

/* Watcher modal */
.ts-modal-backdrop { display:none; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:900; align-items:center; justify-content:center; }
.ts-modal-backdrop.open { display:flex; }
.ts-modal { background:var(--color-bg); border-radius:0.5rem; box-shadow:0 8px 32px rgba(0,0,0,.18); width:100%; max-width:440px; max-height:90vh; display:flex; flex-direction:column; overflow:hidden; }
.ts-modal-header { display:flex; align-items:center; justify-content:space-between; padding:0.85rem 1.1rem; border-bottom:1px solid var(--gray-100); }
.ts-modal-title  { font-weight:700; font-size:0.95rem; }
.ts-modal-close  { border:none; background:none; font-size:1.3rem; cursor:pointer; color:var(--gray-400); line-height:1; padding:0; }
.ts-modal-close:hover { color:var(--gray-700); }
.ts-modal-tabs   { display:flex; border-bottom:1px solid var(--gray-100); }
.ts-modal-tab    { flex:1; padding:0.55rem 0.5rem; font-size:0.83rem; font-weight:600; cursor:pointer; text-align:center; color:var(--gray-400); border-bottom:2px solid transparent; background:none; border-top:none; border-left:none; border-right:none; }
.ts-modal-tab.active { color:var(--color-primary); border-bottom-color:var(--color-primary); }
.ts-modal-body   { padding:1rem; overflow-y:auto; flex:1; }
.ts-modal-footer { padding:0.75rem 1rem; border-top:1px solid var(--gray-100); display:flex; gap:0.5rem; justify-content:flex-end; }

/* ── Quick Actions (kompakt) ── */
.ts-quickactions .ts-card-body { display:flex; gap:0.4rem; flex-wrap:wrap; padding:0.45rem 0.65rem; }
.ts-qa-btn { width:34px; height:34px; display:flex; align-items:center; justify-content:center; border:1px solid var(--gray-200); background:var(--color-bg); color:var(--color-primary); border-radius:0.4rem; cursor:pointer; transition:all 0.15s; }
.ts-qa-btn:hover { background:var(--color-primary); color:var(--color-on-accent); border-color:var(--color-primary); }

/* ── Modals (Ticket→Bestellung, UniFi-Voucher, Ticket→Änderung, Asset-Schnellansicht) ──
   Gemeinsames Grundgerüst für alle vier Modals (Look 1:1 wie das /orders-Modal,
   Werte aus orders.css übernommen). Auf die jeweiligen Modal-IDs gescoped, damit keine
   anderen Ticket-Modals beeinflusst werden. Modal-spezifische Ergänzungen folgen
   jeweils darunter, auf die jeweilige ID gescoped. */
#to-order-modal, #uv-modal, #to-cl-modal, #asset-quick-modal { position:fixed; inset:0; background:rgba(0,0,0,0.5); display:none; align-items:center; justify-content:center; z-index:1000; padding:2rem; }
#to-order-modal.open, #uv-modal.open, #to-cl-modal.open, #asset-quick-modal.open { display:flex; }
#to-order-modal .modal-card, #uv-modal .modal-card, #to-cl-modal .modal-card, #asset-quick-modal .modal-card { background:var(--color-bg); border-radius:0.25rem; box-shadow:0 4px 16px rgba(0,0,0,0.2); width:100%; max-width:560px; max-height:90vh; overflow-y:auto; position:relative; }
/* Schnellaktions-Modals breiter, damit zusammengehörige Felder nebeneinander
   passen und der Dialog auf Laptops nicht gescrollt werden muss. */
#to-order-modal .modal-card, #to-loan-modal .modal-card, #uv-modal .modal-card, #to-cl-modal .modal-card { max-width:680px; }
#asset-quick-modal .modal-card { max-width:440px; }

/* Zwei-Spalten-Zeile in den Schnellaktions-Modals (bricht auf schmalen Screens um). */
.to-row { display:grid; grid-template-columns:1fr 1fr; gap:0 0.75rem; }
@media (max-width:560px) { .to-row { grid-template-columns:1fr; gap:0; } }
#to-order-modal .modal-header, #uv-modal .modal-header, #to-cl-modal .modal-header, #asset-quick-modal .modal-header { display:flex; justify-content:space-between; align-items:center; padding:1.25rem 1.5rem; border-bottom:1px solid var(--gray-200); }
#to-order-modal .modal-header h2, #uv-modal .modal-header h2, #to-cl-modal .modal-header h2, #asset-quick-modal .modal-header h2 { font-size:1.1rem; font-weight:600; margin:0; color:var(--gray-900); }
#to-order-modal .modal-close, #uv-modal .modal-close, #to-cl-modal .modal-close, #asset-quick-modal .modal-close { background:none; border:none; font-size:1.5rem; color:var(--gray-400); cursor:pointer; width:32px; height:32px; display:flex; align-items:center; justify-content:center; border-radius:0.25rem; }
#to-order-modal .modal-close:hover, #uv-modal .modal-close:hover, #to-cl-modal .modal-close:hover, #asset-quick-modal .modal-close:hover { background:var(--gray-100); color:var(--gray-700); }
#to-order-modal .modal-body, #uv-modal .modal-body, #to-cl-modal .modal-body, #asset-quick-modal .modal-body { padding:1.5rem; }
#to-order-modal .modal-footer, #uv-modal .modal-footer, #to-cl-modal .modal-footer, #asset-quick-modal .modal-footer { padding:1rem 1.5rem; border-top:1px solid var(--gray-200); display:flex; justify-content:flex-end; gap:0.75rem; }
#to-order-modal .form-group, #uv-modal .form-group, #to-cl-modal .form-group { margin-bottom:1rem; }
#to-order-modal .form-group:last-child, #uv-modal .form-group:last-child, #to-cl-modal .form-group:last-child { margin-bottom:0; }
#to-order-modal .form-group label, #uv-modal .form-group label, #to-cl-modal .form-group label { display:block; font-size:0.8rem; font-weight:600; color:var(--gray-700); margin-bottom:0.375rem; }
#to-order-modal .form-hint, #uv-modal .form-hint, #to-cl-modal .form-hint { font-weight:400; color:var(--gray-400); }
#to-cl-modal textarea.form-control { resize:vertical; }
/* Hinweis-Box („to-outcome“) wird von Bestellungs- und Änderungs-Modal genutzt */
#to-order-modal .to-outcome, #to-cl-modal .to-outcome { font-size:0.78rem; color:var(--gray-500); background:var(--blue-50); border-left:3px solid var(--color-primary); padding:0.6rem 0.75rem; border-radius:0.25rem; line-height:1.5; }

/* ── Asset-Schnellansicht: inhaltsspezifische Styles (Label/Wert-Zeilen, Status-Badge) ── */
#asset-quick-modal .aqm-loading { color:var(--gray-400); margin:0; font-size:0.85rem; }
#asset-quick-modal .aqm-row { display:flex; gap:0.75rem; padding:0.4rem 0; border-bottom:1px solid var(--gray-100); font-size:0.85rem; }
#asset-quick-modal .aqm-row:last-child { border-bottom:none; }
#asset-quick-modal .aqm-label { flex:0 0 38%; color:var(--gray-500); }
#asset-quick-modal .aqm-val { flex:1; color:var(--gray-900); word-break:break-word; }
#asset-quick-modal .aqm-badge { display:inline-block; padding:0.1rem 0.5rem; border-radius:999px; font-size:0.75rem; font-weight:600; background:var(--gray-200); color:var(--gray-700); }
#asset-quick-modal .aqm-badge.active { background:var(--green-100); color:var(--green-700); }
#asset-quick-modal .aqm-badge.storage { background:var(--yellow-100); color:var(--yellow-800); }
#asset-quick-modal .aqm-badge.decommissioned { background:var(--red-100); color:var(--red-700); }

/* ── Ticket→Bestellung-Modal: spezifische Ergänzungen ── */
#to-order-modal .form-control[readonly] { background:var(--gray-50); color:var(--gray-500); }
#to-order-modal .oc-rows { display:flex; flex-direction:column; gap:0.4rem; }
#to-order-modal .oc-row { display:flex; gap:0.5rem; align-items:center; }
#to-order-modal .oc-row .oc-name { flex:1; }
#to-order-modal .oc-row .oc-qty { width:72px; flex:0 0 auto; text-align:center; }
#to-order-modal .oc-row-remove { background:none; border:none; color:var(--gray-300); cursor:pointer; font-size:1.2rem; line-height:1; padding:0 0.3rem; transition:color 0.15s; }
#to-order-modal .oc-row-remove:hover { color:var(--red-500); }
#to-order-modal .oc-add-row { margin-top:0.5rem; background:none; border:1px dashed var(--slate-300); color:var(--color-primary); border-radius:0.25rem; padding:0.35rem 0.7rem; font-size:0.8rem; font-weight:600; cursor:pointer; transition:border-color 0.15s, background 0.15s; }
#to-order-modal .oc-add-row:hover { border-color:var(--color-primary); background:var(--blue-50); }
#to-order-modal .supplier-wrap { position:relative; }
#to-order-modal .supplier-dropdown { position:absolute; z-index:100; background:var(--color-bg); border:1px solid var(--gray-200); border-radius:0.25rem; box-shadow:0 4px 8px rgba(0,0,0,0.1); max-height:200px; overflow-y:auto; width:100%; display:none; }
#to-order-modal .supplier-option { padding:0.5rem 0.875rem; font-size:0.85rem; cursor:pointer; color:var(--gray-900); }
#to-order-modal .supplier-option:hover { background:var(--gray-100); }
#to-order-modal .supplier-no-result { padding:0.5rem 0.875rem; font-size:0.8rem; color:var(--gray-400); }
#to-order-modal .to-readonly { background:var(--gray-50); border:1px solid var(--slate-100); border-radius:0.25rem; padding:0.55rem 0.875rem; font-size:0.85rem; }
#to-order-modal .to-readonly .to-rcp { color:var(--gray-900); font-weight:600; }
#to-order-modal .to-readonly .to-rcp-mail { color:var(--gray-500); }
#to-order-modal .to-att-list { border:1px solid var(--gray-200); border-radius:0.25rem; overflow:hidden; }
#to-order-modal .to-att-opt { display:flex; align-items:center; gap:0.55rem; padding:0.5rem 0.875rem; border-bottom:1px solid var(--gray-100); font-size:0.85rem; cursor:pointer; }
#to-order-modal .to-att-opt:last-child { border-bottom:none; }
#to-order-modal .to-att-opt:hover { background:var(--gray-50); }
#to-order-modal .to-att-opt input { width:16px; height:16px; accent-color:var(--color-primary); flex:0 0 auto; }
#to-order-modal .to-att-opt .ic { width:20px; text-align:center; flex:0 0 auto; }
#to-order-modal .to-att-opt .nm { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#to-order-modal .to-att-opt .src { font-size:0.66rem; color:var(--gray-400); background:var(--gray-100); border-radius:3px; padding:0 0.3rem; flex:0 0 auto; }
#to-order-modal .to-att-opt .sz { color:var(--gray-400); font-size:0.72rem; flex:0 0 auto; }
#to-order-modal .to-forward-fields { margin-top:0.6rem; padding-left:0.85rem; border-left:3px solid var(--gray-200); }
#to-order-modal textarea.form-control { resize:vertical; }
#to-order-modal .to-forward-fields .form-group:last-child { margin-bottom:0; }
#to-order-modal .to-forward-fields .form-hint { font-size:0.75rem; color:var(--gray-500); line-height:1.5; }

/* ── UniFi-Voucher Modal: spezifische Ergänzungen ── */
#uv-modal .uv-code-box { background:var(--blue-50); border:1px dashed var(--color-primary); border-radius:0.25rem; padding:0.75rem 1rem; text-align:center; }
#uv-modal .uv-code { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:1.35rem; font-weight:700; letter-spacing:0.08em; color:var(--blue-700); user-select:all; }
#uv-modal .uv-result-actions { display:flex; gap:0.5rem; margin-top:0.75rem; }
#uv-modal .uv-result-actions .btn { flex:1; }
#uv-modal .uv-hint { margin-top:0.5rem; font-size:0.75rem; color:var(--amber-700); }

/* Quick-assign-me button */
.ts-assign-me-icon-btn { width:30px; height:30px; padding:0; flex-shrink:0; background:var(--color-primary); border:1px solid var(--color-primary-dark); border-radius:0.375rem; color:var(--color-on-accent); cursor:pointer; font-size:0.95rem; display:inline-flex; align-items:center; justify-content:center; }
.ts-assign-me-icon-btn:hover { background:var(--color-primary-dark); }

/* Closed banner */
/* Roter Akzent links, damit der terminale "Geschlossen"-Zustand sofort
   erkennbar ist. Vorher reines Grau, ging im Layout unter. */
.ts-closed-banner { background:var(--red-50); border:1px solid var(--red-200); border-left:4px solid var(--red-600); border-radius:0.25rem; padding:0.75rem 1rem; font-size:0.85rem; color:var(--red-800); font-weight:500; margin-bottom:1rem; }

/* Reply blocked notice */
.ts-reply-blocked { display:flex; align-items:center; gap:0.6rem; padding:0.875rem 1rem; color:var(--amber-800); background:var(--amber-50); border-top:1px solid var(--amber-200); font-size:0.85rem; }
.ts-reply-blocked-icon { font-size:1.1rem; flex-shrink:0; }

/* Anwesenheit: wer sieht dieses Ticket gerade an (rein informativ, sperrt nichts) */
.ts-viewers {
    display:inline-flex; align-items:center; gap:0.4rem;
    padding:0.2rem 0.6rem; border-radius:999px;
    background:var(--blue-50); color:var(--blue-800); border:1px solid var(--blue-200);
    font-size:0.78rem; font-weight:500; line-height:1.5;
}
.ts-viewers[hidden] { display:none; }
.ts-viewers-dot {
    width:7px; height:7px; border-radius:50%; background:var(--blue-500); flex-shrink:0;
    animation:ts-viewers-pulse 2s ease-in-out infinite;
}
@keyframes ts-viewers-pulse { 0%, 100% { opacity:1; } 50% { opacity:0.35; } }
@media (prefers-reduced-motion: reduce) { .ts-viewers-dot { animation:none; } }
/* In der Zuweisungs-Leiste umbricht der Hinweis eigenstaendig neben dem Button. */
.ts-reply-blocked .ts-viewers { flex:0 0 auto; }

/* Input */
.ts-input { width:100%; max-width:100%; min-width:0; padding:0.35rem 0.6rem; border:1px solid var(--gray-300); border-radius:0.35rem; font-size:0.85rem; font-family:inherit; box-sizing:border-box; }
.ts-input:focus { outline:none; border-color:var(--color-primary); }
input[type="datetime-local"].ts-input { font-size:0.78rem; }

/* Action buttons */
.ts-action-btn { display:block; width:100%; padding:0.5rem 0.75rem; border:none; border-radius:0.25rem; font-size:0.82rem; font-weight:600; cursor:pointer; text-align:left; margin-bottom:0.35rem; transition:opacity 0.15s; }
.ts-action-btn:last-child { margin-bottom:0; }
.ts-action-btn:hover { opacity:0.8; }
.ts-act-solve  { background:var(--indigo-100); color:var(--indigo-800); }
.ts-act-close  { background:var(--red-100); color:var(--red-600); }
.ts-act-reopen { background:var(--emerald-100); color:var(--emerald-800); }
.ts-act-delete { background:var(--red-100); color:var(--red-800); border:1px solid var(--red-300); }

/* Sidebar kollabiert jetzt schon bei 1024 px statt erst bei 960 — auf Tablets
   im Hochformat (768-1024) wurde der Thread sonst auf ~480 px gequetscht. */
@media(max-width:1024px) {
    .ts-layout { grid-template-columns:1fr; padding:1rem; }
}
@media(max-width:767px) {
    html, body         { height:auto; overflow:auto; }
    .wrapper           { min-height:100vh !important; height:auto; }
    .content-wrapper   { min-height:100vh !important; height:auto; overflow:visible; }
    .main-footer       { display:block; }
    .main-content      { overflow:visible; flex:1; }
    .ts-layout         { height:auto; overflow:visible; display:flex; flex-direction:column; padding:0.75rem; }
    .ts-thread         { flex:unset; overflow-y:visible; min-height:unset; }
    .ts-content-col    { overflow-y:visible; min-height:unset; }
    .ts-sidebar        { overflow-y:visible; min-height:unset; }
    /* Avatare auf Mobile ausblenden — die 38px + Gap kosten zu viel
       Bubble-Breite, Initialen sind im Bubble-Header sowieso doppelt. */
    .ts-avatar         { display:none; }
    .ts-bubble         { max-width:100%; }
}

/* ── Reply attachment upload strip ── */
.ts-attachment-upload { display:flex; align-items:center; flex-wrap:wrap; gap:0.4rem; padding:0.3rem 0.6rem; border-top:1px solid var(--gray-100); background:var(--gray-50); }
.ts-upload-label { display:inline-flex; align-items:center; gap:0.3rem; padding:0.2rem 0.55rem; border:1px solid var(--slate-200); border-radius:9999px; font-size:0.76rem; color:var(--gray-500); cursor:pointer; user-select:none; background:var(--color-bg); }
.ts-upload-label:hover { border-color:var(--gray-400); color:var(--gray-700); }
.ts-upload-chips { display:flex; flex-wrap:wrap; gap:0.25rem; }
.ts-attachment-chip-remove { background:transparent; border:none; color:var(--gray-400); font-size:1rem; line-height:1; padding:0 0 0 0.25rem; cursor:pointer; }
.ts-attachment-chip-remove:hover { color:var(--red-600); }

/* ── Drag & Drop overlay on the reply card ── */
.ts-reply-card { position:relative; transition:box-shadow 0.15s; }
.ts-reply-card.ts-drop-active { box-shadow:inset 0 0 0 3px var(--color-primary); background:var(--color-primary-pale); }
.ts-reply-card.ts-drop-active::after {
    content: 'Datei(en) hier ablegen, um sie als Anhang hinzuzufügen';
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    background:rgba(239, 246, 251, 0.85); color:var(--color-primary-strong); font-weight:600; font-size:0.9rem;
    border-radius:inherit; pointer-events:none; z-index:5;
}

/* ── Submit spinner during reply send ── */
.ts-submit-btn:disabled { opacity:0.7; cursor:wait; }
.ts-submit-spinner {
    display:inline-block; width:10px; height:10px; border-radius:50%;
    border:2px solid rgba(255,255,255,0.4); border-top-color:var(--color-on-accent);
    animation:ts-spin 0.7s linear infinite; vertical-align:middle; margin-right:0.35rem;
}
@keyframes ts-spin { to { transform:rotate(360deg); } }

/* ── Ticket-Header: ruhige Info-Spalte + abgesetzte Aktions-Zone ── */
.ts-head { align-items:center; padding:0.6rem 1.25rem; gap:1.25rem; }
.ts-head-info { min-width:0; flex:1; }
/* Titelzeile: Zurück-Pfeil + Betreff + Pills auf einer Höhe (umbruchfähig) */
.ts-head-titlebar { display:flex; align-items:center; flex-wrap:wrap; gap:0.6rem; min-width:0; }
.ts-head-back {
    flex-shrink:0; display:inline-flex; align-items:center; justify-content:center;
    width:32px; height:32px; border-radius:0.5rem;
    color:var(--gray-500); background:transparent; border:1px solid var(--gray-200);
    transition:background-color .15s, border-color .15s, color .15s;
}
.ts-head-back:hover { background:var(--gray-100); border-color:var(--gray-300); color:var(--gray-800); }
.ts-head-back:focus-visible { outline:2px solid var(--color-primary); outline-offset:1px; }
.ts-head-info h1 { font-size:1.3rem; font-weight:600; line-height:1.25; margin:0; color:var(--gray-800); min-width:0; }
/* Ticket-Nummer als gedämpftes Suffix — präsent, aber nicht laut */
.ts-head-id { font-weight:500; color:var(--gray-400); font-variant-numeric:tabular-nums; }

/* Aktions-Zone: rechtsbündig; Verlauf dezent durch Whitespace abgesetzt */
.ts-head-actions { gap:0.5rem; }
.ts-head-history { margin-left:0.35rem; }

@media (max-width:767px) {
    .ts-head { flex-direction:column; align-items:flex-start; }
    .ts-head-actions { align-self:stretch; }
}

/* ── Header-Pills (Status / Priority / Due) — wichtigste Trage-Info above the fold ── */
.ts-header-pills { display:flex; flex-wrap:wrap; align-items:center; gap:0.4rem; margin:0; }
.ts-pill { display:inline-flex; align-items:center; padding:0.2rem 0.65rem; border-radius:9999px; font-size:0.72rem; font-weight:700; white-space:nowrap; line-height:1.4; }
.ts-pill-status-new      { background:var(--ticket-status-new-bg);     color:var(--ticket-status-new-fg); }
.ts-pill-status-open     { background:var(--ticket-status-open-bg);    color:var(--ticket-status-open-fg); }
.ts-pill-status-waiting  { background:var(--ticket-status-waiting-bg); color:var(--ticket-status-waiting-fg); }
.ts-pill-status-solved   { background:var(--ticket-status-solved-bg);  color:var(--ticket-status-solved-fg); }
.ts-pill-status-closed   { background:var(--ticket-status-closed-bg);  color:var(--ticket-status-closed-fg); }
.ts-pill-prio-1 { background:var(--ticket-prio-1-bg); color:var(--ticket-prio-1-fg); }
.ts-pill-prio-2 { background:var(--ticket-prio-2-bg); color:var(--ticket-prio-2-fg); }
.ts-pill-prio-3 { background:var(--ticket-prio-3-bg); color:var(--ticket-prio-3-fg); }
.ts-pill-due-overdue { background:var(--ticket-overdue-bg); color:var(--ticket-overdue-fg); }
.ts-pill-due-soon    { background:var(--ticket-warning-bg); color:var(--ticket-warning-fg); }
.ts-pill-due-ok      { background:var(--ticket-muted-bg);   color:var(--ticket-muted-fg); }
.ts-pill-sla-pending { background:var(--ticket-info-bg);    color:var(--ticket-info-fg); }
.ts-pill-sla-overdue { background:var(--ticket-overdue-bg); color:var(--ticket-overdue-fg); }
.ts-pill-sla-met     { background:var(--ticket-success-bg); color:var(--ticket-success-fg); }
.ts-pill-sla-late    { background:var(--ticket-late-bg);    color:var(--ticket-late-fg); }

/* ── Stoppuhr-Card in der Sidebar (kompakt) ─────────────────── */
.ts-timer-display {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.5rem;
    padding: 0.35rem 0.55rem;
    border-radius: 0.4rem;
    margin-bottom: 0.5rem;
    border: 1px solid transparent;
}
.ts-timer-running {
    background: linear-gradient(180deg, var(--emerald-50) 0%, var(--emerald-100) 100%);
    border-color: var(--emerald-300);
}
.ts-timer-paused {
    background: linear-gradient(180deg, var(--amber-100) 0%, var(--amber-200) 100%);
    border-color: var(--amber-300);
}
.ts-timer-clock {
    font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
    font-size: 1.05rem; font-weight: 700;
    color: var(--gray-900); letter-spacing: 0.02em;
    line-height: 1.1;
}
.ts-timer-status {
    font-size: 0.7rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.03em;
    display: inline-flex; align-items: center; gap: 0.25rem;
}
.ts-timer-running .ts-timer-status { color: var(--emerald-700); }
.ts-timer-paused .ts-timer-status { color: var(--amber-800); }
.ts-timer-stop-row { display: flex; gap: 0.35rem; align-items: stretch; }
.ts-timer-stop-row > input { flex: 1; min-width: 0; margin: 0 !important; }
.ts-timer-stop-row > button { flex-shrink: 0; width: auto !important; margin: 0 !important; }

/* ── Timer-Indikator in der Ticket-Liste ────────────────────── */
@keyframes tkTimerPulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.4; }
}

/* ── Time-Tracking ──────────────────────────────────────────── */
.ts-pill-time { background:var(--indigo-100); color:var(--indigo-800); }
.ts-time-badge {
    display:inline-flex; align-items:center; gap:0.2rem;
    background:var(--indigo-100); color:var(--indigo-800);
    padding:0.05rem 0.4rem; border-radius:9999px;
    font-size:0.65rem; font-weight:700;
    margin-left:0.3rem;
}
.ts-time-input {
    display:inline-flex; align-items:center; gap:0.25rem;
    padding:0.2rem 0.5rem;
    background:var(--gray-100);
    border:1px solid var(--gray-200);
    border-radius:0.35rem;
    font-size:0.78rem;
    color:var(--gray-700);
}
.ts-time-input input {
    width:55px; border:none; background:transparent;
    font-size:0.82rem; font-weight:600; color:var(--gray-800);
    text-align:right; outline:none; padding:0;
    -moz-appearance:textfield;
}
.ts-time-input input::-webkit-outer-spin-button,
.ts-time-input input::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
.ts-time-input:focus-within { border-color:var(--color-primary); box-shadow:0 0 0 2px rgba(var(--color-primary-rgb), 0.15); }

/* ── Linked Tickets (Sidebar-Card) ──────────────────────────── */
.ts-link-item {
    display:flex; align-items:center; gap:0.4rem;
    padding:0.3rem 0.4rem;
    background:var(--slate-50);
    border:1px solid var(--gray-200);
    border-radius:0.35rem;
    font-size:0.8rem;
}
.ts-link-item--incoming { background:var(--gray-50); opacity:0.95; }
.ts-link-label { font-weight:600; color:var(--gray-600); flex-shrink:0; }
.ts-link-target { color:var(--color-primary-strong); text-decoration:none; flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ts-link-target:hover { text-decoration:underline; }

/* ── Antwortvorlagen-Auswahl (Modal mit Suche) ──────────────── */
.ts-canned-modal {
    position:fixed;
    inset:0;
    z-index:1055;
    display:flex;
    align-items:center;
    justify-content:center;
}
.ts-canned-modal[hidden] { display:none; }
.ts-canned-modal-backdrop {
    position:absolute;
    inset:0;
    background:rgba(0,0,0,0.45);
}
.ts-canned-modal-dialog {
    position:relative;
    background:var(--color-bg);
    border-radius:0.75rem;
    box-shadow:0 10px 40px rgba(0,0,0,0.25);
    width:90%;
    max-width:560px;
    max-height:80vh;
    display:flex;
    flex-direction:column;
    overflow:hidden;
}
.ts-canned-modal-header {
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding:1rem 1.25rem;
    border-bottom:1px solid var(--gray-200);
}
.ts-canned-modal-header h3 {
    margin:0;
    font-size:1.05rem;
    font-weight:600;
    color:var(--gray-900);
}
.ts-canned-modal-close {
    background:transparent;
    border:none;
    font-size:1.5rem;
    line-height:1;
    color:var(--gray-500);
    cursor:pointer;
    padding:0 0.25rem;
}
.ts-canned-modal-close:hover { color:var(--gray-900); }
.ts-canned-modal-search {
    position:relative;
    display:flex;
    align-items:center;
    padding:0.75rem 1.25rem;
    border-bottom:1px solid var(--gray-100);
}
.ts-canned-modal-search svg {
    position:absolute;
    left:1.6rem;
    color:var(--gray-400);
    pointer-events:none;
}
.ts-canned-modal-search input {
    width:100%;
    padding:0.55rem 0.75rem 0.55rem 2.1rem;
    border:1px solid var(--gray-200);
    border-radius:0.5rem;
    font-size:0.9rem;
    color:var(--gray-800);
}
.ts-canned-modal-search input:focus {
    outline:none;
    border-color:var(--color-primary);
    box-shadow:0 0 0 3px rgba(var(--color-primary-rgb), 0.15);
}
.ts-canned-modal-body {
    padding:0.5rem 0.75rem 0.75rem;
    overflow-y:auto;
}
.ts-canned-modal-list {
    list-style:none;
    margin:0;
    padding:0;
    display:flex;
    flex-direction:column;
    gap:0.3rem;
}
.ts-canned-modal-item[hidden] { display:none; }
.ts-canned-modal-btn {
    display:block;
    width:100%;
    text-align:left;
    padding:0.6rem 0.75rem;
    background:var(--gray-50);
    border:1px solid transparent;
    border-left:3px solid var(--color-primary);
    border-radius:0.35rem;
    cursor:pointer;
    transition:background-color .15s, border-color .15s;
}
.ts-canned-modal-btn:hover { background:var(--blue-50); border-color:var(--blue-200); border-left-color:var(--color-primary); }
.ts-canned-modal-btn:focus-visible { outline:2px solid var(--color-primary); outline-offset:1px; }
.ts-canned-modal-item-title {
    display:block;
    font-size:0.9rem;
    font-weight:600;
    color:var(--gray-800);
    line-height:1.3;
}
.ts-canned-modal-attach {
    display:inline-block;
    margin-left:0.4rem;
    font-size:0.72rem;
    font-weight:600;
    color:var(--blue-600);
    background:var(--blue-50);
    border:1px solid var(--blue-200);
    border-radius:0.35rem;
    padding:0.02rem 0.35rem;
    vertical-align:middle;
}
.ts-canned-modal-item-preview {
    display:block;
    margin-top:0.2rem;
    font-size:0.8rem;
    color:var(--gray-500);
    line-height:1.35;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
}
.ts-canned-modal-empty {
    color:var(--gray-500);
    font-size:0.9rem;
    text-align:center;
    margin:1.25rem 0;
}
@media(max-width:767px) {
    .ts-canned-modal-dialog { width:95%; max-height:90vh; }
}

/* ── Reply blocked: Quick-Action für „Mir zuweisen & antworten" ── */
/* Box layout (Text + Button nebeneinander, wickeln auf schmalen Viewports). */
.ts-reply-blocked { flex-wrap:wrap; }
.ts-reply-blocked-text { flex:1 1 300px; min-width:0; }
.ts-reply-blocked-form { margin:0; flex-shrink:0; }

/* ── Verlauf: Inline-Zeilen zwischen Chat-Bubbles ──────────────── */
.ts-history-row {
    display:flex;
    align-items:center;
    justify-content:center;
    gap:0.5rem;
    margin:0.25rem auto;
    padding:0.35rem 0.75rem;
    max-width:90%;
    font-size:0.8rem;
    color:var(--gray-500);
    background:transparent;
    border-top:1px dashed var(--gray-200);
    border-bottom:1px dashed var(--gray-200);
}
.ts-history-row-icon { font-size:0.95rem; flex-shrink:0; }
.ts-history-row-text { flex:1 1 auto; text-align:center; }
.ts-history-row-time { flex-shrink:0; color:var(--gray-400); font-size:0.75rem; white-space:nowrap; }

/* ── Verlauf: Icon-Button im Header ──────────────────────────── */
.ts-history-icon-btn {
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:34px;
    height:34px;
    padding:0;
    background:transparent;
    border:1px solid var(--gray-200);
    border-radius:0.5rem;
    color:var(--gray-600);
    font-size:1.05rem;
    cursor:pointer;
    transition:background-color .15s, border-color .15s;
}
.ts-history-icon-btn:hover { background:var(--gray-100); border-color:var(--gray-300); }
.ts-history-icon-btn:focus-visible { outline:2px solid var(--color-primary); outline-offset:1px; }

/* ── Verlauf: Modal mit vollständiger Audit-Timeline ─────────── */
.ts-history-modal {
    position:fixed;
    inset:0;
    z-index:1055;
    display:flex;
    align-items:center;
    justify-content:center;
}
.ts-history-modal[hidden] { display:none; }
.ts-history-modal-backdrop {
    position:absolute;
    inset:0;
    background:rgba(0,0,0,0.45);
}
.ts-history-modal-dialog {
    position:relative;
    background:var(--color-bg);
    border-radius:0.75rem;
    box-shadow:0 10px 40px rgba(0,0,0,0.25);
    width:90%;
    max-width:560px;
    max-height:80vh;
    display:flex;
    flex-direction:column;
    overflow:hidden;
}
.ts-history-modal-header {
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding:1rem 1.25rem;
    border-bottom:1px solid var(--gray-200);
}
.ts-history-modal-header h3 {
    margin:0;
    font-size:1.05rem;
    font-weight:600;
    color:var(--gray-900);
}
.ts-history-modal-close {
    background:transparent;
    border:none;
    font-size:1.5rem;
    line-height:1;
    color:var(--gray-500);
    cursor:pointer;
    padding:0 0.25rem;
}
.ts-history-modal-close:hover { color:var(--gray-900); }
.ts-history-modal-body {
    padding:0.75rem 1.25rem 1.25rem;
    overflow-y:auto;
}
.ts-history-list {
    list-style:none;
    margin:0;
    padding:0;
    display:flex;
    flex-direction:column;
    gap:0.6rem;
}
.ts-history-list-item {
    display:flex;
    align-items:flex-start;
    gap:0.75rem;
    padding:0.6rem 0.75rem;
    background:var(--gray-50);
    border-left:3px solid var(--color-primary);
    border-radius:0.35rem;
}
.ts-history-list-icon {
    flex-shrink:0;
    font-size:1.05rem;
    line-height:1.4;
}
.ts-history-list-content { flex:1 1 auto; min-width:0; }
.ts-history-list-text { color:var(--gray-800); font-size:0.9rem; line-height:1.4; }
.ts-history-list-time { color:var(--gray-500); font-size:0.75rem; margin-top:0.15rem; }
.ts-history-empty { color:var(--gray-500); font-size:0.9rem; text-align:center; margin:1rem 0; }

@media(max-width:767px) {
    .ts-history-row { font-size:0.75rem; max-width:100%; gap:0.35rem; padding:0.3rem 0.5rem; }
    .ts-history-row-time { font-size:0.7rem; }
    .ts-history-modal-dialog { width:95%; max-height:90vh; }
}

/* ── Endgültig-schließen-Bestätigung (Modal) ──────────────────
   Eigene Klasse statt nativem confirm(), damit wir Solve vs. Close
   inhaltlich erklären können und nicht nur einen lapidaren
   „wirklich?"-Dialog zeigen. */
.ts-confirm-modal { position:fixed; inset:0; z-index:1060; display:flex; align-items:center; justify-content:center; }
.ts-confirm-modal[hidden] { display:none; }
.ts-confirm-modal-backdrop { position:absolute; inset:0; background:rgba(0,0,0,0.45); }
.ts-confirm-modal-dialog {
    position:relative; background:var(--color-bg); border-radius:0.75rem;
    box-shadow:0 10px 40px rgba(0,0,0,0.25);
    width:90%; max-width:480px; max-height:80vh;
    display:flex; flex-direction:column; overflow:hidden;
}
.ts-confirm-modal-header { padding:1rem 1.25rem 0.5rem; }
.ts-confirm-modal-header h3 { margin:0; font-size:1.05rem; font-weight:600; color:var(--gray-900); }
.ts-confirm-modal-body { padding:0.5rem 1.25rem 1rem; line-height:1.5; color:var(--gray-800); font-size:0.92rem; }
.ts-confirm-modal-body p { margin:0; }
.ts-confirm-modal-footer { display:flex; justify-content:flex-end; gap:0.5rem; padding:0.75rem 1.25rem 1rem; border-top:1px solid var(--gray-100); background:var(--gray-50); }

/* @Mention: Token im Text + Autovervollständigungs-Dropdown */
.ts-mention { background:var(--blue-100); color:var(--blue-700); border-radius:4px; padding:0 3px; font-weight:600; white-space:nowrap; }
.ts-mention-dd { position:absolute; z-index:3000; min-width:180px; max-width:280px; background:var(--color-bg, var(--color-bg)); border:1px solid var(--gray-200); border-radius:6px; box-shadow:0 6px 20px rgba(0,0,0,.15); overflow:hidden; font-size:0.85rem; }
.ts-mention-opt { padding:0.4rem 0.7rem; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:var(--gray-800); }
.ts-mention-opt.active, .ts-mention-opt:hover { background:var(--blue-50); }

/* CSAT-Bewertung des Melders (Sidebar, schreibgeschützt). */
.ts-csat-stars { display: inline-flex; gap: 2px; font-size: 1.15rem; line-height: 1; }
.ts-csat-star { color: var(--gray-300); }
.ts-csat-star.is-on { color: var(--amber-500); }

/* ── Spaltenauswahl ──
   Eine Häkchenliste im Dialog der Liste. Ein Eintrag je Zeile, damit die
   Erläuterung unter der Beschriftung Platz hat. */
.tk-cols-list { display:flex; flex-direction:column; gap:0.1rem; }
.tk-cols-item {
    display:flex; align-items:flex-start; gap:0.6rem;
    padding:0.45rem 0.5rem; border-radius:0.35rem;
    font-size:0.85rem; font-weight:500; cursor:pointer;
}
.tk-cols-item:hover { background:var(--gray-50); }
.tk-cols-item input { margin-top:0.2rem; flex:none; }
.tk-cols-hint { display:block; font-weight:400; font-size:0.72rem; color:var(--gray-500); }