/* ============================================================
   ANRO Support Pult — design system
   Referenz: "SupportPro" (helle SaaS-Helpdesk-Optik, 3-Spalten).
   Kein CDN — alles hier, System-Font, Inline-SVG-Icons in Templates.
   Akzentfarbe per CSS var --accent, Umschaltung über html[data-accent].
   ============================================================ */

:root{
  --bg:            #F6F8FB;
  --surface:       #FFFFFF;
  --surface-alt:   #FAFBFD;
  --border:        #E6EAF2;
  --border-strong: #D8DEEA;

  --text:          #1D2433;
  --text-muted:    #6B7280;
  --text-faint:    #9AA3B2;

  --radius-sm: 8px;
  --radius:    10px;
  --radius-lg: 12px;
  --radius-xl: 16px;

  --shadow-sm: 0 1px 2px rgba(16,24,40,.04);
  --shadow:    0 1px 3px rgba(16,24,40,.07), 0 1px 2px rgba(16,24,40,.05);
  --shadow-lg: 0 8px 24px rgba(16,24,40,.10), 0 2px 6px rgba(16,24,40,.06);

  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* default accent: blau (SupportPro-Referenz) */
  --accent:       #2563EB;
  --accent-hover: #1D4ED8;
  --accent-light: #EFF4FF;
  --accent-ring:  rgba(37,99,235,.18);

  --green: #16A34A; --green-bg: #DCFCE7; --green-line:#BBF7D0;
  --amber: #B45309; --amber-bg: #FEF3C7; --amber-line:#FDE68A;
  --red:   #DC2626; --red-bg:   #FEE2E2; --red-line:  #FECACA;
  --blue:  #2563EB; --blue-bg:  #DBEAFE; --blue-line: #BFDBFE;
  --grey:  #6B7280; --grey-bg:  #F1F5F9; --grey-line: #E2E8F0;
  --violet:#7C3AED; --violet-bg:#EDE9FE; --violet-line:#DDD6FE;

  --sidebar-w: 230px;
  --list-w: 340px;     /* schmale Ticket-Spalte, wenn ein Ticket offen ist — per Drag-Handle
                          und localStorage (anro_support_listw) veränderbar, siehe pult.js */
  --topbar-h: 60px;
  --resizer-w: 14px;
  --resizer-h: 10px;   /* horizontale Composer-Resize-Leiste, s. .composer-resizer unten */
  --composer-w: 380px; /* Composer-Breite in Position "right" — per Drag +
                           localStorage (anro_support_composerw) veränderbar */
}

/* Alternatives Farbschema: ANRO-Orange + dunkle Sidebar-Akzente.
   Roman entscheidet live, welches Schema bleibt (Umschalter unten links). */
html[data-accent="anro"]{
  --accent:       #F39200;
  --accent-hover: #D97F00;
  --accent-light: #FFF3E0;
  --accent-ring:  rgba(243,146,0,.20);
  --dark: #0E252C;
}
html:not([data-accent="anro"]){ --dark: #16233A; }

/* ============================================================
   Dark Theme (2026-07-28, Punkt 2 des Brief) — html[data-theme] hat 3 Zustände:
   kein Attribut/"auto" = folgt prefers-color-scheme (System), "light" = fest
   hell, "dark" = fest dunkel. Umschalter: 🌓-Button neben dem Akzent-Switch in
   der Sidebar (s. base.html initThemeSwitch in pult.js), localStorage-Key
   anro_support_theme, VOR dem ersten Paint gesetzt (s. Pre-Paint-Script in
   base.html/login.html) — kein Flash von hell→dunkel beim Laden.
   Beide Akzente (Blau + ANRO-Orange) bekommen eigene, für Dunkel-Hintergrund
   angepasste Töne (heller/gesättigter als im Hellmodus, sonst zu blass/matt
   auf #0F1115) — Kontrast von Pillen/Buttons in beiden Themes geprüft.
   Zwei identische Regelsätze: (a) @media prefers-color-scheme:dark — Auto-
   Modus, nur wenn kein explizites data-theme="light" gesetzt ist; (b)
   html[data-theme="dark"] — expliziter Wechsel, unabhängig vom System.
   ============================================================ */
html[data-theme="dark"]{
  --bg:            #0F1115;
  --surface:       #171A21;
  --surface-alt:   #1D212B;
  --border:        #262B36;
  --border-strong: #333A48;

  --text:          #E5E9F0;
  --text-muted:    #9AA3B5;
  --text-faint:    #8A93A5;

  --dark: #2B3242; /* Avatar-/Toast-Bubble — heller als --surface, sonst unsichtbar */

  --shadow-sm: 0 1px 2px rgba(0,0,0,.35);
  --shadow:    0 1px 3px rgba(0,0,0,.45), 0 1px 2px rgba(0,0,0,.35);
  --shadow-lg: 0 8px 24px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.40);

  /* Statusfarben — hellere/gesättigtere Töne für Lesbarkeit als Text auf
     dunklem Grund, *-bg als transluzentes Overlay statt fast-weißer Fläche
     (die helle -bg-Variante wäre auf #171A21 ein blindender Fleck). */
  --green: #4ADE80; --green-bg: rgba(74,222,128,.16);  --green-line: rgba(74,222,128,.4);
  --amber: #FBBF24; --amber-bg: rgba(251,191,36,.16);  --amber-line: rgba(251,191,36,.4);
  --red:   #F87171; --red-bg:   rgba(248,113,113,.16); --red-line:   rgba(248,113,113,.4);
  --blue:  #60A5FA; --blue-bg:  rgba(96,165,250,.16);  --blue-line:  rgba(96,165,250,.4);
  --grey:  #A7AFC0; --grey-bg:  rgba(167,175,192,.14); --grey-line:  rgba(167,175,192,.3);
  --violet:#C4B5FD; --violet-bg:rgba(196,181,253,.16); --violet-line:rgba(196,181,253,.4);
}
html[data-theme="dark"]:not([data-accent="anro"]){
  --accent:       #3B82F6;
  --accent-hover: #60A5FA;
  --accent-light: rgba(59,130,246,.16);
  --accent-ring:  rgba(59,130,246,.35);
}
html[data-theme="dark"][data-accent="anro"]{
  --accent:       #F5A623;
  --accent-hover: #FFBB4D;
  --accent-light: rgba(245,166,35,.16);
  --accent-ring:  rgba(245,166,35,.35);
}
@media (prefers-color-scheme: dark){
  html:not([data-theme="light"]){
    --bg:            #0F1115;
    --surface:       #171A21;
    --surface-alt:   #1D212B;
    --border:        #262B36;
    --border-strong: #333A48;

    --text:          #E5E9F0;
    --text-muted:    #9AA3B5;
    --text-faint:    #8A93A5;

    --dark: #2B3242;

    --shadow-sm: 0 1px 2px rgba(0,0,0,.35);
    --shadow:    0 1px 3px rgba(0,0,0,.45), 0 1px 2px rgba(0,0,0,.35);
    --shadow-lg: 0 8px 24px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.40);

    --green: #4ADE80; --green-bg: rgba(74,222,128,.16);  --green-line: rgba(74,222,128,.4);
    --amber: #FBBF24; --amber-bg: rgba(251,191,36,.16);  --amber-line: rgba(251,191,36,.4);
    --red:   #F87171; --red-bg:   rgba(248,113,113,.16); --red-line:   rgba(248,113,113,.4);
    --blue:  #60A5FA; --blue-bg:  rgba(96,165,250,.16);  --blue-line:  rgba(96,165,250,.4);
    --grey:  #A7AFC0; --grey-bg:  rgba(167,175,192,.14); --grey-line:  rgba(167,175,192,.3);
    --violet:#C4B5FD; --violet-bg:rgba(196,181,253,.16); --violet-line:rgba(196,181,253,.4);
  }
  html:not([data-theme="light"]):not([data-accent="anro"]){
    --accent:       #3B82F6;
    --accent-hover: #60A5FA;
    --accent-light: rgba(59,130,246,.16);
    --accent-ring:  rgba(59,130,246,.35);
  }
  html:not([data-theme="light"])[data-accent="anro"]{
    --accent:       #F5A623;
    --accent-hover: #FFBB4D;
    --accent-light: rgba(245,166,35,.16);
    --accent-ring:  rgba(245,166,35,.35);
  }
}
/* Scrollbar-Look (Chromium/Firefox) an das Theme koppeln, sonst blitzt im
   Dark-Mode die helle System-Standard-Scrollbar auf. */
html[data-theme="dark"]{ color-scheme: dark; }
@media (prefers-color-scheme: dark){ html:not([data-theme="light"]){ color-scheme: dark; } }
html[data-theme="light"]{ color-scheme: light; }

*, *::before, *::after{ box-sizing:border-box; }
html, body{ height:100%; }
body{
  margin:0;
  font-family:var(--font);
  font-size:14px;
  line-height:1.5;
  color:var(--text);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
}
a{ color:inherit; text-decoration:none; }
button{ font-family:inherit; }
ul, ol{ list-style:none; margin:0; padding:0; }
h1,h2,h3,h4{ margin:0; font-weight:600; }
img{ max-width:100%; }
/* Auswahl KONTRASTREICH (Roman 2026-08-04 «не могу выделять»): vorher lag hier
   var(--accent-light) = 16%-transparentes Blau — auf hellen Bildschirmen
   praktisch unsichtbar. Die Auswahl FUNKTIONIERTE die ganze Zeit, man SAH sie
   nur nicht. Jetzt: kräftige Akzentfarbe + weiße Schrift, unübersehbar. */
::selection{ background:var(--accent); color:#fff; }

/* Sicherheitsnetz (2026-07-28, Playwright hat den Bug gefunden): das [hidden]-
   Attribut hat laut UA-Stylesheet nur `display:none` mit Attribut-Selector-
   Spezifität (0,1,0) — GENAU dieselbe Spezifität wie eine Klasse (.pill/.btn/…),
   die selbst ein explizites `display` setzt. Bei Gleichstand gewinnt die
   AUTOR-Regel (diese Datei) über die UA-Default-Regel, unabhängig von der
   Quellreihenfolge — ein `<span class="pill" hidden>` blieb dadurch sichtbar
   (reproduziert: .snooze-badge/.pill UND [data-unsnooze-btn]/.btn). Diese
   Regel MUSS vor allen anderen stehen (nicht wegen Kaskaden-Reihenfolge, s.o.,
   sondern damit sie inhaltlich zuerst gilt) — `!important` ist hier bewusst
   und notwendig, kein Stilfehler: ein [hidden]-Element MUSS immer unsichtbar
   sein, ausnahmslos. */
[hidden]{ display:none !important; }

.icon{ width:18px; height:18px; flex:none; stroke:currentColor; fill:none; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; }
.icon-sm{ width:15px; height:15px; }
.icon-lg{ width:22px; height:22px; }

/* ============================================================
   Shell — Layout v2 (2026-07-27, Roman: «двигать окна», «список справа,
   переписка в центре»). .shell ist der Grid-Container, sidebar/ticket-region/
   col-resizer/conv-region sind direkte Kinder mit eigenem grid-area — welches
   Kind wohin gehört, hängt NUR von CSS-Klassen ab (kein DOM-Reparenting beim
   Öffnen/Schließen eines Tickets, siehe pult.js loadTicketPanel/closeTicket).

   Zustand 1 — .list-only (kein Ticket offen): ticket-region = volle Breite,
   genau wie vorher (Roman: «Список тикетов ок» — nicht anfassen).
   Zustand 2 — .ticket-open: ticket-region wird zur schmalen Liste (--list-w,
   Default 340px), conv-region (die Konversation) wird zur breiten Hauptfläche.
   Reihenfolge per html[data-listpos] — Default (kein Attribut) = Liste RECHTS
   (Roman-Wunsch), data-listpos="left" = Liste links (Umschalter im Resizer).
   ============================================================ */
.shell{
  min-height:100vh;
  display:grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-areas: "sidebar main";
  align-items:stretch;
}
.sidebar{ grid-area:sidebar; }
.ticket-region{ grid-area:main; min-width:0; display:flex; flex-direction:column; }
.conv-region, .col-resizer{ display:none; }

.shell.ticket-open{
  grid-template-columns: var(--sidebar-w) 1fr var(--resizer-w) var(--list-w);
  grid-template-areas: "sidebar conv resizer list";
}
html[data-listpos="left"] .shell.ticket-open{
  grid-template-columns: var(--sidebar-w) var(--list-w) var(--resizer-w) 1fr;
  grid-template-areas: "sidebar list resizer conv";
}
.shell.ticket-open .ticket-region{ grid-area:list; }
.shell.ticket-open .conv-region{ grid-area:conv; display:flex; }
.shell.ticket-open .col-resizer{ grid-area:resizer; display:flex; }

/* ---------------- Sidebar ---------------- */
.sidebar{
  grid-area:sidebar;
  background:var(--surface);
  border-right:1px solid var(--border);
  display:flex; flex-direction:column;
  padding:var(--sp-4) var(--sp-3);
  gap:var(--sp-5);
  position:sticky; top:0; height:100vh; overflow-y:auto;
}
.brand{ display:flex; align-items:center; gap:var(--sp-2); padding:var(--sp-1) var(--sp-2) var(--sp-2); }
/* Seit 2026-08-01 ein Bild (static/favicon.svg) statt eines gefärbten
   Kästchens mit Buchstaben — dasselbe Zeichen wie im Browser-Tab, damit Tab
   und Seitenleiste dieselbe Marke zeigen. Farben stecken in der Grafik, hier
   deshalb kein background/color mehr; die Regel gilt weiter für <span> wie
   <img> (Login-Seiten überschreiben nur die Größe). */
.brand-mark{
  width:30px; height:30px; border-radius:9px; flex:none;
  display:block; object-fit:contain;
  box-shadow:0 1px 2px rgba(16,24,40,.15);
}
.brand-name{ font-weight:700; font-size:14.5px; letter-spacing:-.01em; color:var(--text); }
/* Kanal ohne offene Tickets (Marktplatz-Aufteilung): sichtbar, aber blass —
   die Liste bleibt eine vollständige Karte, der Blick bleibt bei der Arbeit. */
.nav-item-empty{ opacity:.5; }
/* Widerspruch bei der Kundenzuordnung — muss auffallen, sonst antwortet man
   mit der falschen Bestellnummer (Codex-Audit 2026-08-01). */
.order-items{ margin-top:8px; border-top:1px solid var(--border); padding-top:8px; display:flex; flex-direction:column; gap:5px; }
.order-item{ display:flex; align-items:baseline; gap:8px; font-size:12.5px; }
.oi-qty{ color:var(--text-muted); font-variant-numeric:tabular-nums; white-space:nowrap; min-width:44px; }
.oi-name{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text); }
.oi-sku{ font-family:var(--font-mono,monospace); font-size:11px; color:var(--text-faint); white-space:nowrap; }
.oi-price{ font-variant-numeric:tabular-nums; color:var(--text-muted); white-space:nowrap; }
.cw-conflict{
  background:var(--amber-bg); border:1px solid var(--amber-line); color:var(--text);
  border-radius:var(--radius-sm); padding:7px 9px; font-size:12px; margin-bottom:8px;
}
.nav-item-empty:hover{ opacity:1; }

/* ── Bild-Betrachter (2026-08-01) ─────────────────────────────────────────
   Dunkler Hintergrund, damit das Bild und nicht die Oberfläche wirkt. Das
   <img> bleibt ein echtes Bild — der Rechtsklick des Browsers («Bild
   speichern unter…») soll funktionieren, deshalb liegt NICHTS darüber. */
.lb-overlay{
  position:fixed; inset:0; z-index:9999; background:rgba(12,16,24,.92);
  display:flex; align-items:center; justify-content:center; gap:10px; padding:56px 16px 24px;
}
.lb-overlay[hidden]{ display:none; }
.lb-img{ max-width:92vw; max-height:calc(100vh - 96px); object-fit:contain; border-radius:6px; background:#fff; }
.lb-bar{
  position:absolute; top:0; left:0; right:0; height:48px; display:flex; align-items:center;
  gap:10px; padding:0 14px; background:rgba(0,0,0,.45); color:#fff; font-size:12.5px;
}
.lb-name{ font-weight:600; max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lb-count{ color:rgba(255,255,255,.7); }
.lb-btn{
  margin-left:auto; color:#fff; text-decoration:none; font-size:12.5px;
  border:1px solid rgba(255,255,255,.35); border-radius:6px; padding:4px 10px; background:none; cursor:pointer;
}
.lb-btn + .lb-btn{ margin-left:6px; }
.lb-btn:hover{ background:rgba(255,255,255,.14); }
.lb-close{ font-size:14px; line-height:1; }
.lb-nav{
  background:rgba(255,255,255,.12); color:#fff; border:none; border-radius:50%;
  width:40px; height:40px; font-size:24px; line-height:1; cursor:pointer; flex:none;
}
.lb-nav:hover{ background:rgba(255,255,255,.25); }
.lb-nav[hidden]{ display:none; }

.nav-group{ display:flex; flex-direction:column; gap:2px; }
.nav-label{
  font-size:10.5px; font-weight:700; letter-spacing:.07em; color:var(--text-faint);
  text-transform:uppercase; padding:var(--sp-2) var(--sp-2) 2px;
}
.nav-item{
  display:flex; align-items:center; gap:var(--sp-2);
  padding:7px var(--sp-2); border-radius:var(--radius-sm);
  color:var(--text-muted); font-size:13.5px; font-weight:500;
  cursor:pointer; border:none; background:none; width:100%; text-align:left;
}
.nav-item .icon{ color:var(--text-faint); }
.nav-item:hover{ background:var(--surface-alt); color:var(--text); }
.nav-item.active{
  background:var(--accent-light); color:var(--accent-hover); font-weight:600;
}
.nav-item.active .icon{ color:var(--accent); }
.nav-item .count{
  margin-left:auto; font-size:11px; font-weight:700; color:var(--text-faint);
  background:var(--grey-bg); border-radius:99px; padding:1px 7px; min-width:20px; text-align:center;
}
.nav-item.active .count{ background:var(--surface); color:var(--accent); }
.nav-item.stub{ cursor:default; opacity:.55; }
.nav-item.stub:hover{ background:none; color:var(--text-muted); }
.nav-item.view-link .count{ background:var(--grey-bg); color:var(--text-muted); }

/* Интент-фильтр — aufklappbare Untergruppe (Roman 2026-07-28+, s. base.html) */
.nav-intent-group{ display:flex; flex-direction:column; gap:2px; }
.nav-intent-summary{
  cursor:pointer; list-style:none; display:flex; align-items:center; justify-content:space-between;
}
.nav-intent-summary::-webkit-details-marker{ display:none; }
.nav-intent-summary::after{ content:'▸'; font-size:10px; color:var(--text-faint); transition:transform .15s; }
.nav-intent-group[open] .nav-intent-summary::after{ transform:rotate(90deg); }
.nav-intent-group .nav-item{ padding-left:calc(var(--sp-2) + 10px); }

.sidebar-spacer{ flex:1; }

.accent-switch{
  display:flex; align-items:center; justify-content:space-between;
  padding:var(--sp-2); border:1px dashed var(--border-strong); border-radius:var(--radius-sm);
  font-size:12px; color:var(--text-muted);
}
.accent-switch button{
  border:1px solid var(--border-strong); background:var(--surface); border-radius:7px;
  width:28px; height:28px; cursor:pointer; font-size:14px; display:flex; align-items:center; justify-content:center;
}
.accent-switch button.active{ border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-ring); }

/* Sprachblock kompakt (Roman 2026-07-29: «язык уменьши») — ~1.5x kleiner als
   der normale .accent-switch-Block (Design/Akzent): weniger Padding, kleinere
   Buttons/Schrift. Lesbarkeit bleibt (10.5px ist noch gut lesbar für RU/DE/EN),
   funktioniert in beiden Themes (nutzt dieselben --border-strong/--surface/
   --accent-Variablen wie .accent-switch). */
.lang-switch-sm{ padding:5px var(--sp-2); font-size:10.5px; }
.lang-switch-sm button{
  width:auto; height:19px; min-width:19px; padding:0 5px;
  font-size:10.5px; font-weight:600; border-radius:6px;
}
.lang-switch-sm button.active{ border-color:var(--accent); box-shadow:0 0 0 1.5px var(--accent-ring); }

.user-card{
  display:flex; align-items:center; gap:var(--sp-2);
  padding:var(--sp-2); border-radius:var(--radius); border:1px solid var(--border);
  background:var(--surface-alt);
}
.avatar{
  width:32px; height:32px; border-radius:50%; flex:none;
  background:var(--dark); color:#fff; font-weight:700; font-size:12.5px;
  display:flex; align-items:center; justify-content:center;
}
.avatar.sm{ width:24px; height:24px; font-size:10.5px; }
.user-card-body{ min-width:0; flex:1; }
.user-card-name{ font-size:13px; font-weight:600; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.user-card-role{ font-size:11px; color:var(--text-faint); }
.user-card-logout{
  flex:none; width:26px; height:26px; border-radius:7px; display:flex; align-items:center; justify-content:center;
  color:var(--text-faint); border:1px solid transparent;
}
.user-card-logout:hover{ background:var(--surface); border-color:var(--border); color:var(--red); }

/* ---------------- Ticket-region (Tabelle — voll in list-only, schmal in ticket-open) ---------------- */
.topbar{
  height:var(--topbar-h); flex:none;
  display:flex; align-items:center; gap:var(--sp-3);
  padding:0 var(--sp-5); border-bottom:1px solid var(--border);
  background:var(--surface); position:sticky; top:0; z-index:5;
}
.topbar-form{ display:flex; align-items:center; gap:var(--sp-2); flex:1; min-width:0; }

.search-box{
  display:flex; align-items:center; gap:var(--sp-2);
  background:var(--surface-alt); border:1px solid var(--border);
  border-radius:var(--radius-sm); padding:0 var(--sp-3); height:36px;
  flex:1; max-width:420px; color:var(--text-faint);
}
.search-box:focus-within{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-ring); background:var(--surface); }
.search-box input{
  border:none; outline:none; background:transparent; font-size:13.5px; color:var(--text); width:100%; height:100%;
}
.search-box input::placeholder{ color:var(--text-faint); }

.btn{
  display:inline-flex; align-items:center; gap:6px; justify-content:center;
  height:36px; padding:0 var(--sp-3); border-radius:var(--radius-sm);
  font-size:13px; font-weight:600; cursor:pointer; border:1px solid transparent;
  white-space:nowrap; line-height:1;
}
.btn-sm{ height:30px; padding:0 var(--sp-2); font-size:12.5px; }
.btn-primary{ background:var(--accent); color:#fff; }
.btn-primary:hover{ background:var(--accent-hover); }
.btn-outline{ background:var(--surface); border-color:var(--border-strong); color:var(--text); }
.btn-outline:hover{ background:var(--surface-alt); border-color:var(--text-faint); }
.btn-ghost{ background:transparent; color:var(--text-muted); }
.btn-ghost:hover{ background:var(--surface-alt); color:var(--text); }
.btn:disabled, .btn[aria-disabled="true"]{
  opacity:.5; cursor:not-allowed; pointer-events:none;
}
.btn[data-locked]{ opacity:.6; cursor:not-allowed; }

details.filter-pop{ position:relative; }
details.filter-pop > summary{ list-style:none; cursor:pointer; }
details.filter-pop > summary::-webkit-details-marker{ display:none; }
.filter-pop-body{
  position:absolute; top:calc(100% + 8px); left:0; z-index:20;
  width:260px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius); box-shadow:var(--shadow-lg); padding:var(--sp-3);
  display:flex; flex-direction:column; gap:var(--sp-3);
}
.filter-pop-body label{ display:flex; flex-direction:column; gap:4px; font-size:12px; font-weight:600; color:var(--text-muted); }
.filter-pop-actions{ display:flex; gap:var(--sp-2); margin-top:2px; }

select, .field-input{
  height:34px; border-radius:var(--radius-sm); border:1px solid var(--border-strong);
  background:var(--surface); font-size:13px; color:var(--text); padding:0 var(--sp-2);
  outline:none;
}
select:focus, .field-input:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-ring); }

.sort-select{ min-width:150px; }

.bell-btn{
  width:36px; height:36px; border-radius:var(--radius-sm); border:1px solid var(--border);
  background:var(--surface); color:var(--text-muted); display:flex; align-items:center; justify-content:center;
  flex:none; cursor:not-allowed; opacity:.6;
}

/* chips row */
.chip-row{
  display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap;
  padding:var(--sp-3) var(--sp-5); border-bottom:1px solid var(--border); background:var(--surface);
}
.chip{
  display:inline-flex; align-items:center; gap:6px;
  height:28px; padding:0 var(--sp-3); border-radius:99px; font-size:12.5px; font-weight:600;
  background:var(--grey-bg); color:var(--text-muted); border:1px solid transparent;
}
.chip:hover{ filter:brightness(.97); }
.chip .n{ font-weight:700; opacity:.75; }
.chip.active{ background:var(--accent-light); color:var(--accent-hover); border-color:var(--accent-ring); }
.chip.tone-red{ background:var(--red-bg); color:var(--red); }
.chip.tone-amber{ background:var(--amber-bg); color:var(--amber); }
.chip.tone-blue{ background:var(--blue-bg); color:var(--blue); }
.chip.stub{ opacity:.55; cursor:not-allowed; }
.chip-clear{ margin-left:auto; font-size:12px; font-weight:600; color:var(--text-faint); }
.chip-clear:hover{ color:var(--red); }

/* ---------------- Table ---------------- */
.table-wrap{ flex:1; overflow:auto; padding:0 var(--sp-5); }
.tix-table{ width:100%; border-collapse:collapse; font-size:13px; }
.tix-table thead th{
  position:sticky; top:0; background:var(--bg);
  text-align:left; font-size:11px; font-weight:700; letter-spacing:.03em; text-transform:uppercase;
  color:var(--text-faint); padding:var(--sp-3) var(--sp-2); border-bottom:1px solid var(--border);
}
.tix-table thead th a{ display:inline-flex; align-items:center; gap:4px; color:inherit; }
.tix-table thead th a:hover{ color:var(--text); }
.tix-table tbody tr{ cursor:pointer; border-bottom:1px solid var(--border); background:var(--surface); }
.tix-table tbody tr:hover{ background:var(--surface-alt); }
.tix-table tbody tr.row-sel{ background:var(--accent-light); box-shadow:inset 3px 0 0 var(--accent); }
.tix-table td{ padding:11px var(--sp-2); vertical-align:middle; }
.tix-table td.col-check{ width:34px; }
.tix-table td.col-updated,
.tix-table td.col-created{ white-space:nowrap; color:var(--text-muted); font-size:12.5px; }

/* Spalten verschieben (2026-07-29): der Griff ist der Spaltenkopf selbst.
   Sortier-Links darin bleiben klickbar — Ziehen und Klicken beißen sich
   nicht, der Browser unterscheidet das. */
.tix-table thead th[data-col]{ cursor:grab; user-select:none; }
.tix-table thead th[data-col]:active{ cursor:grabbing; }
.tix-table thead th.col-dragging{ opacity:.4; }
.tix-table thead th.col-drop-target{ box-shadow:inset 3px 0 0 var(--accent); }

.subject-cell{ min-width:220px; max-width:360px; }
/* display:block ist hier NICHT kosmetisch: <a> ist inline, und auf Inline-Elementen
   greifen overflow/text-overflow überhaupt nicht — der lange Betreff lief deshalb aus
   der Zelle heraus und überlagerte die Kundenspalte (Roman-Bugreport 2026-07-29,
   Screenshot: "#11533055…653" quer über "bodysy_dts4795ph"). .subject-sub war nie
   betroffen, weil das ein <div> ist. */
.subject-title{ display:block; font-weight:600; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.subject-sub{ color:var(--text-faint); font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; margin-top:2px; }

.cust-cell{ display:flex; align-items:center; gap:8px; min-width:170px; }
.cust-name{ font-weight:600; color:var(--text); font-size:12.8px; }
.cust-email{ color:var(--text-faint); font-size:11.5px; }
.cart-badge{
  margin-left:4px; font-size:10.5px; font-weight:700; color:var(--accent-hover);
  background:var(--accent-light); border-radius:99px; padding:1px 6px; white-space:nowrap;
}

.pill{
  display:inline-flex; align-items:center; gap:5px; height:22px; padding:0 9px;
  border-radius:99px; font-size:11.5px; font-weight:700; white-space:nowrap; border:1px solid transparent;
}
.pill-dot{ width:6px; height:6px; border-radius:50%; background:currentColor; flex:none; }
.pill-green{ background:var(--green-bg); color:var(--green); }
.pill-grey{ background:var(--grey-bg); color:var(--text-muted); }
.pill-blue{ background:var(--blue-bg); color:var(--blue); }
.pill-red{ background:var(--red-bg); color:var(--red); }
.pill-amber{ background:var(--amber-bg); color:var(--amber); }
.pill-violet{ background:var(--violet-bg); color:var(--violet); }
.pill-muted{ background:var(--grey-bg); color:var(--text-faint); font-weight:600; }
.pill .pct{ opacity:.65; font-weight:600; }

.assignee-cell{ display:flex; align-items:center; gap:7px; color:var(--text-muted); font-size:12.5px; }
.assignee-none{ color:var(--text-faint); }

.empty-row td{ text-align:center; color:var(--text-faint); padding:var(--sp-8) var(--sp-3); }

/* pagination */
.pager{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-3);
  padding:var(--sp-3) var(--sp-5); border-top:1px solid var(--border); background:var(--surface);
  font-size:12.5px; color:var(--text-muted);
}
.pager-pages{ display:flex; align-items:center; gap:4px; }
.pager-pages a, .pager-pages span{
  display:flex; align-items:center; justify-content:center; min-width:28px; height:28px;
  border-radius:7px; font-weight:600; color:var(--text-muted);
}
.pager-pages a:hover{ background:var(--surface-alt); }
.pager-pages .cur{ background:var(--accent); color:#fff; }
.pager-pages .disabled{ opacity:.35; pointer-events:none; }

/* ---------------- Kompakt-Modus der Liste (2026-07-27, Punkt 4) ----------------
   Bei offenem Ticket wird die Tabelle schmal (--list-w) — Spalten Checkbox +
   Bearbeiter raus, Untertitel/E-Mail/Avatar raus: nur noch Thema + Kunde +
   Status/Intent-Punkt + Zeit passen in die Zeile ("тема+клиент+интент-точка"). */
/* Fix 2026-07-28 (Drag-Bug, s. Resizer-Kommentar unten): im ticket-open/Kompakt-
   Modus wie sidebar/conv-region/col-resizer auf position:sticky + height:100vh
   gepinnt statt frei zu wachsen — verhindert, dass eine lange Ticketliste die
   ganze Grid-Row (und damit den Resizer/Button) über den Viewport hinaus zieht.
   List-only-Modus (kein Ticket offen) bleibt unangetastet, wie gefordert. */
.shell.ticket-open .ticket-region{ position:sticky; top:0; height:100vh; overflow-y:auto; }
.shell.ticket-open .ticket-region .topbar{
  height:auto; flex-wrap:wrap; padding:var(--sp-3); gap:var(--sp-2);
}
.shell.ticket-open .ticket-region .search-box{ max-width:none; flex:1 1 100%; order:1; }
.shell.ticket-open .ticket-region .sort-select{ display:none; }
.shell.ticket-open .ticket-region .chip-row{ padding:var(--sp-2) var(--sp-3); }
.shell.ticket-open .ticket-region .table-wrap{ padding:0 var(--sp-3); }
.shell.ticket-open .ticket-region .pager{ padding:var(--sp-2) var(--sp-3); flex-wrap:wrap; }

.shell.ticket-open .ticket-region .tix-table{ font-size:12px; }
.shell.ticket-open .ticket-region .tix-table td, .shell.ticket-open .ticket-region .tix-table th{ padding:8px 6px; }
/* Schmale Liste: «Bearbeiter» fliegt raus, die Auswahlspalte BLEIBT — sie war
   hier bis 08.09.2026 mit ausgeblendet, und damit ging beim offenen Ticket die
   Mehrfachauswahl verloren (Roman: «когда двойное окно, уходит возможность
   выбрать сразу несколько писем»). */
.shell.ticket-open .ticket-region .tix-table th:nth-child(6),
.shell.ticket-open .ticket-region .tix-table td:nth-child(6){ display:none; }
.shell.ticket-open .ticket-region .tix-table td.col-check{ width:26px; }
.shell.ticket-open .ticket-region .subject-cell{ min-width:0; max-width:none; }
.shell.ticket-open .ticket-region .subject-sub{ display:none; }
.shell.ticket-open .ticket-region .cust-cell{ min-width:0; }
.shell.ticket-open .ticket-region .cust-cell .avatar{ display:none; }
.shell.ticket-open .ticket-region .cust-email{ display:none; }
.shell.ticket-open .ticket-region .col-updated{ font-size:11px; }
.shell.ticket-open .ticket-region .intent-cell .pill span:not(.pill-dot){ display:none; } /* nur der Punkt, kein "STORNO 82%"-Text */

/* ---------------- Resizer/Drag-Handle + Liste links⇄rechts-Umschalter ----------------
   Fix 2026-07-28 (Roman-Bugreport «нет возможности подвигать, раскладка разваливается»,
   root-caused live per playwright-Repro, s. decision support-pult/ux-v3/drag-fix):
   (1) Der Swap-Button war das EINZIGE optisch auffällige Element im 14px-Handle und
   vertikal zentriert über die GESAMTE Grid-Row-Höhe (bei langer Ticket-Liste oft weit
   größer als der Viewport) statt über den sichtbaren Viewport — Nutzer griffen beim
   "Mitte des Balkens anfassen" praktisch immer den Button statt der fast unsichtbaren
   1px-Linie, und pointerdown auf dem Button bricht den Drag-Start ABSICHTLICH ab
   (s. pult.js initResizer `closest('[data-listpos-toggle]')`) — reproduziert: Drag auf
   dem Button = 0px Wirkung, Drag 4px daneben = funktioniert einwandfrei. (2) LISTW_MAX
   war ein FIXER Wert (720px) unabhängig von der tatsächlichen Fensterbreite — auf einem
   schmaleren Fenster/Laptop konnte die Liste fast den ganzen Platz beanspruchen und
   .conv-region auf einen hauchdünnen Streifen zusammenquetschen; der dazwischenliegende
   Resizer (kaum sichtbar ohne Hover) wirkt dann wie eine leere Lücke, der schmale
   Composer wie "abgerissen" — genau das gemeldete Bild. (3) Der gespeicherte
   localStorage-Wert wurde im Pre-Paint-Script (base.html) UNGEPRÜFT übernommen, auch
   nach Fenster-Resize keine Nachjustierung. Fix: Resizer + Liste (im ticket-open/
   Kompakt-Modus) sind jetzt wie sidebar/conv-region auf position:sticky + height:100vh
   gepinnt (Button zentriert sich relativ zum Viewport, nicht zur Dokumenthöhe), Hit-
   Fläche vergrößert (::before, ~24px, unsichtbar) und eine IMMER sichtbare Grip-Leiste
   (::after, min. 4px, nicht erst bei Hover) ergänzt. LISTW_MAX ist jetzt dynamisch
   (50% Fensterbreite, s. pult.js), gespeicherte Werte werden beim Laden UND bei
   window.resize gegen den aktuellen gültigen Bereich geprüft/geklemmt. ---------------- */
.col-resizer{
  width:var(--resizer-w); cursor:col-resize; position:sticky; top:0; height:100vh;
  align-items:center; justify-content:center; background:var(--bg); touch-action:none;
  z-index:6; /* über .tix-table thead (sticky, z-index:5) — sonst frisst die Tabelle
                die vergrößerte Hit-Fläche an der Spaltengrenze */
}
/* Vergrößerte, unsichtbare Hit-Fläche — ~24px, überlappt bewusst ein paar Pixel in
   die Nachbarspalten (rein für Pointer-Events, keine Layoutänderung: die schmale
   var(--resizer-w)-Spur bleibt die einzige tatsächliche Grid-Spalte). */
.col-resizer::before{
  content:''; position:absolute; top:0; bottom:0; left:50%; width:24px;
  transform:translateX(-50%);
}
/* Immer sichtbare Grip-Leiste (nicht erst bei :hover) — "заметная ручка". */
.col-resizer::after{
  content:''; position:absolute; top:0; bottom:0; left:50%; width:4px;
  background:var(--border-strong); border-radius:2px; transform:translateX(-50%);
  transition:background-color .12s ease, width .12s ease; pointer-events:none;
}
.col-resizer:hover::after, body.resizing .col-resizer::after{ background:var(--accent); width:6px; }
.list-toggle-btn{
  width:24px; height:40px; border-radius:8px; border:1px solid var(--border-strong); background:var(--surface);
  display:flex; align-items:center; justify-content:center; color:var(--text-faint);
  box-shadow:var(--shadow-sm); position:relative; z-index:2; cursor:pointer;
}
.list-toggle-btn:hover{ color:var(--accent); border-color:var(--accent); }
body.resizing{ cursor:col-resize !important; }
body.resizing, body.resizing *{ user-select:none !important; }

/* ---------------- Conv-region (Konversation — jetzt die breite Hauptfläche) ---------------- */
.conv-region{
  background:var(--surface); border-left:1px solid var(--border);
  flex-direction:column; min-width:0; height:100vh; position:sticky; top:0; overflow:hidden;
}
.panel-empty{
  margin:auto; text-align:center; color:var(--text-faint); padding:var(--sp-6);
  display:flex; flex-direction:column; align-items:center; gap:var(--sp-3);
}
.panel-empty .icon{ width:34px; height:34px; color:var(--border-strong); }
.panel-empty-title{ font-size:13.5px; font-weight:600; color:var(--text-muted); }
.panel-empty-sub{ font-size:12.5px; max-width:220px; }

/* .panel-root Kinder (panel-scroll/composer-resizer/composer-dock) werden per
   CSS `order` umsortiert statt im DOM verschoben zu werden — s. Composer-
   Position-Block unten (2026-07-28, Roman: «ответ хочу справа, а не внизу,
   либо наоборот вверху»). html[data-composer-pos] steuert die Reihenfolge +
   flex-direction, dieselbe Technik wie beim äußeren Listen-Swap
   (html[data-listpos], s. .shell.ticket-open oben) — kein Reparenting nötig. */
.panel-root{ display:flex; flex-direction:column; height:100%; min-height:0; }
.panel-scroll{ order:1; flex:1 1 auto; min-height:0; min-width:0; overflow-y:auto; }
/* Lesbarkeit (Punkt 1): Kopf+Tabs+Konversation auf max-width 900px zentriert —
   der Composer-Dock darunter bleibt dagegen volle Breite (Punkt 3). */
.panel-inner{ max-width:900px; margin:0 auto; }
.panel-head{ padding:var(--sp-4) var(--sp-4) var(--sp-3); border-bottom:1px solid var(--border); }
.panel-head-top{ display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-2); }
.panel-number{ font-size:11.5px; font-weight:700; color:var(--accent); letter-spacing:.02em; }
.panel-close{
  width:26px; height:26px; border-radius:7px; display:flex; align-items:center; justify-content:center;
  color:var(--text-faint); border:1px solid transparent; flex:none;
}
.panel-close:hover{ background:var(--surface-alt); color:var(--text); border-color:var(--border); }
.panel-title{ font-size:18px; font-weight:700; color:var(--text); margin-top:2px; line-height:1.3; }

.panel-customer{ display:flex; align-items:center; gap:9px; margin-top:var(--sp-3); }
.panel-customer-meta{ font-size:12px; color:var(--text-faint); }
.panel-customer-name{ font-size:13px; font-weight:600; }

.badge-row{ display:flex; align-items:center; gap:6px; margin-top:var(--sp-3); flex-wrap:wrap; }

.gate-row{ display:flex; flex-wrap:wrap; gap:8px; margin-top:var(--sp-3); }
/* BUGFIX (2026-07-29, Roman: «Активируй, пожалуйста, эти кнопки» — Schließen/
   Spam SAHEN aus wie deaktiviert, obwohl beide voll funktionsfähig sind, s.
   pult.js initTicketActions data-ticket-close/data-ticket-spam). Erbe alter
   Phase-2-Platzhalter (Retoure/Refund, längst entfernt) — die "недоступно"-
   Optik (dashed border, blasser Text, not-allowed) lag auf ALLEN .btn dieser
   Zeile per Nachfahren-Selektor, auch auf den neueren eBay-Aktions-Buttons
   (.ebay-action-row lebt INNERHALB .gate-row; deren eigene .btn-Override
   weiter unten bleibt bestehen, ist nach diesem Fix nur noch redundant, nicht
   falsch). Normale, aktive Optik ist jetzt die BASIS; "недоступно" gibt es nur
   noch für ECHT deaktivierte Buttons (:disabled / [aria-disabled="true"]). */
.gate-row .btn{ flex:1 1 calc(33.3% - 6px); background:var(--surface); color:var(--text); border:1px solid var(--border-strong); cursor:pointer; }
/* Rücknahme-Knöpfe (Roman 2026-08-01: geschlossenes Ticket -> «Wieder öffnen»,
   markierter Spam -> «Kein Spam»): zurückhaltender als die Hauptaktionen —
   sie sind die Ausnahme, nicht der übliche Weg. Kein disabled-Grau: der Knopf
   TUT etwas, er tut nur das Gegenteil. */
.gate-row .btn-undo{ color:var(--text-muted); border-style:dashed; }
.gate-row .btn-undo:hover{ color:var(--text); border-style:solid; }
.gate-row .btn:hover{ background:var(--surface-alt); border-color:var(--text-faint); }
.gate-row .btn .icon{ color:var(--text); }
.gate-row .btn:disabled,
.gate-row .btn[aria-disabled="true"]{
  background:var(--surface-alt); color:var(--text-faint); border:1px dashed var(--border-strong); cursor:not-allowed;
}
.gate-row .btn:disabled:hover,
.gate-row .btn[aria-disabled="true"]:hover{ background:var(--surface-alt); border-color:var(--border-strong); }
.gate-row .btn:disabled .icon,
.gate-row .btn[aria-disabled="true"] .icon{ color:var(--text-faint); }

/* ---------------- Kundenwidget (Block 3) ---------------- */
.customer-widget{
  margin:var(--sp-3) var(--sp-4) 0; padding:var(--sp-3); border-radius:var(--radius);
  background:var(--surface-alt); border:1px solid var(--border);
}
.customer-widget-loading{ display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--text-faint); }
.customer-widget-loading .spinner{ display:inline-block; }
.customer-widget-empty{ font-size:12.5px; color:var(--text-faint); display:flex; align-items:center; gap:8px; }
.cw-head{ display:flex; align-items:center; gap:9px; }
.cw-name{ font-size:13.5px; font-weight:700; color:var(--text); }
.cw-email{ font-size:11.5px; color:var(--text-faint); }
/* Персональное обращение (2026-07-28) — откуда взято, для прозрачности оператору */
.cw-salutation{
  font-size:11.5px; color:var(--text-muted); margin-top:6px; padding-top:6px;
  border-top:1px dashed var(--border); display:flex; align-items:center; gap:5px; flex-wrap:wrap;
}
.cw-salutation-source{ color:var(--text-faint); }
.cw-stats{ display:flex; flex-wrap:wrap; gap:6px; margin-top:var(--sp-2); }
.cw-stat{
  display:inline-flex; align-items:center; gap:5px; font-size:12px; font-weight:600; color:var(--text-muted);
  background:var(--surface); border:1px solid var(--border); border-radius:99px; padding:3px 10px;
}
.cw-stat .icon{ width:13px; height:13px; color:var(--text-faint); }
.cw-stat.cw-returns{ color:var(--amber); }
.cw-orders-list{ margin-top:var(--sp-2); display:flex; flex-direction:column; gap:6px; }
.cw-order-row{
  display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:12px;
  padding:6px 8px; border-radius:7px; background:var(--surface); border:1px solid var(--border);
  flex-wrap:wrap;
}
.cw-order-num{ font-weight:700; font-family:var(--font-mono); }
/* ---------------- Reiter «Anhänge» (2026-07-29) ----------------
   Bilder mit Vorschau, alles andere als Zeile. Die Vorschau ist der Punkt:
   bei einem Reklamationsfoto will der Operator sofort sehen, worum es geht,
   ohne erst herunterzuladen. Auslöser: Ticket #18134, ein 71-KB-PDF lag im
   Ticket und war nirgends sichtbar. */
.files-box{ display:flex; flex-direction:column; gap:8px; padding:var(--sp-3) 0; }
.file-row{
  display:flex; align-items:center; gap:10px; text-decoration:none; color:var(--text);
  border:1px solid var(--border); border-radius:var(--radius-sm);
  padding:8px 10px; background:var(--surface);
}
.file-row:hover{ border-color:var(--accent); background:var(--surface-alt); }
.file-row.sm{ padding:5px 8px; font-size:12px; }
.file-thumb{
  width:56px; height:56px; object-fit:cover; border-radius:4px; flex-shrink:0;
  background:var(--surface-alt);
}
.file-icon{ font-size:22px; width:34px; text-align:center; flex-shrink:0; }
.file-meta{ display:flex; flex-direction:column; min-width:0; }
.file-meta b{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.file-sub{ font-size:11.5px; color:var(--text-muted); }
.file-wrappers{ margin-top:10px; padding-top:8px; border-top:1px dashed var(--border); }
.file-wrappers-hd{ font-size:11.5px; color:var(--text-faint); margin-bottom:5px; }
.tab-count{
  margin-left:5px; font-size:10.5px; font-weight:700; padding:1px 6px;
  border-radius:99px; background:var(--accent-light); color:var(--accent-hover);
}

/* ---------------- Weiche Kollisionssperre (2026-07-29) ----------------
   Optik zum readOnly/disabled aus pult.js applyCollisionLock. Die Sperre ist
   fachlich hart (Tastatur kommt nicht durch), optisch aber absichtlich weich:
   der Entwurf des Kollegen bleibt LESBAR — man will ja sehen, was er schreibt,
   bevor man ihn anspricht. */
.collision-bar{
  display:flex; align-items:flex-start; gap:10px;
  background:var(--amber-bg, #fffbeb); border:1px solid var(--amber, #fcd34d);
  border-radius:var(--radius-sm); padding:9px 11px; margin-bottom:8px;
}
.collision-icon{ font-size:15px; line-height:1.2; }
.collision-text{ flex:1; font-size:12.5px; line-height:1.45; }
.collision-hint{ display:block; color:var(--text-muted); font-size:11.5px; }
.collision-bar .btn{ flex-shrink:0; }
.reply-box.reply-locked{ opacity:.62; }
.reply-box.reply-locked textarea{ background:var(--surface-alt); cursor:not-allowed; }

/* ---------------- Seite «Ausgang» (2026-07-29) ----------------
   Bewusst nur ein paar Ergänzungen — Tabelle/Pills kommen unverändert von
   der Ticketliste, damit die Seite nicht wie ein Fremdkörper aussieht. */
.ob-head{ padding:var(--sp-4) 0 var(--sp-3); }
.ob-title{ font-size:18px; font-weight:700; margin:0 0 2px; }
.ob-sub{ font-size:12.5px; color:var(--text-muted); }
.ob-tid{ font-family:var(--font-mono); font-weight:700; color:var(--accent); }
.ob-tid:hover{ text-decoration:underline; }
.ob-err{ font-size:11.5px; color:var(--red); margin-top:3px; max-width:320px; }
/* Bereits geklaerter Fall: kein Grund, ihn weiter rot anzuschreien. */
.ob-err-done{ color:var(--text-muted); }
.ob-err-note{ font-size:11.5px; color:var(--green); margin-top:2px; max-width:320px; }
.ob-err-more{ margin-top:2px; max-width:320px; }
.ob-err-more summary{ font-size:11px; color:var(--text-muted); cursor:pointer; }
.ob-err-more summary:hover{ color:var(--text); }
/* Roh-Antwort der Plattform: JSON bricht nicht um und sprengt sonst die Spalte. */
.ob-err-raw{
  font-family:var(--font-mono); font-size:10.5px; color:var(--text-muted);
  margin-top:3px; max-height:140px; overflow:auto; white-space:pre-wrap;
  word-break:break-all; background:var(--bg); padding:6px 8px;
  border-radius:var(--radius-sm);
}

/* Marktplatz-Bestellnummer — die Nummer, die der KUNDE nennt. Optisch als
   eigener Chip, damit sie sich nicht mit unserer JTL-Nummer daneben mischt. */
.cw-order-ext{
  font-family:var(--font-mono); font-size:11px; font-weight:600;
  color:var(--text-muted); background:var(--surface-alt);
  border:1px solid var(--border); border-radius:5px; padding:1px 6px; white-space:nowrap;
}
.cw-order-track{ flex-basis:100%; font-size:11.5px; color:var(--text-faint); }
.cw-order-track a{ font-weight:600; font-family:var(--font-mono); }
.cw-order-row a{ font-weight:700; color:var(--accent); font-family:var(--font-mono); }
.cw-order-row a:hover{ text-decoration:underline; }
.cw-order-meta{ color:var(--text-faint); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cw-order-status{ font-size:10.5px; font-weight:700; text-transform:uppercase; padding:1px 7px; border-radius:99px; }
.cw-order-status.st-versandt{ background:var(--green-bg); color:var(--green); }
.cw-order-status.st-offen{ background:var(--blue-bg); color:var(--blue); }
.cw-order-status.st-storniert{ background:var(--red-bg); color:var(--red); }

.rewrite-box{ display:none; flex-direction:column; gap:8px; }
/* SICHERHEITS-FIX (2026-07-29, Roman-Screenshot): eigene umrandete Karte statt
   loser Buttons — macht die Umschreiben-Zone optisch als eigenen Block sichtbar,
   klar getrennt von .reply-toolbar/"Senden" darunter (s. Template-Kommentar
   bei .rewrite-box). Der Submit-Button selbst ist jetzt btn-outline + flex-start
   (links, unter dem Textfeld) statt btn-primary + flex-end (rechts, direkt über
   Senden) — Details im Template. */
.rewrite-box.open{
  display:flex; padding:var(--sp-2) var(--sp-3); margin-bottom:2px;
  border:1px dashed var(--border-strong); border-radius:var(--radius-sm); background:var(--surface-alt);
}
.rewrite-box textarea{ resize:vertical; }
.rewrite-mode-hint{ font-size:11.5px; color:var(--text-faint); margin-bottom:2px; }

textarea{
  width:100%; border-radius:var(--radius-sm); border:1px solid var(--border-strong);
  font-family:inherit; font-size:13px; padding:var(--sp-2) var(--sp-3); color:var(--text); outline:none;
}
textarea:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-ring); }

.status-line{ display:flex; align-items:center; gap:8px; font-size:12px; color:var(--text-faint); min-height:0; }
/* Leere Statuszeile kostet keinen Platz mehr (Roman 2026-07-31: «уменьши это
   расстояние» — zwischen Trennleiste und den Reitern «Antwort/Interne Notiz»
   klafften 42px: Resizer 10 + Dock-Polster 8 + reservierte Statuszeile 16 +
   Flex-Gap 8). display:none statt min-height:0, sonst bliebe der Gap des
   Flex-Containers stehen. Sobald setStatusLine() Text setzt oder der Spinner
   läuft, greift die Regel nicht mehr — die Zeile erscheint wie gehabt.
   Ohne :has()-Unterstützung bleibt schlicht das alte Verhalten. */
.status-line:not(:has(.spinner.on)):not(:has(.status-text:not(:empty))){ display:none; }
.spinner{
  width:13px; height:13px; border-radius:50%; border:2px solid var(--border-strong); border-top-color:var(--accent);
  animation:spin .7s linear infinite; display:none;
}
.spinner.on{ display:inline-block; }
@keyframes spin{ to{ transform:rotate(360deg); } }

/* tabs */
.tabbar{ display:flex; gap:var(--sp-1); padding:0 var(--sp-4); border-bottom:1px solid var(--border); }
.tab-btn{
  border:none; background:none; padding:10px 6px; font-size:12.8px; font-weight:600; color:var(--text-faint);
  cursor:pointer; border-bottom:2px solid transparent; margin-right:var(--sp-4);
}
.tab-btn:hover{ color:var(--text); }
.tab-btn.active{ color:var(--accent); border-bottom-color:var(--accent); }
.tab-panels{ flex:1; }
.tab-panel{ display:none; padding:var(--sp-4); }
.tab-panel.active{ display:block; }

/* conversation */
.msg{ border-radius:var(--radius); border:1px solid var(--border); background:var(--surface); padding:var(--sp-3); margin-bottom:var(--sp-3); }
.msg.note{ background:var(--accent-light); border-color:var(--accent-ring); }
.msg.agent{ background:var(--surface-alt); }
.msg-head{ display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.msg-from{ font-size:12.5px; font-weight:700; color:var(--text); }
.msg-time{ font-size:11px; color:var(--text-faint); margin-left:auto; white-space:nowrap; }
.msg-note-chip{
  font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.03em;
  background:var(--accent); color:#fff; border-radius:99px; padding:1px 8px;
}
.msg-body{ font-size:12.8px; color:var(--text); white-space:pre-wrap; word-break:break-word; }
.msg-subject{ font-size:11.5px; color:var(--text-faint); font-style:italic; margin-bottom:4px; }
/* Kopf «Variante 2»: Operator + An-Zeile + Zustellstatus (Kontaktform #18542) */
.msg-from-org{ font-size:11.5px; color:var(--text-faint); }
.msg-to{ font-size:11.5px; color:var(--text-faint); margin-bottom:4px; }
.msg-to.self{ color:var(--bad, #c62828); font-weight:600; }
.msg-delivery{ font-size:11px; font-weight:600; margin-left:6px; }
.msg-delivery.ok{ color:var(--good, #1a7f37); }
.msg-delivery.fail{ color:var(--bad, #c62828); }

/* Bestellung tab */
.order-card{ border:1px solid var(--border); border-radius:var(--radius); padding:var(--sp-3); margin-bottom:var(--sp-3); background:var(--surface-alt); }
.order-num{ font-family:var(--font-mono); font-size:12.5px; font-weight:700; color:var(--accent); }
.order-row{ display:flex; justify-content:space-between; gap:8px; font-size:12.5px; color:var(--text-muted); margin-top:6px; }
.order-link{ display:inline-flex; align-items:center; gap:4px; margin-top:8px; font-size:12.5px; font-weight:600; color:var(--accent); }
.order-link:hover{ text-decoration:underline; }
.muted-note{ color:var(--text-faint); font-size:12.5px; }

/* Automatik tab — timeline */
.timeline{ position:relative; padding-left:20px; }
.timeline::before{ content:''; position:absolute; left:5px; top:4px; bottom:4px; width:2px; background:var(--border); }
.timeline-item{ position:relative; padding-bottom:var(--sp-4); }
.timeline-item::before{
  content:''; position:absolute; left:-20px; top:3px; width:10px; height:10px; border-radius:50%;
  background:var(--accent); border:2px solid var(--surface); box-shadow:0 0 0 1px var(--accent);
}
.timeline-time{ font-size:11px; color:var(--text-faint); }
.timeline-title{ font-size:12.8px; font-weight:600; color:var(--text); margin-top:2px; }
.timeline-body{ font-size:12.3px; color:var(--text-muted); margin-top:2px; }

/* Details tab */
.kv-list{ display:flex; flex-direction:column; gap:0; }
.kv-row{ display:flex; justify-content:space-between; gap:var(--sp-2); padding:9px 0; border-bottom:1px solid var(--border); font-size:12.8px; }
.kv-row:last-child{ border-bottom:none; }
.kv-key{ color:var(--text-faint); }
.kv-val{ color:var(--text); font-weight:600; text-align:right; }

/* ---------------- Composer-Resizer + Position (2026-07-28, Roman: «границу
   между перепиской и композером двигать нельзя» + Erweiterung noch in
   derselben Session: «ответ хочу справа, а не внизу, либо наоборот вверху»).
   Drag-Leiste zwischen .panel-scroll (Konversation) und .composer-dock,
   gleiches Grundmuster wie #col-resizer (s. Fix-Kommentar weiter oben,
   decision support-pult/ux-v3/drag-fix): vergrößerte unsichtbare Hit-Fläche
   (::before, ~24px) + immer sichtbare Grip-Leiste (::after), Pointer-Capture
   + 4px-Bewegungsschwelle in pult.js initComposerResizer(). ANDERS als beim
   ursprünglichen Punkt-1-Fix jetzt DOCH ein Button im Handle (Positions-
   Umschalter #composer-pos-toggle, Cycle bottom→right→top→bottom) — darum
   der downOnButton-Sonderfall wieder wie beim äußeren #col-resizer nötig
   (s. pult.js: downOnButton wird bei pointerdown gemerkt, NICHT erst in
   endDrag aus ev.target gelesen, weil setPointerCapture() alle folgenden
   Events auf den Resizer umbiegt).

   3 Positionen über html[data-composer-pos="bottom|right|top"] (kein
   Attribut = bottom, Default — gleiche Konvention wie data-listpos):
   - bottom (Default): .panel-root bleibt flex-direction:column, Reihenfolge
     scroll→resizer→dock unverändert. Gezogen wird die .draft-textarea-Höhe
     direkt (Composer-Dock ist flex:none/Inhalt-Höhe und wächst automatisch
     mit) — das ist die einzige Position, in der pro Tastenanschlag auto-
     gewachsen wird (autoGrowTextarea in pult.js), darum bleibt hier die
     Textarea-Direkttechnik statt den Dock selbst zu sizen.
   - top: gleiche Spalten-Logik, nur Reihenfolge umgedreht (Dock zuerst) —
     Ziehen nach UNTEN vergrößert jetzt den Composer (umgekehrtes Vorzeichen
     ggü. bottom, s. pult.js).
   - right: .panel-root wird flex-direction:row, Composer-Dock bekommt eine
     explizite BREITE (var(--composer-w), 320px..60% Fensterbreite) statt
     Höhe — die Höhe kommt automatisch aus dem Row-Flex-Stretch (kein Auto-
     Grow-beim-Tippen nötig, darum .reply-box/.draft-textarea hier flex:1
     und in .composer-dock genug Rest-Höhe vorhanden, um zu greifen). Diese
     Composer-Breite ist eine GETRENNTE Grid-Ebene vom äußeren #col-resizer
     (--list-w, Liste links/rechts) — beide Resizer dürfen gleichzeitig
     "rechts" stehen (Liste UND Composer rechts), ohne sich zu stören,
     s. Playwright-Kombinationstest. */
.composer-resizer{
  order:2; /* Bugfix 2026-07-28 (Roman-Report: Ручка+Button "оторвались" und
    schwebten oben über dem Ticket-Titel): OHNE explizites order landet die
    Leiste beim initialen CSS-Wert order:0 — VOR .panel-scroll (order:1),
    weil nur die top/right-Overrides unten je order:2 gesetzt hatten, die
    Basisregel (= Position bottom, der Default OHNE html[data-composer-pos]-
    Attribut) aber nicht. Damit rutschte die Ручка im Standardfall an den
    Anfang von .panel-root (ganz oben), komplett getrennt vom Composer-Dock
    (order:3) unten — genau das gemeldete Bild. Jetzt Basis-order:2 (Scroll→
    Resizer→Dock), die top/right-Overrides bleiben als redundante, aber
    harmlose explizite Bestätigung stehen. */
  flex:none; height:var(--resizer-h); cursor:row-resize; position:relative;
  display:flex; align-items:center; justify-content:center;
  background:var(--surface); touch-action:none; z-index:4;
}
.composer-resizer::before{
  content:''; position:absolute; left:0; right:0; top:50%; height:24px;
  transform:translateY(-50%);
}
.composer-resizer::after{
  content:''; position:absolute; left:0; right:0; top:50%; height:4px;
  background:var(--border-strong); border-radius:2px; transform:translateY(-50%);
  transition:background-color .12s ease, height .12s ease; pointer-events:none;
}
.composer-resizer:hover::after, body.resizing-composer .composer-resizer::after{
  background:var(--accent); height:6px;
}
body.resizing-composer{ cursor:row-resize !important; }
body.resizing-composer, body.resizing-composer *{ user-select:none !important; }
#composer-pos-toggle{ width:34px; height:20px; font-size:11px; }

html[data-composer-pos="top"] .panel-scroll{ order:3; }
html[data-composer-pos="top"] .composer-resizer{ order:2; }
html[data-composer-pos="top"] .composer-dock{ order:1; border-top:none; border-bottom:1px solid var(--border); }

html[data-composer-pos="right"] .panel-root{ flex-direction:row; }
html[data-composer-pos="right"] .panel-scroll{ order:1; }
html[data-composer-pos="right"] .composer-resizer{ order:2; }
html[data-composer-pos="right"] .composer-dock{ order:3; }
html[data-composer-pos="right"] .composer-resizer{
  height:auto; align-self:stretch; width:var(--resizer-w); cursor:col-resize;
}
html[data-composer-pos="right"] .composer-resizer::before{
  left:50%; right:auto; top:0; bottom:0; width:24px; height:auto; transform:translateX(-50%);
}
html[data-composer-pos="right"] .composer-resizer::after{
  left:50%; right:auto; top:0; bottom:0; width:4px; height:auto; transform:translateX(-50%);
}
html[data-composer-pos="right"] .composer-resizer:hover::after,
html[data-composer-pos="right"] body.resizing-composer .composer-resizer::after{
  width:6px; height:auto;
}
html[data-composer-pos="right"] body.resizing-composer{ cursor:col-resize !important; }
html[data-composer-pos="right"] #composer-pos-toggle{ width:20px; height:34px; }

/* ---------------- Composer-Dock (Punkt 3, 2026-07-27) ----------------
   Immer sichtbar (unten/oben/rechts je nach Position), volle Breite der
   Konversation im bottom/top-Fall (NICHT auf 900px begrenzt — Roman will
   Platz zum Tippen). Bot-Aktionen EINE Zeile über der Antwort-Textarea
   (vorher: 2-Spalten-Grid im Kopf, gequetscht).
   2026-07-29 (Roman, live: «уменьши разрыв между ответом и полоской этой
   верхней серой») — padding-top/-bottom var(--sp-3)→var(--sp-2) + Kind-
   Abstand (gap) 10px→8px: weniger Leerraum zwischen der Composer-Resizer-
   Griffleiste und den Reply-Tabs/der Textarea. NUR das Innen-Padding des
   Docks — die Resizer-Ручка selbst (.composer-resizer, Höhe var(--resizer-h)
   + ::before-Hit-Fläche 24px) bleibt unverändert greifbar, s.o. Symmetrisch
   (nicht nur padding-top), damit es auch in Position "top" (Dock ÜBER dem
   Resizer, s. html[data-composer-pos="top"] unten) knapper wirkt. */
.composer-dock{
  order:3; flex:none; border-top:1px solid var(--border); background:var(--surface);
  /* oben knapper als unten (Roman 2026-07-31): über den Reitern sitzt schon
     die Resizer-Leiste, ein zweites volles Polster wirkte wie ein Loch */
  padding:var(--sp-1) var(--sp-5) var(--sp-2); display:flex; flex-direction:column; gap:8px;
  max-height:70vh; overflow-y:auto; /* Sicherheitsnetz: auch bei manuell sehr
    großer Textarea (s. pult.js COMPOSER_MAX_VH) bleibt der Dock selbst
    innerhalb der 70vh-Grenze scrollbar statt den Viewport zu sprengen. */
}
html[data-composer-pos="right"] .composer-dock{
  width:var(--composer-w, 380px); min-width:320px; max-width:60%;
  max-height:none; height:auto; overflow-y:auto;
  border-top:none; border-left:1px solid var(--border);
}
/* Roman 2026-07-28: ряд слишком крупный — уменьшить ~в 1.5x (высота/паддинги/
   шрифт/иконки/зазоры). wrap вместо overflow-x: при нехватке места ряд
   переносится, а не обрезается/скроллится.
   LAYOUT-VEREINHEITLICHUNG (2026-07-29, Roman-Screenshot-Vergleich Antwort vs.
   Interne Notiz): die frühere .bot-action-row war ein EIGENER verschachtelter
   Flex-Container — beim Umbruch klappte sie als GANZER BLOCK auf eine neue
   Zeile (Antwort-Tab zerfiel sichtbar in zwei Ebenen), während Interne Notiz
   (ohne diesen Block-Umbruch-Effekt) alles in einer Zeile zeigte. Jetzt sind
   KI-Antwort/Umschreiben/Übersetzen-Popover/Werkzeuge/Wiedervorlage direkte
   Kinder von .reply-toolbar (kein Wrapper-Div mehr) — sie brechen einzeln mit
   den kleinen Werkzeugen zusammen um, EIN gemeinsamer Umbruch-Fluss. Diese
   Größen-Regeln bleiben inhaltlich gleich, nur der Selektor ist jetzt EINE
   Ebene flacher (.reply-toolbar > statt .bot-action-row >) — :not([data-send-
   btn]) schließt den jetzt im selben Container lebenden Senden-Button aus
   (der bleibt bewusst GROSS, s. .reply-toolbar weiter unten). */
.reply-toolbar > .btn:not([data-send-btn]),
.reply-toolbar > details > summary.btn{
  height:24px; padding:0 var(--sp-2); font-size:11px; gap:4px;
}
.reply-toolbar > .btn:not([data-send-btn]) .icon,
.reply-toolbar > details > summary.btn .icon{ width:11px; height:11px; }
.reply-toolbar .field-input{ height:24px; font-size:11px; padding:0 6px; }
/* Rein optischer Trenner zwischen kleiner Werkzeug-Gruppe (😀📎Aa/Zitat/
   Entwurf) und Aktions-Gruppe (KI-Antwort/Umschreiben/…) — ein einzelnes
   Element, KEINE eigene Flex-Box mehr (das war die Ursache des Block-Umbruchs
   oben). Bricht mit um wie jedes andere Element, verschwindet einfach am
   Zeilenanfang wenn es dort optisch nichts zu trennen gäbe. */
.toolbar-divider{ width:1px; align-self:stretch; min-height:16px; background:var(--border); flex:none; }
@media (max-width: 560px){ .toolbar-divider{ display:none; } }

/* Zeichenzähler eBay-Limit (Roman-Audit 2026-07-28) — dezent unter der
   Textarea, wird erst bei Annäherung/Überschreitung auffällig (JS setzt
   .char-counter-warn/.char-counter-over, s. pult.js initCharCounter). */
.char-counter{
  align-self:flex-end; font-size:11px; color:var(--text-faint); font-variant-numeric:tabular-nums;
}
.char-counter.char-counter-warn{ color:var(--amber); font-weight:600; }
.char-counter.char-counter-over{ color:var(--red); font-weight:700; }

.reply-box{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; gap:8px; }
.reply-tabs{ display:flex; gap:var(--sp-4); }
.reply-tab{ font-size:12px; font-weight:700; color:var(--text-faint); padding-bottom:6px; border-bottom:2px solid transparent; }
.reply-tab.active{ color:var(--text); border-bottom-color:var(--accent); }
/* EIN flacher Container für ALLES (2026-07-29, s. Kommentar oben) — kleine
   Werkzeuge, Trenner, Aktions-Buttons UND jetzt auch "Senden" selbst als
   letztes Kind (margin-left:auto hält es rechts, SOLANGE Platz ist — läuft
   die Zeile über, bricht "Senden" wie jeder andere Button eine Zeile tiefer,
   KEIN erzwungener zweiter Level mehr, s. Roman: «как во Interne Notiz»).
   SICHERHEITS-FIX (2026-07-29, voriger Auftrag) bleibt erhalten: fester
   Trenner (border-top+padding-top) ÜBER dieser Zeile — die Aktionsleiste ist
   so IMMER optisch von allem darüber abgesetzt (Umschreiben-Karte, Anhänge,
   Wiedervorlage-Hinweis…), unabhängig von Composer-Position oder Umbruch. */
.reply-toolbar{
  display:flex; align-items:center; gap:6px; flex-wrap:wrap;
  border-top:1px solid var(--border); padding-top:var(--sp-2); margin-top:2px;
}
.reply-icon-btn{
  width:26px; height:26px; border-radius:7px; display:flex; align-items:center; justify-content:center;
  color:var(--text-faint); border:1px solid transparent; font-size:14px; cursor:not-allowed; opacity:.7;
}
/* "Senden"/"Notiz" — einzige primary-Aktion im Composer-Footer (Sicherheits-
   Prinzip, s. vorige Session): bleibt GROSS (normale .btn-Größe, s. :not()-
   Ausschluss oben), margin-left:auto pinnt es rechts INNERHALB des Umbruch-
   Flusses statt in einer separaten erzwungenen Zeile. */
[data-send-btn]{ margin-left:auto; flex:none; }
.reload-draft-btn{ font-size:11.5px; color:var(--text-faint); display:inline-flex; align-items:center; gap:4px; }
/* Anhänge-Status IMMER sichtbar (2026-07-29) — s. Template-Kommentar bei
   data-attach-status. Dezent (wie .reload-draft-btn), aber niemals leer. */
.attach-status{ font-size:11.5px; color:var(--text-muted); white-space:nowrap; }
.attach-status.attach-status-empty{ color:var(--text-faint); }

/* Großer Composer (Punkt 3): 14px Schrift, wächst automatisch bis ~40vh im
   bottom/top-Auto-Modus (s. pult.js autoGrowTextarea), manuelles Ziehen an
   der .composer-resizer-Ручка bleibt zusätzlich möglich (überstimmt Auto-
   Grow, s. isComposerManual in pult.js). flex:1 wirkt nur in Position
   "right" (dort hat .composer-dock echte Rest-Höhe zum Verteilen) — im
   Auto-Höhe-Fall (bottom/top) ist der Dock inhalts-hoch, also No-Op. */
.draft-textarea{ flex:1 1 auto; min-height:110px; max-height:40vh; font-size:14px; line-height:1.5; resize:vertical; }
html[data-composer-pos="right"] .draft-textarea{ max-height:none; resize:none; }
.reload-draft-btn:hover{ color:var(--accent); }

.toast{
  position:fixed; right:20px; bottom:20px; z-index:100;
  background:var(--dark); color:#fff; padding:10px 16px; border-radius:var(--radius);
  font-size:12.8px; box-shadow:var(--shadow-lg); opacity:0; transform:translateY(8px);
  transition:opacity .18s ease, transform .18s ease; pointer-events:none; max-width:320px;
  display:flex; gap:10px; align-items:flex-start;
}
.toast.show{ opacity:1; transform:translateY(0); }
/* Sperr- und Fehlermeldungen bleiben stehen, bis der Operator sie wegklickt
   (Roman 05.08: «слишком быстро уходит»). Einen Grund, den man in 3 Sekunden
   nicht zu Ende liest, verschluckt der Toast sonst — deshalb hier auch etwas
   mehr Breite als beim kurzen «Gesendet.». */
.toast.sticky{ pointer-events:auto; max-width:480px; }
.toast-msg{ flex:1 1 auto; white-space:pre-line; line-height:1.45; }
.toast-x{
  flex:0 0 auto; pointer-events:auto; cursor:pointer;
  background:none; border:0; color:#fff; opacity:.65;
  font-size:18px; line-height:1; padding:0 2px; margin:-2px -4px 0 0;
}
.toast-x:hover{ opacity:1; }

/* ============================================================
   Login page
   ============================================================ */
body.login-body{
  min-height:100vh; display:flex; align-items:center; justify-content:center;
  background:var(--bg); background-image:radial-gradient(circle at 15% 10%, var(--accent-light), transparent 45%);
}
.login-card{
  width:360px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  box-shadow:var(--shadow-lg); padding:var(--sp-6);
}
.login-brand{ display:flex; flex-direction:column; align-items:center; gap:var(--sp-3); margin-bottom:var(--sp-5); }
.login-brand .brand-mark{ width:44px; height:44px; border-radius:12px; font-size:20px; }
.login-brand h1{ font-size:16.5px; }
.login-field{ display:flex; flex-direction:column; gap:6px; margin-bottom:var(--sp-3); }
.login-field label{ font-size:12.5px; font-weight:600; color:var(--text-muted); }
.login-field input{ height:38px; border-radius:var(--radius-sm); border:1px solid var(--border-strong); padding:0 var(--sp-3); font-size:13.5px; outline:none; }
.login-field input:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-ring); }
.login-error{
  background:var(--red-bg); color:var(--red); border:1px solid var(--red-line); border-radius:var(--radius-sm);
  font-size:12.5px; padding:8px 10px; margin-bottom:var(--sp-3);
}
.login-submit{ width:100%; margin-top:var(--sp-2); height:40px; }
.login-hint{ text-align:center; font-size:11.5px; color:var(--text-faint); margin-top:var(--sp-4); }

/* ============================================================
   Wiedervorlage (2026-07-28) — natives Zammad state='pending reminder' +
   pending_time, s. helpdesk.snooze_ticket/unsnooze_ticket. Badge im Panel-Kopf
   + Popover-Formular im Composer (details/summary, gleiches Muster wie
   .filter-pop in _ticket_table.html) + Spalte "Fällig" in der Tabelle.
   ============================================================ */
.snooze-badge{ cursor:default; }
.col-due{ white-space:nowrap; color:var(--text-muted); font-size:12.5px; }
.col-due .rel-time-due{ font-variant-numeric:tabular-nums; }

.snooze-pop{ position:relative; }
.snooze-pop > summary{ list-style:none; cursor:pointer; }
.snooze-pop > summary::-webkit-details-marker{ display:none; }
.snooze-pop-body{
  position:absolute; bottom:calc(100% + 8px); left:0; z-index:20;
  width:270px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius); box-shadow:var(--shadow-lg); padding:var(--sp-3);
  display:flex; flex-direction:column; gap:var(--sp-3);
}
.snooze-quick{ display:flex; gap:6px; flex-wrap:wrap; }
.snooze-quick .btn{ flex:1 1 auto; }
.snooze-quick .btn.active{ background:var(--accent-light); border-color:var(--accent); color:var(--accent-hover); }
.snooze-field{ display:flex; flex-direction:column; gap:4px; font-size:12px; font-weight:600; color:var(--text-muted); }
.snooze-field input, .snooze-field textarea{ width:100%; }
.snooze-field textarea{ resize:vertical; font-weight:400; }
.snooze-pop-actions{ display:flex; justify-content:flex-end; }
.snooze-error{
  font-size:12px; color:var(--red); background:var(--red-bg); border:1px solid var(--red-line);
  border-radius:var(--radius-sm); padding:6px 8px;
}
/* «Kundennachricht übersetzen» — kompakte RU/Deutsch/English-Auswahl,
   selbes .snooze-pop-Popover-Muster, nur schmaler + Zeile statt Formular. */
.translate-in-pop .snooze-pop-body{ width:auto; min-width:170px; }
.translate-in-pop-body{ flex-direction:row !important; flex-wrap:wrap; }
.translate-in-pop-body .btn{ flex:1 1 auto; white-space:nowrap; }

/* «Für Kunde übersetzen» — Popover statt <select> (2026-07-29, Roman: «для
   чего это АВТО перевод? непонятно»). Erster Punkt (⚡ Automatisch) volle
   Breite/eigene Zeile + hervorgehoben (Default-Verhalten), darunter alle
   translate_ext.LANGS-Sprachen als Grid aus kleinen Pillen (12 Stück — anders
   als .translate-in-pop-body mit nur 3 braucht das mehr Platz, darum breiter
   + eigenes Grid statt einer einzelnen Zeile).
   Breite bewusst auf der EIGENEN Klasse .translate-out-pop-body gesetzt (nicht
   als Nachfahren-Selektor .translate-out-pop .snooze-pop-body wie beim älteren
   .translate-in-pop) — initPortalPopovers() hängt den Body beim Öffnen nach
   document.body um (s. Kommentar dort), ein Nachfahren-Selektor über das
   <details>-Element würde dann nicht mehr greifen. */
.translate-out-pop-body{ width:236px; max-width:280px; gap:8px; }
.translate-out-auto{ width:100%; justify-content:flex-start; }
.translate-out-auto-lang{ opacity:.7; font-weight:400; }
.translate-out-pop-langs{ display:flex; flex-wrap:wrap; gap:6px; }
.translate-out-pop-langs .btn{ flex:1 1 64px; white-space:nowrap; }

/* Popover-"Portal" (2026-07-28, Playwright-Repro): .bot-action-row hat
   overflow-x:auto ohne explizites overflow-y → per Spec effektiv overflow-y:
   auto auch (Clipping-Container). Ein normal absolut positioniertes Popover
   würde darin abgeschnitten/fehlplatziert — pult.js initPortalPopovers()
   verschiebt den Inhalt beim Öffnen nach document.body und positioniert ihn
   per position:fixed (JS-berechnete Koordinaten) — diese Klasse überschreibt
   dafür position/bottom/left aus .snooze-pop-body (Grund für !important: die
   Positionierung MUSS Vorrang vor der statischen Popover-Regel haben, das ist
   der einzige Zweck dieser Klasse). */
/* max-height/overflow: das Popover kann durch aufgeklappte Untermenüs beliebig
   hoch werden. Ohne Deckel läuft es unten aus dem Bild und die untersten
   Einträge sind nicht mehr erreichbar — mit Deckel scrollt es stattdessen
   in sich. Ergänzt die Neupositionierung in pult.js initPortalPopovers. */
.portal-pop-body{
  position:fixed !important; bottom:auto !important; z-index:200;
  max-height:calc(100vh - 24px); overflow-y:auto; overscroll-behavior:contain;
}

/* ---------------- Bot-Notizen-Kollaps (2026-07-28, Roman: «заметки бота
   слишком длинные, захламляют тред») ----------------
   Standard: eingeklappt (eine Zeile, .bot-note-preview sichtbar). Klick auf
   die Zeile öffnet .bot-note-body per max-height-Übergang (Doppel-Wrapper
   .bot-note-body/.bot-note-body-inner — klassischer Accordion-Trick, damit
   Innen-Padding während des Kollaps nicht "durchschlägt"). Individueller
   Zustand lebt nur im DOM dieser Panel-Instanz (kein localStorage) — beim
   Ticketwechsel wird das Panel komplett neu gerendert, also automatisch
   wieder zu. Globaler Umschalter (Checkbox oben im Konversations-Tab,
   .conv-toolbar) erzwingt "immer offen", persistiert in localStorage. */
.conv-toolbar{ display:flex; justify-content:flex-end; margin-bottom:var(--sp-2); }
.bot-note-global-toggle{
  display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--text-faint);
  cursor:pointer; user-select:none;
}
.bot-note-global-toggle input{ accent-color:var(--accent); cursor:pointer; }

.bot-note{ padding:0; overflow:hidden; }
.bot-note-head{
  width:100%; display:flex; align-items:center; gap:8px; text-align:left;
  background:none; border:none; cursor:pointer; padding:var(--sp-3); font:inherit;
}
.bot-note-icon{ flex:none; font-size:13px; }
.bot-note-label{ font-size:12.5px; font-weight:700; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bot-note-head .msg-time{ margin-left:auto; }
.bot-note-caret{
  flex:none; color:var(--text-faint); font-size:11px; transition:transform .15s ease;
}
.bot-note.open .bot-note-caret{ transform:rotate(90deg); }
.bot-note-preview{
  font-size:11.8px; color:var(--text-faint); padding:0 var(--sp-3) var(--sp-3);
  margin-top:-6px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.bot-note.open .bot-note-preview{ display:none; }
.bot-note-body{ max-height:0; overflow:hidden; transition:max-height .18s ease; }
.bot-note.open .bot-note-body{ max-height:1200px; transition:max-height .25s ease; }
.bot-note-body-inner{ padding:0 var(--sp-3) var(--sp-3); }
@media (prefers-reduced-motion: reduce){
  .bot-note-body, .bot-note-caret{ transition:none; }
}

/* ---------------- Inline-Übersetzung der Kundennachricht (2026-07-28,
   Roman: Team ist RU-sprachig) — Original/RU/DE/EN-Pillen unter der Nachricht,
   Auswahl ist eine PERSÖNLICHE Operator-Einstellung (localStorage
   anro_support_translate_lang), gilt global für alle Tickets. ---------------- */
.msg-translate{ margin-top:var(--sp-2); padding-top:var(--sp-2); border-top:1px dashed var(--border); }
.msg-translate-bar{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.msg-translate-icon{ font-size:12px; opacity:.7; }
.msg-translate-pills{ display:flex; gap:4px; }
.mt-pill{
  border:1px solid var(--border-strong); background:var(--surface); color:var(--text-muted);
  border-radius:99px; font-size:10.5px; font-weight:700; padding:2px 9px; cursor:pointer;
}
.mt-pill:hover{ border-color:var(--accent); color:var(--text); }
.mt-pill.active{ background:var(--accent); border-color:var(--accent); color:#fff; }
.mt-status{ font-size:11px; color:var(--text-faint); display:inline-flex; align-items:center; gap:5px; }
.mt-status .spinner{ width:11px; height:11px; }

/* ---------------- Умное предложение Wiedervorlage (2026-07-28, Brief Punkt 6) ---------------- */
.smart-hint{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  background:var(--amber-bg); border:1px solid var(--amber-line); color:var(--text);
  border-radius:var(--radius-sm); padding:8px 10px; font-size:12.5px;
}
.smart-hint-icon{ flex:none; }
.smart-hint .btn{ margin-left:auto; }
.smart-hint-dismiss{
  flex:none; width:20px; height:20px; border-radius:6px; border:none; background:none;
  color:var(--text-faint); cursor:pointer; font-size:14px; line-height:1;
}
.smart-hint-dismiss:hover{ background:rgba(0,0,0,.06); color:var(--text); }

/* ---------------- Русский подстрочник черновика (2026-07-28, Roman: «оператор
   должен понимать, ЧТО отправляет»). 2026-07-29 (Roman, live-Screenshot: «эту
   кнопочку тоже в подвал, на первое место перед смайликами») — lebt jetzt als
   <details class="snooze-pop js-portal-pop"> ganz vorn in .reply-toolbar (s.
   _ticket_panel.html), NICHT mehr als eigener Block über den Reply-Tabs.
   Wiederverwendet 1:1 die Wiedervorlage/Werkzeuge-Popover-Optik (Portal-
   Positionierung via initPortalPopovers() in pult.js — .composer-dock hat
   overflow-y:auto, ein normales position:absolute-Popover würde hier
   abgeschnitten). .draft-gloss-toggle bleibt kompakt wie die Nachbar-Tools
   (Entwurf-neu-laden/-speichern) — nicht größer. ---------------- */
.draft-gloss{ font-size:12px; }
.draft-gloss-toggle{
  display:flex; align-items:center; gap:6px; background:none; border:none; cursor:pointer;
  font:inherit; font-size:12px; font-weight:600; color:var(--text-muted); padding:2px 0;
}
.draft-gloss-toggle:hover{ color:var(--text); }
.draft-gloss-lang{
  font-size:10px; font-weight:700; color:var(--accent); background:var(--accent-light);
  border-radius:99px; padding:1px 7px;
}
.draft-gloss-toggle .caret{ transition:transform .15s ease; color:var(--text-faint); font-size:10px; }
.draft-gloss[open] .draft-gloss-toggle .caret{ transform:rotate(90deg); }
/* .snooze-pop-body liefert bereits Hintergrund/Rahmen/Schatten/Padding/Gap
   (position via initPortalPopovers, s.o.) — hier nur die Breite, etwas
   großzügiger als das 270px-Default (Übersetzungstext kann mehrzeilig sein). */
.draft-gloss-body{ width:320px; max-width:calc(100vw - 24px); }
.draft-gloss-status{ font-size:11.5px; color:var(--text-faint); display:inline-flex; align-items:center; gap:6px; }
.draft-gloss-text{ font-size:13px; color:var(--text); white-space:pre-wrap; word-break:break-word; margin-top:4px; }
@media (prefers-reduced-motion: reduce){
  .draft-gloss-toggle .caret{ transition:none; }
}

/* ---------------- UI-Sprache RU/DE/EN (2026-07-28) ---------------- */
.accent-switch.lang-switch button{ width:auto; min-width:26px; padding:0 6px; font-size:10.5px; font-weight:700; }

/* Defensive Fix (2026-07-28, Roman-Report «подсказка налезает»): [hidden] hat
   dieselbe Spezifität wie eine Klasse — ein Autoren-Regelsatz mit display:flex/
   block auf DEMSELBEN Element kann die UA-Regel [hidden]{display:none} im
   Cascade-Tie überstimmen (Quellreihenfolge entscheidet). Für jedes Composer-
   Element, das per .hidden-Property ein-/ausgeblendet wird, [hidden] explizit
   erzwingen — sonst bleibt es unsichtbar-aber-raumgreifend oder blitzt kurz auf. */
.smart-hint[hidden], .attach-chips[hidden],
.emoji-pop[hidden], .fontsize-pop[hidden], .send-modal-overlay[hidden],
.note-textarea[hidden], .draft-conflict-banner[hidden], .draft-attach-chips[hidden]{
  display:none !important;
}

/* ============================================================
   ОТПРАВКА клиенту (2026-07-28, Roman im Chat bestätigt: «Включаем отправку?
   — ДА») — reply-tabs jetzt echte Buttons, Interne-Notiz-Modus, Anhänge-Chips,
   Emoji-/Schriftgrößen-Popover, Zitat-Toggle, Bestätigungs-Modal.
   ============================================================ */
.reply-tab{
  background:none; border:none; cursor:pointer; font:inherit;
  font-size:12px; font-weight:700; color:var(--text-faint); padding-bottom:6px;
  border-bottom:2px solid transparent;
}
.reply-tab.active{ color:var(--text); border-bottom-color:var(--accent); }
.reply-tab:hover:not(.active){ color:var(--text-muted); }

/* Interne-Notiz-Modus (BUG 2, 2026-07-28): gelber Rahmen/Hintergrund wie bei
   internen Notizen im Thread (.msg.note oben) — Operator soll nie versehentlich
   glauben, eine Notiz ginge an den Kunden. */
.composer-dock.note-mode{
  background:var(--amber-bg); border-top-color:var(--amber-line);
  border-radius:var(--radius); box-shadow:inset 0 0 0 1px var(--amber-line);
}
.note-textarea{
  flex:1 1 auto; min-height:110px; max-height:40vh; font-size:14px; line-height:1.5;
  resize:vertical; background:var(--surface);
}

.attach-chips, .draft-attach-chips{ display:flex; flex-wrap:wrap; gap:6px; }
.attach-chip{
  display:inline-flex; align-items:center; gap:6px; background:var(--surface-alt);
  border:1px solid var(--border-strong); border-radius:99px; padding:4px 6px 4px 10px;
  font-size:11.5px; color:var(--text); max-width:260px;
}
/* Bot-Anhänge des Shared Drafts (2026-07-28) — leicht abgesetzt (Akzent-Rahmen),
   damit klar ist: das ist NICHT die eigene Auswahl des Operators, sondern was
   der Bot (z.B. «Счёт») schon an den Entwurf gehängt hat. */
.attach-chip-bot{ border-color:var(--accent-ring); background:var(--accent-light); }
.attach-chip-origin{ flex:none; font-size:11px; }
.attach-chip-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:inherit; text-decoration:none; }
/* 2026-07-29 (Roman-Screenshot «я вложил, хочу нажать и увидеть») — Dateiname
   klickbar (Vorschau in neuem Tab): eigener Look (Akzentfarbe+Underline-on-
   hover+pointer), ersetzt den vorherigen separaten ⬇-Button. Gilt für BEIDE
   Varianten: <a> (Bot-Anhänge, Server-Route) UND <button> (frisch ausgewählte,
   noch nicht hochgeladene Dateien, s. pult.js attach-chip-name-btn). */
.attach-chip-link{ cursor:pointer; color:var(--accent); }
.attach-chip-link:hover{ text-decoration:underline; }
.attach-chip-name-btn{ background:none; border:none; padding:0; margin:0; font:inherit; text-align:left; }
.attach-chip-size{ color:var(--text-faint); flex:none; }
.attach-chip-remove{
  flex:none; width:16px; height:16px; border-radius:50%; border:none; background:none;
  color:var(--text-faint); cursor:pointer; font-size:12px; line-height:1; display:flex;
  align-items:center; justify-content:center;
}
.attach-chip-remove:hover{ background:rgba(0,0,0,.08); color:var(--red); }
.attach-error{ font-size:11.5px; color:var(--red); }

.reply-icon-btn{ cursor:pointer; opacity:1; }
.reply-icon-btn:hover{ background:var(--surface-alt); color:var(--accent); border-color:var(--border); }
.reply-icon-btn:disabled{ cursor:not-allowed; opacity:.5; }
.emoji-pop-wrap, .fontsize-pop-wrap{ position:relative; }
.emoji-pop{
  position:absolute; bottom:calc(100% + 6px); left:0; z-index:30; width:236px;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  box-shadow:var(--shadow-lg); padding:8px; display:grid;
  grid-template-columns:repeat(8, 1fr); gap:2px;
}
.emoji-pop button{
  border:none; background:none; cursor:pointer; font-size:17px; line-height:1;
  border-radius:6px; padding:4px 0;
}
.emoji-pop button:hover{ background:var(--surface-alt); }
.fontsize-pop{
  position:absolute; bottom:calc(100% + 6px); left:0; z-index:30;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  box-shadow:var(--shadow-lg); padding:4px; display:flex; gap:2px;
}
.fontsize-pop button{
  border:1px solid transparent; background:none; cursor:pointer; font-size:12px; font-weight:700;
  border-radius:6px; padding:5px 9px; color:var(--text-muted);
}
.fontsize-pop button:hover{ background:var(--surface-alt); }
.fontsize-pop button.active{ background:var(--accent-light); color:var(--accent-hover); border-color:var(--accent-ring); }
.draft-textarea.fs-s, .note-textarea.fs-s{ font-size:12px; }
.draft-textarea.fs-m, .note-textarea.fs-m{ font-size:14px; }
.draft-textarea.fs-l, .note-textarea.fs-l{ font-size:17px; }

.quote-toggle{
  display:flex; align-items:center; gap:5px; font-size:11.5px; color:var(--text-faint);
  cursor:pointer; user-select:none; margin-left:2px;
}
.quote-toggle input{ accent-color:var(--accent); cursor:pointer; }

/* ---------------- Autosave-Indikator (2026-07-28, Roman: «пишу, забылся, и
   оно не сохранилось») ---------------- */
.autosave-status{ font-size:11px; color:var(--text-faint); margin-left:2px; white-space:nowrap; }
.autosave-status.busy{ color:var(--text-faint); }
.autosave-status.ok{ color:var(--green); }
.autosave-status.warn{ color:var(--amber); }
.autosave-status.error{ color:var(--red); }

/* ---------------- Unausgefüllter {Platzhalter} im Entwurf (2026-08-13) ----------------
   Rot bewusst erlaubt: Rot ist dem echten Fehlschlag vorbehalten (s. outbound-
   Kommentar unten) — ein {Bestellnummer}-Token, das so an den Kunden ginge,
   IST ein echter Fehlschlag. Bauform wie .draft-conflict-banner. */
.draft-placeholder-warn{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  background:var(--red-bg); border:1px solid var(--red-line); color:var(--text);
  border-radius:var(--radius-sm); padding:8px 10px; font-size:12.5px;
}
.draft-placeholder-warn[hidden]{ display:none; }
.draft-placeholder-warn b{ font-family:var(--mono, monospace); }

/* ---------------- Draft-Konflikt-Banner (Kollisionsschutz Punkt 2) ---------------- */
.draft-conflict-banner{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  background:var(--amber-bg); border:1px solid var(--amber-line); color:var(--text);
  border-radius:var(--radius-sm); padding:8px 10px; font-size:12.5px;
}
.draft-conflict-icon{ flex:none; }
.draft-conflict-actions{ display:flex; gap:6px; margin-left:auto; flex-wrap:wrap; }

/* ---------------- Verzögerter Versand / Abbruchfenster (2026-07-29, Roman:
   «таймер на 5 минут») — dieselbe Bauform wie .draft-conflict-banner /
   .smart-hint (flex-Zeile, Icon links, Aktion rechts über margin-left:auto),
   nur in Blau statt Amber: Amber heißt in diesem Composer bereits «Achtung,
   schau nochmal hin», hier ist aber nichts falsch — es läuft nur ein Timer.
   Rot ist ausschließlich dem echten Fehlschlag vorbehalten. ---------------- */
.outbound-banner{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  background:var(--blue-bg); border:1px solid var(--blue-line); color:var(--text);
  border-radius:var(--radius-sm); padding:8px 10px; font-size:12.5px;
}
.outbound-banner .btn, .outbound-dismiss{ margin-left:auto; }
/* Versand steckt fest (Audit-Punkt 5): rot statt blau — «wird gesendet»
   in Blau hat den Operator warten lassen, obwohl nichts mehr passierte. */
.outbound-banner.outbound-stuck{ background:var(--red-bg); border-color:var(--red-line); }
.outbound-icon{ flex:none; }
.outbound-text{ font-weight:600; }
.outbound-countdown{ font-variant-numeric:tabular-nums; }
.outbound-banner.outbound-failed{ background:var(--red-bg); border-color:var(--red-line); }
.outbound-dismiss{
  flex:none; width:20px; height:20px; border-radius:6px; border:none; background:none;
  color:var(--text-faint); cursor:pointer; font-size:14px; line-height:1;
}
.outbound-dismiss:hover{ background:rgba(0,0,0,.06); color:var(--text); }
.outbound-banner[hidden]{ display:none !important; }
/* Composer ist gesperrt, solange ein Brief in der Warteschlange liegt — sonst
   tippt der Operator in einen Entwurf, der gleich ohnehin rausgeht. */
.composer-locked .draft-textarea{ opacity:.6; }
.composer-locked .reply-send-btn{ opacity:.5; pointer-events:none; }

/* ---------------- Presence-Badges (Kollisionsschutz Punkt 1) ---------------- */
.presence-badges{ display:inline-flex; gap:4px; flex-wrap:wrap; }
.presence-badge{ animation:none; }

/* ---------------- Bestätigungs-Modal (Punkt A.4, 2026-07-28) ----------------
   Kein bisheriges Modal im Projekt — eigenes, minimales Overlay, per JS EINMAL
   an document.body angehängt (überlebt Panel-Neurendering beim Ticketwechsel,
   selbes Muster wie .toast). */
.send-modal-overlay{
  position:fixed; inset:0; z-index:300; background:rgba(15,17,21,.45);
  display:flex; align-items:center; justify-content:center; padding:var(--sp-4);
}
.send-modal{
  width:min(640px, 100%); max-height:88vh; overflow-y:auto; background:var(--surface);
  border-radius:var(--radius-lg); box-shadow:var(--shadow-lg); display:flex; flex-direction:column;
}
.send-modal-head{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-3);
  padding:var(--sp-4) var(--sp-5); border-bottom:1px solid var(--border); font-weight:700; font-size:14.5px;
}
.send-modal-close{
  border:none; background:none; cursor:pointer; color:var(--text-faint); font-size:18px; line-height:1;
  width:26px; height:26px; border-radius:8px;
}
.send-modal-close:hover{ background:var(--surface-alt); color:var(--text); }
.send-modal-body{ padding:var(--sp-4) var(--sp-5); display:flex; flex-direction:column; gap:var(--sp-3); }
.send-modal-row{ font-size:12.8px; color:var(--text); }
.send-modal-row b{ color:var(--text-muted); font-weight:600; margin-right:4px; }
.send-modal-label{ font-size:11.5px; font-weight:700; text-transform:uppercase; letter-spacing:.02em; color:var(--text-faint); }
.send-modal-text, .send-modal-gloss{
  font-size:13px; white-space:pre-wrap; word-break:break-word; background:var(--surface-alt);
  border:1px solid var(--border); border-radius:var(--radius-sm); padding:var(--sp-3);
  max-height:220px; overflow-y:auto; font-family:inherit; margin:4px 0 0;
}
.send-modal-gloss{ color:var(--text-muted); font-style:italic; }
.send-modal-warn{
  display:flex; align-items:center; gap:8px; background:var(--amber-bg); border:1px solid var(--amber-line);
  color:var(--text); border-radius:var(--radius-sm); padding:9px 11px; font-size:12.5px;
}
.send-modal-attach{ font-size:12px; color:var(--text-muted); }
/* Policy-Verstoß-Box (Roman-Audit 2026-07-28) — rot statt amber (.send-modal-
   warn), das ist ein HARTER Block, kein bloßer Hinweis (s. pult.js showModal). */
.send-modal-warn-policy{
  display:block; background:var(--red-bg); border-color:var(--red-line);
}
.send-modal-warn-policy [data-sm-policy-head]{ font-weight:700; margin-bottom:4px; }
.sm-policy-list{ margin:0; padding-left:18px; font-size:12.5px; }
.sm-policy-list li{ margin:2px 0; word-break:break-word; }
/* Kaufland-Bestätigungs-Hinweis (#1216) — amber wie .send-modal-warn, nur mehrzeilig. */
.send-modal-warn-confirm{ display:block; line-height:1.4; }
.send-modal-actions{
  display:flex; justify-content:flex-end; gap:8px; padding:var(--sp-3) var(--sp-5) var(--sp-4);
  border-top:1px solid var(--border);
}

@media (max-width:760px){
  .send-modal{ max-height:94vh; }
  .emoji-pop{ width:210px; grid-template-columns:repeat(7, 1fr); }
}

/* ============================================================
   Responsive (2026-07-27, Layout v2) — unter ~1000px ist kein Platz mehr für
   Liste+Resizer+Konversation nebeneinander: .ticket-open zeigt dann NUR die
   Konversation (volle Breite), die Liste rückt weg (kein Overlay/Scrim mehr
   nötig — reines grid-area-Umschalten, "Schließen" bringt die Liste zurück).
   ============================================================ */
@media (max-width:1000px){
  .shell.ticket-open{
    grid-template-columns: var(--sidebar-w) 1fr;
    grid-template-areas: "sidebar conv";
  }
  .shell.ticket-open .ticket-region,
  .shell.ticket-open .col-resizer{ display:none; }
  .shell.ticket-open .conv-region{ border-left:none; }
  .panel-inner{ max-width:none; }
}
@media (max-width:760px){
  .shell, .shell.ticket-open{ grid-template-columns: 1fr; grid-template-areas:"main"; }
  .shell .ticket-region{ grid-area:main; }
  .shell.ticket-open .conv-region{ grid-area:main; display:flex; }
  .shell.ticket-open .ticket-region{ display:none; }
  .sidebar{ position:fixed; left:0; top:0; width:210px; z-index:60; transform:translateX(-100%); transition:transform .2s ease; box-shadow:var(--shadow-lg); }
  .sidebar.open{ transform:translateX(0); }
  .composer-dock{ padding:var(--sp-3); }
}

/* ============================================================
   🧰 Werkzeuge-Menü (2026-07-29) — <details class="snooze-pop js-portal-pop
   tools-menu"> wiederverwendet die Wiedervorlage-Popover-Optik 1:1 (Portal-
   Positionierung, Schatten, Radius), nur der Inhalt ist eine vertikale Liste
   von "Menüpunkten" statt Formularfeldern. Verschachtelte <details> (Sendung
   suchen / Zusammenführen) bleiben INLINE im schon-portierten Container —
   deshalb KEIN eigenes js-portal-pop/position:absolute für sie (s. pult.js
   initToolsMenu-Kommentar: das würde bei display:none-Summary die
   getBoundingClientRect()-Positionierung brechen).
   ============================================================ */
.tools-menu-body{ width:250px; padding:6px; gap:2px; }
.tools-menu-item{
  display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  background:none; border:none; cursor:pointer; font:inherit; font-size:13px;
  color:var(--text); padding:8px 8px; border-radius:var(--radius-sm); list-style:none;
}
.tools-menu-item::-webkit-details-marker{ display:none; }
.tools-menu-item:hover{ background:var(--surface-alt); }
.tools-menu-submenu{ border-top:1px solid var(--border); margin-top:2px; padding-top:2px; }
.tools-menu-submenu > summary{ cursor:pointer; }
.tools-menu-submenu-body{ padding:8px 8px 4px; display:flex; flex-direction:column; gap:8px; }
.tools-menu-hint{ font-size:12px; color:var(--text-muted); padding:4px 8px; }

/* 💶 Rabatt vorschlagen (2026-09-14) — Presets nutzen .translate-out-pop-langs,
   darunter die freie Eingabe. Nur Tokens, keine eigenen Farben/Masse. */
.discount-custom{ display:flex; gap:6px; padding:4px 8px 2px; align-items:center; }
.discount-input{
  flex:1 1 auto; min-width:0; padding:5px 8px; font-size:12.5px;
  border:1px solid var(--border-strong); border-radius:var(--radius-sm);
  background:var(--surface); color:var(--text);
}
.discount-input:focus{ outline:2px solid var(--accent); outline-offset:1px; }

.shipment-results{ display:flex; flex-direction:column; gap:8px; }
.shipment-row{
  border:1px solid var(--border-strong); border-radius:var(--radius-sm);
  padding:8px; display:flex; flex-direction:column; gap:4px; background:var(--surface-alt);
}
.shipment-row-head{ font-size:12.5px; }
.shipment-row-meta{ font-size:11.5px; color:var(--text-muted); }
.shipment-row-links{ display:flex; gap:10px; }
.shipment-link{ font-size:11.5px; color:var(--accent); text-decoration:none; }
.shipment-link:hover{ text-decoration:underline; }
.shipment-row .btn{ align-self:flex-start; margin-top:2px; }

/* ============================================================
   eBay-Retouren/Disputes-Aktionen (2026-07-29) — Buttons in der gate-row
   (nur gerendert, wenn ebay_action gesetzt ist, s. _ticket_panel.html) +
   Bestätigungs-Modal (Singleton, wiederverwendet .send-modal/.send-modal-*
   der Versand-Bestätigung für ein konsistentes Erscheinungsbild).
   ============================================================ */
.ebay-action-row{ display:flex; flex-wrap:wrap; gap:8px; }
.ebay-action-row .btn{ background:var(--surface); color:var(--text); border-color:var(--border-strong); }
.ebay-action-row .btn:hover{ background:var(--surface-alt); border-color:var(--text-faint); }
/* Geld-Aktionen (Erstattung/Teilerstattung) optisch abgesetzt — dezenter
   roter Akzent-Rahmen, kein voller Warnton (der lebt im Bestätigungs-Modal). */
.ebay-action-row .ebay-act-money{ border-color:var(--red-line); color:var(--red); }
.ebay-action-row .ebay-act-money:hover{ background:var(--red-bg); }

/* ============================================================
   «Neues Ticket» (2026-07-29) — Modal zum Eröffnen eines Vorgangs durch den
   Operator. Kein eigener Modal-Kosmos: Rahmen/Kopf/Fuß kommen 1:1 von
   .send-modal/.send-modal-* (Versand-Bestätigung), hier nur die Innereien —
   Bestellsuche, Trefferliste, Modus-Umschalter.
   ============================================================ */
.newt-field{ display:flex; flex-direction:column; gap:5px; }
.newt-field textarea{
  font:inherit; font-size:13px; color:var(--text); background:var(--surface);
  border:1px solid var(--border-strong); border-radius:var(--radius-sm);
  padding:8px 9px; resize:vertical; min-height:96px;
}
.newt-field textarea:focus, .newt-field .field-input:focus{
  border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-ring); outline:none;
}
.newt-input-locked{ background:var(--surface-alt); color:var(--text-muted); cursor:default; }
.newt-search-row{ display:flex; gap:var(--sp-2); align-items:center; }
.newt-search-row .field-input{ flex:1; min-width:0; }
.newt-hint{ font-size:11.5px; color:var(--text-muted); }
/* Gruppenzeile statt Auswahlfeld — die Gruppe folgt dem Verkaufskanal */
.newt-group-auto{ font-size:12px; color:var(--text-muted); display:flex; align-items:baseline; gap:4px; flex-wrap:wrap; }
.newt-group-name{ color:var(--text); font-weight:600; }
.newt-group-why{ color:var(--text-muted); }
.newt-group-edit{
  background:none; border:none; padding:0; margin-left:4px; cursor:pointer;
  color:var(--accent); font-size:12px; text-decoration:underline;
}
.newt-attach{ display:flex; flex-direction:column; gap:6px; align-items:flex-start; margin-top:6px; }

.newt-results{
  display:flex; flex-direction:column; gap:4px; max-height:230px; overflow-y:auto;
  border:1px solid var(--border); border-radius:var(--radius-sm);
  padding:5px; background:var(--surface-alt); font-size:12.5px; color:var(--text-muted);
}
.newt-order-row{
  display:flex; flex-direction:column; gap:2px; width:100%; text-align:left;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-sm);
  padding:7px 9px; cursor:pointer; font:inherit; color:var(--text);
}
.newt-order-row:hover{ border-color:var(--accent); background:var(--surface-alt); }
.newt-order-head{ font-size:12.5px; font-weight:600; word-break:break-word; }
.newt-order-sub{ font-size:11.5px; color:var(--text-muted); word-break:break-word; }

.newt-picked{
  display:flex; flex-direction:column; gap:3px; align-items:flex-start;
  border:1px solid var(--accent); border-radius:var(--radius-sm);
  padding:8px 10px; background:var(--surface-alt);
}
.newt-picked-label{ font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.02em; color:var(--text-faint); }
.newt-picked .btn{ margin-top:3px; }

.newt-radio{ display:flex; align-items:center; gap:7px; font-size:13px; color:var(--text); cursor:pointer; }
.newt-radio input{ margin:0; }
.newt-radio-off{ opacity:.5; cursor:not-allowed; }
/* Hinweiszeile unter den Modi: normal ein ruhiger Hinweis (amber wie
   .send-modal-warn), im Sperrfall rot — «geht nicht» darf nicht wie
   «beachte bitte» aussehen. */
.newt-mode-note{ font-size:12px; }
.newt-mode-note-block{ background:var(--red-bg); border-color:var(--red-line); }

.ebay-action-modal .send-modal-body{ gap:var(--sp-3); }
.ebay-action-money-warn{ background:var(--red-bg); border-color:var(--red-line); font-weight:600; }
.ebay-action-field label{ display:flex; flex-direction:column; gap:4px; font-size:12.5px; color:var(--text-muted); }
.ebay-action-field input, .ebay-action-field textarea{
  font:inherit; font-size:13px; color:var(--text); background:var(--surface);
  border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:7px 9px;
}
.ebay-action-field textarea{ resize:vertical; min-height:64px; }
.ebay-amount-input-row{ display:flex; align-items:center; gap:8px; }
.ebay-amount-input-row input{ width:140px; }

/* ---------------- Amazon-Mail eingeklappt (2026-07-30) ----------------
   Roman: «скрывай от оператора половину мусора, но не удаляй — наверняка это
   нужно для амазона». Genau so gebaut: sichtbar nur die Kundennachricht,
   das Original bleibt einen Klick entfernt. Es ist NICHT entbehrlich —
   Amazon verlangt beim Antworten das zitierte Original. */
.amz-meta{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin:6px 0 2px; }
.amz-chip{
  font:11.5px var(--font-mono); background:var(--surface-alt); color:var(--text-muted);
  border:1px solid var(--border); border-radius:5px; padding:1px 6px;
}
.amz-open{
  font-size:12px; font-weight:600; color:var(--accent); text-decoration:none;
  border:1px solid var(--accent); border-radius:5px; padding:2px 8px;
}
.amz-open:hover{ background:var(--accent-light); }
.amz-orig{ margin-top:6px; }
.amz-orig > summary{
  cursor:pointer; font-size:11.5px; color:var(--text-faint); list-style:none;
  padding:2px 0; user-select:none;
}
.amz-orig > summary::-webkit-details-marker{ display:none; }
.amz-orig > summary::before{ content:'▸ '; }
.amz-orig[open] > summary::before{ content:'▾ '; }
.amz-orig > summary:hover{ color:var(--text-muted); }
.amz-orig-n{ opacity:.75; }
.amz-orig-body{
  margin-top:4px; padding:8px 10px; border-left:3px solid var(--border);
  background:var(--surface-alt); font-size:12px; color:var(--text-muted);
  max-height:320px; overflow-y:auto;
}

/* Anhänge direkt an der Nachricht im Verlauf (Roman 2026-07-30: «вложение не
   вложилось и не ушло» — es ging mit, war aber nirgends zu sehen). Bewusst
   dieselbe Chip-Optik wie im Composer, damit «angehängt» überall gleich
   aussieht. */
.msg-attach { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 2px; }
.msg-attach-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text); font-size: 13px;
  text-decoration: none; max-width: 100%;
}
.msg-attach-chip:hover { border-color: var(--accent); background: var(--surface-alt); }
.msg-attach-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 320px; }
.msg-attach-size { color: var(--text-muted); font-size: 12px; }

/* Bestellnummer als Link nach Seller Central (Roman 2026-07-30). Sieht aus wie
   ein Chip, verhält sich wie ein Link — deshalb nur Hover-Feedback ergänzt. */
.amz-chip-link{ text-decoration:none; cursor:pointer; }
.amz-chip-link:hover{ border-color:var(--accent); background:var(--surface-alt); }

/* ── Bearbeiter zuweisen (Roman 2026-08-03) ── */
.assign-box{ display:inline-flex; align-items:center; gap:6px; margin-left:auto; }
.assign-box select{ font-size:12.5px; padding:3px 8px; border:1px solid var(--border, #d7dbe3);
  border-radius:8px; background:var(--card-bg, #fff); color:inherit; max-width:190px; cursor:pointer; }
.note-copy-btn{ margin-top:6px; font-size:11.5px; }

/* Текст сообщений/заметок ВСЕГДА выделяем (страховка от любых блокировок
   user-select — напр. залипшего body.resizing из старой вкладки) */
.msg-body, .bot-note-body .msg-body, .bot-note-preview{
  user-select:text !important; -webkit-user-select:text !important;
}

/* Окно «Текст заметки» (частичное копирование, 2026-08-04) */
.note-copy-overlay{ position:fixed; inset:0; background:rgba(0,0,0,.35); z-index:1000;
  display:flex; align-items:center; justify-content:center; }
.note-copy-box{ background:var(--card-bg,#fff); color:inherit; border-radius:12px;
  width:min(640px, 92vw); padding:14px; display:flex; flex-direction:column; gap:10px;
  box-shadow:0 12px 40px rgba(0,0,0,.25); }
.note-copy-head{ display:flex; align-items:center; justify-content:space-between; }
.note-copy-ta{ width:100%; min-height:180px; font:12.5px/1.5 ui-monospace,monospace;
  padding:10px; border:1px solid var(--border,#d7dbe3); border-radius:8px;
  background:var(--surface-alt,#f7f8fa); color:inherit; resize:vertical;
  user-select:text !important; }
.note-copy-foot{ display:flex; align-items:center; gap:10px; }
.note-copy-hint{ font-size:11.5px; color:var(--text-faint,#8a90a0); }
.count-red{ background:#df2f4a !important; color:#fff !important; }

/* ── Gelesen per Nutzer (Roman 04.08): gelesene Tickets ohne Fettschrift ── */
.row-read .subject-title { font-weight: 400; }

/* ── Straf-SLA-Countdown (Roman 04.08: «сколько осталось до штрафбалла») ── */
.sla-timer { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.sla-timer.sla-ok   { color: var(--text-dim, #6b7280); font-weight: 400; }
.sla-timer.sla-warn { color: #b45309; }
.sla-timer.sla-crit { color: #dc2626; }

/* ── Spaltenbreite ziehen (Roman 04.08) ── */
.tix-table th[data-col] { position: relative; }
.col-resize { position: absolute; top: 0; right: -4px; bottom: 0; width: 9px;
              cursor: col-resize; z-index: 3; }
.col-resize:hover, .col-resize.active { background: var(--accent-light, #dbeafe); }
.tix-table.cols-fixed { table-layout: fixed; width: 100%; }
.tix-table.cols-fixed td { overflow: hidden; }

/* Retoure-Modal (Werkzeuge → Retoure anlegen) */
.rt-full{ width:100%; }
.rt-grid{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-3); }
.rt-grid label{ display:flex; flex-direction:column; gap:var(--sp-1); font-size:12px; color:var(--text-muted); }
.rt-grid label select, .rt-grid label input{ width:100%; }
.rt-items{ display:flex; flex-direction:column; gap:var(--sp-1); }
.rt-item{ display:grid; grid-template-columns:auto 1fr 3fr 64px auto; gap:var(--sp-2); align-items:center; font-size:12.8px;
  padding:var(--sp-1) var(--sp-2); border:1px solid var(--border); border-radius:var(--radius-sm); }
.rt-item-sku{ font-weight:600; }
.rt-item-name{ color:var(--text-muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rt-item-of{ color:var(--text-faint); }
.rt-qty{ height:28px; }
.rt-check{ display:flex; align-items:center; gap:var(--sp-2); font-size:12.8px; }
.rt-hint{ color:var(--text-muted); }
@media (max-width:560px){ .rt-grid{ grid-template-columns:1fr; } .rt-item{ grid-template-columns:auto 1fr 60px; } .rt-item-name{ display:none; } }

/* Automatik-Schaltpult (/bots) */
.bots-table td{ vertical-align:middle; }
.bots-desc{ font-size:11.5px; color:var(--text-faint); margin-top:2px; max-width:44ch; }
.bots-days{ display:flex; flex-wrap:wrap; gap:var(--sp-1) var(--sp-2); }
.bots-day{ display:inline-flex; align-items:center; gap:4px; font-size:12px; color:var(--text-muted); }
.bots-time{ white-space:nowrap; }
.bots-time input{ width:96px; }
.bots-meta{ font-size:12px; color:var(--text-muted); }
.bots-foot{ margin-top:var(--sp-3); }
.pill-live{ background:var(--good-bg, #e6f4ea); color:var(--good, #1e7f76); }
.pill-observe{ background:var(--warn-bg, #f6ebd3); color:var(--warn, #b7791f); }
.pill-off{ background:var(--surface-alt); color:var(--text-faint); }

/* Dashboard (Roman 08.09.2026) — плитки «что делать сейчас» */
.dash{ padding-bottom:var(--sp-4); }
.dash-grid{ display:grid; gap:var(--sp-2); margin-bottom:var(--sp-3);
  grid-template-columns:repeat(auto-fill, minmax(196px, 1fr)); }
.dash-card{ display:block; padding:var(--sp-3); border:1px solid var(--border);
  border-radius:var(--radius-sm); background:var(--surface); color:inherit; text-decoration:none; }
a.dash-card:hover{ border-color:var(--border-strong); background:var(--surface-alt); }
.dash-v{ font-size:28px; font-weight:700; line-height:1.15; font-variant-numeric:tabular-nums; }
.dash-u{ font-size:16px; font-weight:600; color:var(--text-muted); }
.dash-k{ margin-top:2px; font-size:13px; font-weight:600; }
.dash-s{ margin-top:2px; font-size:11.5px; color:var(--text-faint); min-height:14px; }
.dash-src{ font-size:11.5px; font-weight:400; color:var(--text-faint); }
.dash-card.dash-warn{ border-color:var(--warn, #b7791f); }
.dash-card.dash-warn .dash-v{ color:var(--warn, #b7791f); }
.dash-card.dash-bad{ border-color:var(--bad, #c05353); }
.dash-card.dash-bad .dash-v{ color:var(--bad, #c05353); }

/* Verwaltungsseite /settings (Roman 08.09.2026) */
.set-h{ margin:var(--sp-4) 0 var(--sp-2); font-size:15px; font-weight:700; color:var(--text); }
.set-table{ margin-bottom:var(--sp-2); }
.set-table td{ vertical-align:middle; }

/* Sammelauswahl über der Liste (Roman 08.09.2026) */
.bulk-bar{ display:flex; align-items:center; gap:var(--sp-2); margin:0 0 var(--sp-2);
  padding:var(--sp-2) var(--sp-3); border:1px solid var(--border-strong);
  border-radius:var(--radius-sm); background:var(--surface-alt); }
.bulk-count{ font-size:13px; color:var(--text-muted); margin-right:auto; }
.bulk-count b{ color:var(--text); font-variant-numeric:tabular-nums; }
.tix-table td.col-check input, .tix-table th.col-check input{ cursor:pointer; }
.tix-table tbody tr.row-picked{ background:var(--accent-light); }

/* Journal der angehaltenen Zuschnitte (/bots, Roman 08.09.2026) */
.holds-table td{ vertical-align:middle; }
.holds-detail{ max-width:52ch; color:var(--text-muted); font-size:12.5px; }
.holds-table tr.hold-done td{ opacity:.55; }
.holds-table thead th.sort-link{ cursor:pointer; user-select:none; }
.holds-table thead th[data-dir=asc]::after{ content:' ▲'; color:var(--text-faint); }
.holds-table thead th[data-dir=desc]::after{ content:' ▼'; color:var(--text-faint); }

/* Aufgaben-Chips im Panel-Kopf (Roman 07.09.2026: Aufgabe abhaken) */
.task-chip{ border:none; cursor:pointer; font: inherit; display:inline-flex; align-items:center; gap:4px; }
.task-chip:hover{ filter:brightness(0.95); }
.task-chip:disabled{ opacity:.5; cursor:default; }
.task-chip-x{ font-weight:700; }
.pill-amber{ background:var(--warn-bg, #f6ebd3); color:var(--warn, #b7791f); }
