HDE Chat Compact

Telegram-style чат + опциональная тёмная тема интерфейса. Автозагрузка до 10 страниц при открытии тикета.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         HDE Chat Compact
// @namespace    http://tampermonkey.net/
// @version      14.45
// @description  Telegram-style чат + опциональная тёмная тема интерфейса. Автозагрузка до 10 страниц при открытии тикета.
// @author       Eban
// @license MIT
// @match        https://*.helpdeskeddy.com/*
// @grant        none
// @run-at       document-start
// @language     ru
// ==/UserScript==

(function () {
  'use strict';

  // ============================================================
  // HDE Chat Compact — Module Map
  // ============================================================
  // 1) Constants + Config Storage
  // 2) Theme Engine (dark/pink remap)
  // 3) Compact Chat Rendering
  // 4) History / Previous Dialogs Loader
  // 5) Colleague Statuses + Staffs Drawer
  // 6) Left Tabs Panel (standalone entries/sort/polling/ui)
  // 7) Settings Panel + Menu Actions
  // 8) Boot / Init / Cleanup
  // ============================================================

  const STYLE_ID = 'hde-compact-v10-style';
  const DONE_CLASS = 'hde-v10-done';
  const DATE_SEP_CLASS = 'hde-date-separator';
  const TICKET_SEP_CLASS = 'hde-ticket-separator';
  const MENU_STYLE_ID = 'hde-tools-menu-style';
  const MENU_PANEL_ID = 'hde-tools-panel';
  const THEME_STYLE_ID = 'hde-tools-theme-style';
  const THEME_BOOT_STYLE_ID = 'hde-tools-theme-boot-style';
  const LEFT_TABS_BOOT_STYLE_ID = 'hde-left-tabs-boot-style';
  const DARK_HTML_CLASS = 'hde-tools-theme-dark';
  const PINK_HTML_CLASS = 'hde-tools-theme-pink';
  const MIDNIGHT_BLUE_HTML_CLASS = 'hde-tools-theme-midnight-blue';
  const TRICOLOR_HTML_CLASS = 'hde-tools-theme-tricolor';
  const MONOCHROME_HTML_CLASS = 'hde-tools-theme-monochrome';
  const LEGACY_DARK_HTML_CLASS = 'hde-tools-dark';
  const LEGACY_THEME_STYLE_ID = 'hde-tools-dark-theme-style';
  const THEME_MODE_STANDARD = 'standard';
  const THEME_MODE_DARK = 'dark';
  const THEME_MODE_PINK = 'pink';
  const THEME_MODE_MIDNIGHT_BLUE = 'midnight-blue';
  const THEME_MODE_TRICOLOR = 'tricolor-contrast';
  const THEME_MODE_MONOCHROME = 'bw-contrast';
  const THEME_MODES = [THEME_MODE_STANDARD, THEME_MODE_DARK, THEME_MODE_PINK, THEME_MODE_MIDNIGHT_BLUE, THEME_MODE_TRICOLOR, THEME_MODE_MONOCHROME];
  const THEME_HTML_CLASSES = [DARK_HTML_CLASS, PINK_HTML_CLASS, MIDNIGHT_BLUE_HTML_CLASS, TRICOLOR_HTML_CLASS, MONOCHROME_HTML_CLASS, LEGACY_DARK_HTML_CLASS];
  const THEME_MODE_TO_HTML_CLASS = {
    [THEME_MODE_DARK]: DARK_HTML_CLASS,
    [THEME_MODE_PINK]: PINK_HTML_CLASS,
    [THEME_MODE_MIDNIGHT_BLUE]: MIDNIGHT_BLUE_HTML_CLASS,
    [THEME_MODE_TRICOLOR]: TRICOLOR_HTML_CLASS,
    [THEME_MODE_MONOCHROME]: MONOCHROME_HTML_CLASS
  };
  const THEME_MODE_TO_LABEL = {
    [THEME_MODE_STANDARD]: 'Стандартная',
    [THEME_MODE_DARK]: 'Тёмная',
    [THEME_MODE_PINK]: 'Розовая',
    [THEME_MODE_MIDNIGHT_BLUE]: 'Midnight Blue',
    [THEME_MODE_TRICOLOR]: 'Контрастная (бело-сине-красная)',
    [THEME_MODE_MONOCHROME]: 'Контрастная ч/б'
  };
  const THEME_BOOT_COLORS = {
    [THEME_MODE_DARK]: { bg: '#121418', fg: '#dcdfe6' },
    [THEME_MODE_PINK]: { bg: '#fbe9f2', fg: '#6f4d60' },
    [THEME_MODE_MIDNIGHT_BLUE]: { bg: '#0b1220', fg: '#cfddf5' },
    [THEME_MODE_TRICOLOR]: { bg: '#ffffff', fg: '#1d3f73' },
    [THEME_MODE_MONOCHROME]: { bg: '#0c0c0c', fg: '#f1f1f1' }
  };
  /** Увеличивать при добавлении полей в панель — пересборка после обновления скрипта */
  const SETTINGS_PANEL_VERSION = '8';
  const STAFFS_DRAWER_ID = 'hde-staffs-drawer';
  const LEFT_TABS_MIRROR_ID = 'hde-left-tabs-mirror';
  const LEFT_TABS_COLUMN_ID = 'hde-left-tabs-column';
  const LEFT_TABS_ONLY_CLASS = 'hde-left-tabs-only';
  const LEFT_TABS_CACHE_KEY = 'hde-left-tabs-cache-v1';
  const LEFT_TABS_CACHE_KEY_LEGACY_V2 = 'hde-left-tabs-cache-v2';
  const MSG_BLOCK_SELECTOR = ':scope > .ticket-conversation__message-block';
  const MSG_HTML_SELECTOR = ':scope > .ticket-conversation__message-text > .ticket-conversation__message-html';
  const DEFAULT_PREVIOUS_TICKETS_TO_LOAD = 5;
  const MAX_PAGES_PER_PREVIOUS_TICKET = 3;
  const DEBUG_LOGS = false;

  function debugLog(...args) {
    if (!DEBUG_LOGS) return;
    console.log(...args);
  }

  // ─── Конфигурация модулей ────────────────────────────────
  const CONFIG = {
    compactChat: false,
    autoLoadHistory: false,
    autoLoadPreviousDialogs: false,
    previousDialogsLimit: 1,
    themeMode: THEME_MODE_STANDARD,
    colleagueStatuses: false,
    leftTabsMirror: false,
    hideNativeTicketTabs: false
  };

  function normalizeThemeMode(value) {
    const mode = String(value || '').toLowerCase();
    return THEME_MODES.includes(mode) ? mode : THEME_MODE_STANDARD;
  }

  function applyThemeClass(mode, root = document.documentElement) {
    if (!root) return false;
    root.classList.remove(...THEME_HTML_CLASSES);
    const nextClass = THEME_MODE_TO_HTML_CLASS[mode];
    if (!nextClass) return false;
    root.classList.add(nextClass);
    return true;
  }

  function buildThemeBootCss() {
    return Object.entries(THEME_BOOT_COLORS).map(([mode, palette]) => {
      const cls = THEME_MODE_TO_HTML_CLASS[mode];
      if (!cls) return '';
      return `html.${cls}, html.${cls} body { background: ${palette.bg} !important; color: ${palette.fg} !important; }`;
    }).join('\n');
  }

  function renderThemeOptions(selectedMode) {
    return THEME_MODES.map((mode) => {
      const label = THEME_MODE_TO_LABEL[mode] || mode;
      const selected = selectedMode === mode ? 'selected' : '';
      return `<option value="${mode}" ${selected}>${label}</option>`;
    }).join('');
  }

  function getEarlyThemeModeFromStorage() {
    try {
      const saved = localStorage.getItem('hde-tools-config');
      if (!saved) return THEME_MODE_STANDARD;
      const parsed = JSON.parse(saved);
      if (parsed && typeof parsed.themeMode === 'string') {
        return normalizeThemeMode(parsed.themeMode);
      }
      if (parsed && typeof parsed.darkTheme === 'boolean') {
        return parsed.darkTheme ? THEME_MODE_DARK : THEME_MODE_STANDARD;
      }
    } catch (e) {}
    return THEME_MODE_STANDARD;
  }

  function getEarlyLeftTabsMirrorFromStorage() {
    try {
      const saved = localStorage.getItem('hde-tools-config');
      if (!saved) return false;
      const parsed = JSON.parse(saved);
      return !!(parsed && parsed.leftTabsMirror === true);
    } catch (e) {}
    return false;
  }

  function getEarlyHideNativeTicketTabsFromStorage() {
    try {
      const saved = localStorage.getItem('hde-tools-config');
      if (!saved) return false;
      const parsed = JSON.parse(saved);
      return !!(parsed && parsed.hideNativeTicketTabs === true);
    } catch (e) {}
    return false;
  }

  function shouldHideNativeTicketTabs() {
    return !!CONFIG.hideNativeTicketTabs;
  }

  function syncNativeTicketTabsVisibilityClass(root = document.documentElement) {
    if (!root) return;
    root.classList.toggle(LEFT_TABS_ONLY_CLASS, shouldHideNativeTicketTabs());
  }

  function applyEarlyThemeBoot() {
    const mode = getEarlyThemeModeFromStorage();
    const root = document.documentElement;
    if (!root) return;
    if (!applyThemeClass(mode, root)) return;

    if (document.getElementById(THEME_BOOT_STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = THEME_BOOT_STYLE_ID;
    style.textContent = buildThemeBootCss();
    if (document.head) document.head.appendChild(style);
    else root.appendChild(style);
  }

  applyEarlyThemeBoot();

  function applyEarlyLeftTabsBoot() {
    const earlyLeftTabsMirror = getEarlyLeftTabsMirrorFromStorage();
    const earlyHideNativeTabs = getEarlyHideNativeTicketTabsFromStorage();
    if (!earlyLeftTabsMirror && !earlyHideNativeTabs) return;
    const root = document.documentElement;
    if (!root) return;
    if (earlyHideNativeTabs) root.classList.add(LEFT_TABS_ONLY_CLASS);

    if (document.getElementById(LEFT_TABS_BOOT_STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = LEFT_TABS_BOOT_STYLE_ID;
    style.textContent = `
      html.${LEFT_TABS_ONLY_CLASS} #ticket-app .ticket-topbar__tabs {
        display: none !important;
      }
      html.${LEFT_TABS_ONLY_CLASS} .ticket-tabs__show-more-popper {
        display: none !important;
      }
      #${LEFT_TABS_COLUMN_ID} {
        flex: 0 0 180px;
        width: 180px;
        min-width: 180px;
        box-sizing: border-box;
        margin-top: 0;
      }
      #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton {
        margin: 0;
        border-radius: 6px;
        overflow: hidden;
        background: #ffffff;
      }
      #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__title {
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        font-weight: 600;
        color: #909399;
        background: #f5f7fa;
      }
      #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__list {
        padding: 6px 0;
      }
      #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item {
        height: 34px;
        margin: 0 8px 8px;
        border-radius: 8px;
        background: linear-gradient(90deg, #eef1f6 25%, #f5f7fa 45%, #eef1f6 65%);
        background-size: 220% 100%;
        animation: hdeLeftTabsSkeletonPulse 1.2s linear infinite;
      }
      #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item:last-child {
        margin-bottom: 0;
      }
      html.${DARK_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton {
        background: #1e2529;
      }
      html.${DARK_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__title {
        color: #c0c4cc;
        background: #252b33;
      }
      html.${DARK_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item {
        background: linear-gradient(90deg, #2a3038 25%, #343b45 45%, #2a3038 65%);
      }
      html.${PINK_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton {
        background: #fff6fb;
      }
      html.${PINK_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__title {
        color: #7a5a6b;
        background: #f8eaf2;
      }
      html.${PINK_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item {
        background: linear-gradient(90deg, #f0deea 25%, #f6e8f0 45%, #f0deea 65%);
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton {
        background: #0f1728;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__title {
        color: #b7cae7;
        background: #16243b;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item {
        background: linear-gradient(90deg, #1b2d4a 25%, #23395f 45%, #1b2d4a 65%);
      }
      html.${TRICOLOR_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton {
        background: #ffffff;
      }
      html.${TRICOLOR_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__title {
        color: #2a4d82;
        background: #edf4ff;
      }
      html.${TRICOLOR_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item {
        background: linear-gradient(90deg, #e7edf6 25%, #f1f5fb 45%, #e7edf6 65%);
      }
      html.${MONOCHROME_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton {
        background: #151515;
      }
      html.${MONOCHROME_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__title {
        color: #e6e6e6;
        background: #1f1f1f;
      }
      html.${MONOCHROME_HTML_CLASS} #${LEFT_TABS_MIRROR_ID}.hde-left-tabs-mirror--skeleton .hde-left-tabs-mirror__skeleton-item {
        background: linear-gradient(90deg, #252525 25%, #323232 45%, #252525 65%);
      }
      @keyframes hdeLeftTabsSkeletonPulse {
        0% { background-position: 100% 0; }
        100% { background-position: -100% 0; }
      }
    `;
    if (document.head) document.head.appendChild(style);
    else root.appendChild(style);
  }

  applyEarlyLeftTabsBoot();

  function ensureEarlyLeftTabsSkeleton(column) {
    if (!(column instanceof Element)) return;
    if (document.getElementById(LEFT_TABS_MIRROR_ID)) return;
    const mirror = document.createElement('div');
    mirror.id = LEFT_TABS_MIRROR_ID;
    mirror.className = 'hde-left-tabs-mirror hde-left-tabs-mirror--skeleton';
    mirror.innerHTML = `
      <div class="hde-left-tabs-mirror__title">
        <span class="hde-left-tabs-mirror__title-text">Тикеты</span>
      </div>
      <div class="hde-left-tabs-mirror__list">
        <div class="hde-left-tabs-mirror__skeleton-item"></div>
        <div class="hde-left-tabs-mirror__skeleton-item"></div>
        <div class="hde-left-tabs-mirror__skeleton-item"></div>
      </div>
    `;
    column.appendChild(mirror);
  }

  function loadConfig() {
    try {
      const saved = localStorage.getItem('hde-tools-config');
      if (saved) {
        Object.assign(CONFIG, JSON.parse(saved));
      }
      const limit = parseInt(CONFIG.previousDialogsLimit, 10);
      CONFIG.previousDialogsLimit = Number.isFinite(limit) ? Math.min(10, Math.max(1, limit)) : DEFAULT_PREVIOUS_TICKETS_TO_LOAD;
      const hasThemeMode = typeof CONFIG.themeMode === 'string' && THEME_MODES.includes(CONFIG.themeMode.toLowerCase());
      if (hasThemeMode) {
        CONFIG.themeMode = normalizeThemeMode(CONFIG.themeMode);
      } else if (typeof CONFIG.darkTheme === 'boolean') {
        CONFIG.themeMode = CONFIG.darkTheme ? THEME_MODE_DARK : THEME_MODE_STANDARD;
      } else {
        CONFIG.themeMode = THEME_MODE_STANDARD;
      }
      if (typeof CONFIG.colleagueStatuses !== 'boolean') CONFIG.colleagueStatuses = false;
      if (typeof CONFIG.leftTabsMirror !== 'boolean') CONFIG.leftTabsMirror = false;
      if (typeof CONFIG.hideNativeTicketTabs !== 'boolean') CONFIG.hideNativeTicketTabs = false;
      delete CONFIG.darkTheme;
    } catch (e) {
      console.warn('Ошибка загрузки конфига:', e);
    }
  }

  function saveConfig() {
    CONFIG.themeMode = normalizeThemeMode(CONFIG.themeMode);
    const payload = Object.assign({}, CONFIG);
    delete payload.darkTheme;
    localStorage.setItem('hde-tools-config', JSON.stringify(payload));
  }

  // ============================================================
  // 2) Theme Engine (dark/pink/midnight-blue/tricolor remap)
  // ============================================================

  // ─── Theme Engine: Dark Theme ────────────────────────────
  // Структурировано секциями, чтобы было проще добавлять новые темы.
  const DARK_THEME_CSS_BASE = `
html.${DARK_HTML_CLASS},
html.${DARK_HTML_CLASS} body {
  background-color: #121418 !important;
  color: #dcdfe6 !important;
  scrollbar-color: #3d4654 #1a1f26;
}
html.${DARK_HTML_CLASS} {
  --menu-background: #161a1f;
  --menu-item-color: #e8eaed;
  --menu-item-background: #161a1f;
  --menu-item-color-hover: #e8f4f7;
  --menu-item-background-hover: #1f2a32;
  --ticket-user-post-color: #e8eaed;
  --ticket-user-post-background: #2d333b;
  --ticket-user-href-color: #7ec8e0;
  --ticket-user-href-hover: #a6dff0;
  --ticket-user-background: #1a1f26;
  --ticket-user-href-border: 0px;
  --ticket-staff-post-color: #f0f2f5;
  --ticket-staff-post-background: #4a5563;
  --ticket-staff-href-color: #fff;
  --ticket-staff-href-hover: #e2e8f0;
  --ticket-staff-own-post-color: #f0f2f5;
  --ticket-staff-own-post-background: #3d4654;
  --ticket-staff-comment-color: #f0fafc;
  --ticket-staff-comment-background: #1a5f6e;
  --ticket-staff-comment-href-color: #e0f7fa;
  --ticket-staff-comment-href-hover: #fff;
  --ticket-staff-own-comment-color: #e8f4f7;
  --ticket-staff-own-comment-background: #154a56;
  --ticket-post-input-color: #e4e7ed;
  --ticket-post-input-background: #252b33;
  --ticket-comment-input-color: #f0fafc;
  --ticket-comment-input-background: #1a5f6e;
  --ticket-primary-button-color: #0f1419;
  --ticket-primary-button-background: #5eb3c9;
  --ticket-primary-button-color-hover: #0f1419;
  --ticket-primary-button-background-hover: #7ec8e0;
  --ticket-secondary-button-color: #dcdfe6;
  --ticket-secondary-button-background: #2a3038;
  --ticket-secondary-button-color-hover: #7ec8e0;
  --ticket-secondary-button-background-hover: #343b45;
}
`;

  const DARK_THEME_CSS_COMPONENTS = `
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__container {
  background-color: #1a1f26 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-text,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter a {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-button,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-button i,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-button .el-icon-setting {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-button:hover,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-button:hover i,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__heading-button:hover .el-icon-setting {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .sidebar,
html.${DARK_HTML_CLASS} .sidebar__item,
html.${DARK_HTML_CLASS} .sidebar__item-icon,
html.${DARK_HTML_CLASS} .sidebar__item-name,
html.${DARK_HTML_CLASS} i.hde-macro {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .sidebar__item:hover {
  background-color: #252b33 !important;
}
html.${DARK_HTML_CLASS} .macro__row,
html.${DARK_HTML_CLASS} .macro__row.macro__row_heading,
html.${DARK_HTML_CLASS} .macro__col {
  background-color: #1e2529 !important;
  color: #c0c4cc !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__heading,
html.${DARK_HTML_CLASS} #ticket-app .ticket-topbar {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-user,
html.${DARK_HTML_CLASS} #ticket-app .ticket-modules {
  background-color: #1a1f26 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__filter-count span {
  background: #2d333b !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .menu__item-badge,
html.${DARK_HTML_CLASS} .menu__item-avatar-status {
  color: #121418 !important;
  font-weight: 700 !important;
}
html.${DARK_HTML_CLASS} .user-card-info,
html.${DARK_HTML_CLASS} .create-ticket-btn,
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav,
html.${DARK_HTML_CLASS} .user-card-custom-title {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav li {
  background-color: #252b33 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav li.active {
  background-color: #2d333b !important;
}
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav li a,
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav li i,
html.${DARK_HTML_CLASS} .user-card-name,
html.${DARK_HTML_CLASS} .user-card-name span,
html.${DARK_HTML_CLASS} .user-card-info a,
html.${DARK_HTML_CLASS} .user-card-info i,
html.${DARK_HTML_CLASS} #user-audit-btn {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav li.active a,
html.${DARK_HTML_CLASS} .etabs.user-card-tabs-nav li.active i,
html.${DARK_HTML_CLASS} .hde-comment-dots.active {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .user-card-toggle,
html.${DARK_HTML_CLASS} .user-card-toggle.pull-right,
html.${DARK_HTML_CLASS} .user-card-toggle.pull-right.ml-2 {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
  border: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} .user-card-info input,
html.${DARK_HTML_CLASS} .user-card-custom-title input {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table,
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table tr,
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table td {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table tr:hover,
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table tr:hover td {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table tr.border-top td,
html.${DARK_HTML_CLASS} .user-card-custom-toggle .user-card-toggle-div table tr.border-bottom td {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .user-card-custom-toggle .depart-ul li {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} i.hde-pencil,
html.${DARK_HTML_CLASS} i.icon-attachment {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs {
  background: #161a1f !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__tab {
  background: #252b33 !important;
  color: #c0c4cc !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs .ticket-tabs__tab-divider {
  background: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__close-all,
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__more-close-all,
html.${DARK_HTML_CLASS} .ticket-tabs__close-all,
html.${DARK_HTML_CLASS} .ticket-tabs__more-close-all {
  background-color: #1e2529 !important;
  border: 1px solid #3d4654 !important;
  color: #c0c4cc !important;
  box-shadow: none !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__close-all:hover,
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__more-close-all:hover,
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__close-all:focus,
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__more-close-all:focus,
html.${DARK_HTML_CLASS} .ticket-tabs__close-all:hover,
html.${DARK_HTML_CLASS} .ticket-tabs__more-close-all:hover,
html.${DARK_HTML_CLASS} .ticket-tabs__close-all:focus,
html.${DARK_HTML_CLASS} .ticket-tabs__more-close-all:focus {
  background-color: #252b33 !important;
  border-color: #4a5563 !important;
  color: #e4e7ed !important;
  outline: none !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-tabs__tab:hover {
  background: #2d333b !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-sla-overdue {
  color: #d97a7a !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-status[title*="offline" i],
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-status[aria-label*="offline" i],
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-status_offline,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-status.status-offline {
  --status-background-color: #8f4a4a !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-status[style*="--status-background-color:#D31616"],
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-status[style*="--status-background-color: #D31616"],
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-select-text[style*="--status-background-color:#D31616"],
html.${DARK_HTML_CLASS} #ticket-app .ticket-list__column-select-text[style*="--status-background-color: #D31616"] {
  --status-background-color: #8f4a4a !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail,
html.${DARK_HTML_CLASS} #ticket-app .ticket-container,
html.${DARK_HTML_CLASS} #ticket-app .el-main {
  background-color: #121418 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail,
html.${DARK_HTML_CLASS} #ticket-app .ticket-container,
html.${DARK_HTML_CLASS} #ticket-app .el-main,
html.${DARK_HTML_CLASS} #ticket-app .ticket-conversation__messages {
  background-color: #1a1f26 !important;
}
/* Metro: боковые колонки и блок полей — в theme жёстко #fff */
html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-left-block,
html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-right-block {
  background-color: #1a1f26 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__image {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__title,
html.${DARK_HTML_CLASS} #ticket-app .ticket-right-block {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-topbar,
html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-topbar {
  background-color: #1e2529 !important;
  border-bottom-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-aside {
  background-color: #1a1f26 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-table {
  background-color: #1a1f26 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-table tr,
html.${DARK_HTML_CLASS} #ticket-app .el-table__body tr {
  background-color: #1a1f26 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-table th.el-table__cell {
  background-color: #161a1f !important;
  color: #c0c4cc !important;
  border-bottom-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-table td.el-table__cell {
  border-bottom-color: #2d333b !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-table--striped .el-table__body tr.el-table__row--striped td {
  background: #1e2529 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-table--enable-row-hover .el-table__body tr:hover > td {
  background-color: #252b33 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-input__inner,
html.${DARK_HTML_CLASS} #ticket-app .el-textarea__inner {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-input__inner {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-input__inner:hover,
html.${DARK_HTML_CLASS} .el-input__inner:focus,
html.${DARK_HTML_CLASS} .el-input.is-focus .el-input__inner {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
  border-color: #4a5563 !important;
}
html.${DARK_HTML_CLASS} .el-checkbox__inner {
  background-color: #252b33 !important;
  border-color: #4a5563 !important;
}
html.${DARK_HTML_CLASS} .el-checkbox__inner:hover,
html.${DARK_HTML_CLASS} .el-checkbox__input:hover .el-checkbox__inner {
  border-color: #7ec8e0 !important;
}
html.${DARK_HTML_CLASS} .el-checkbox__input.is-checked .el-checkbox__inner,
html.${DARK_HTML_CLASS} .el-checkbox__input.is-indeterminate .el-checkbox__inner {
  background-color: #3d4654 !important;
  border-color: #7ec8e0 !important;
}
html.${DARK_HTML_CLASS} .el-checkbox__input.is-checked + .el-checkbox__label,
html.${DARK_HTML_CLASS} .el-checkbox__label {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-checkbox__input.is-disabled .el-checkbox__inner {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-checkbox__input.is-disabled + span.el-checkbox__label,
html.${DARK_HTML_CLASS} .el-checkbox__input.is-disabled.is-checked + span.el-checkbox__label {
  color: #8b9199 !important;
}
html.${DARK_HTML_CLASS} .select,
html.${DARK_HTML_CLASS} .select.is-active,
html.${DARK_HTML_CLASS} .select__options {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .select__options *,
html.${DARK_HTML_CLASS} .select * {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .select__options .is-active,
html.${DARK_HTML_CLASS} .select__options .active,
html.${DARK_HTML_CLASS} .select__options .selected,
html.${DARK_HTML_CLASS} .select__options *:hover {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar .ck-toolbar__items {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor .ck.ck-editor,
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor .ck.ck-editor__top,
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor .ck.ck-sticky-panel,
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor .ck.ck-sticky-panel__content,
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor .ck.ck-sticky-panel__placeholder {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
  box-shadow: none !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar__separator,
html.${DARK_HTML_CLASS} #ticket-app .ck .ck-toolbar__separator {
  background-color: #3d4654 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar button,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar .ck-button {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-list,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-list__item {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-list-item-button,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-button.ck-list-item-button {
  background-color: #1e2529 !important;
  color: #c0c4cc !important;
  border-color: transparent !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-list-item-button:hover,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-button.ck-list-item-button:hover,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-list-item-button.ck-on,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-dropdown__panel .ck-list-item-button[aria-checked="true"] {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar .ck-button:hover,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar .ck-splitbutton__action:hover,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-toolbar .ck-splitbutton__arrow:hover {
  background-color: #252b33 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-button.ck-source-editing-button,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-button.ck-source-editing-button:hover,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-button.ck-source-editing-button:focus,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-button.ck-source-editing-button.ck-on,
html.${DARK_HTML_CLASS} #ticket-app .ck.ck-button.ck-source-editing-button.ck-off {
  background-color: #252b33 !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-select-dropdown,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__dropdown,
html.${DARK_HTML_CLASS} #ticket-app .el-select-dropdown__item,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader-node {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-select-dropdown,
html.${DARK_HTML_CLASS} .el-cascader__dropdown,
html.${DARK_HTML_CLASS} .el-select-dropdown__item,
html.${DARK_HTML_CLASS} .el-cascader-node {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-panel,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-list,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-item,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-panel,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-list,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-item {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-item:hover,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-item:focus,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-item.is-checked,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader__suggestion-item.is-active,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-item:hover,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-item:focus,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-item.is-checked,
html.${DARK_HTML_CLASS} .el-cascader__suggestion-item.is-active {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-scrollbar__view.el-select-dropdown__list,
html.${DARK_HTML_CLASS} #ticket-app .el-scrollbar__view.el-cascader-menu__list,
html.${DARK_HTML_CLASS} #ticket-app .el-cascader-menu {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-scrollbar__view.el-select-dropdown__list,
html.${DARK_HTML_CLASS} .el-scrollbar__view.el-cascader-menu__list,
html.${DARK_HTML_CLASS} .el-cascader-menu {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-select-dropdown__item:hover,
html.${DARK_HTML_CLASS} #ticket-app .el-select-dropdown__item.hover,
html.${DARK_HTML_CLASS} #ticket-app .el-select-dropdown__item.selected,
html.${DARK_HTML_CLASS} #ticket-app .el-select-dropdown__item.is-selected,
html.${DARK_HTML_CLASS} .el-select-dropdown__item:hover,
html.${DARK_HTML_CLASS} .el-select-dropdown__item.hover,
html.${DARK_HTML_CLASS} .el-select-dropdown__item.selected,
html.${DARK_HTML_CLASS} .el-select-dropdown__item.is-selected {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item > *,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-cascader-menu__list .el-cascader-node,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-cascader-menu__list .el-cascader-node > * {
  background-color: transparent !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item:hover,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item.hover,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item.selected,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item.is-selected,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item:hover > *,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item.hover > *,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item.selected > *,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item.is-selected > *,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-cascader-node:hover,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-cascader-node.in-active-path,
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-cascader-node.is-active {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item span[style*="color: rgb(0, 0, 0)"],
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item span[style*="color:#000"],
html.${DARK_HTML_CLASS} #ticket-app .ticket-fields__field-input .el-select-dropdown__item span[style*="color: #000000"] {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-form-item__label {
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .common-value,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__container .ticket-list-column-title__icon,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__post-count,
html.${DARK_HTML_CLASS} #ticket-app .user-color,
html.${DARK_HTML_CLASS} #ticket-app .user-color[data-v-e3f175be] {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-popover__watching-btn {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__info-button button,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__info-button button i {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list_ticket-type-icon,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__new-window button,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__new-window button i,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list .ticket-list-column-title__new-window .icon-new-tab {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter.ticket-sidebar__filter_child {
  border-color: #3d4654 !important;
  border-radius: 14px !important;
  overflow: hidden !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter.ticket-sidebar__filter_child:hover {
  background-color: #252b33 !important;
  border-radius: 14px !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button.router-link-exact-active,
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button.active {
  background-color: #252b33 !important;
  border-radius: 14px !important;
  border: none !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button:hover {
  border-radius: 14px !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-audit__item {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-audit__item:hover {
  background-color: #252b33 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-audit__item::before,
html.${DARK_HTML_CLASS} #ticket-app .ticket-audit__item::after,
html.${DARK_HTML_CLASS} #ticket-app .ticket-audit__line,
html.${DARK_HTML_CLASS} #ticket-app .ticket-audit hr {
  border-color: #3d4654 !important;
  background-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-dialog {
  background: #1e2529 !important;
  border: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-dialog__title,
html.${DARK_HTML_CLASS} #ticket-app .el-dialog__body {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-dialog {
  background: #1e2529 !important;
  border: 1px solid #3d4654 !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45) !important;
}
html.${DARK_HTML_CLASS} .el-dialog__header,
html.${DARK_HTML_CLASS} .el-dialog__body,
html.${DARK_HTML_CLASS} .el-dialog__footer {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-dialog__header {
  border-bottom: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-dialog__footer {
  border-top: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-dialog__title,
html.${DARK_HTML_CLASS} .el-dialog__headerbtn .el-dialog__close,
html.${DARK_HTML_CLASS} .el-dialog__body,
html.${DARK_HTML_CLASS} .el-dialog__body * {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-dialog .el-dialog__headerbtn:hover .el-dialog__close {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .el-dialog table,
html.${DARK_HTML_CLASS} .el-dialog thead,
html.${DARK_HTML_CLASS} .el-dialog tbody,
html.${DARK_HTML_CLASS} .el-dialog tr,
html.${DARK_HTML_CLASS} .el-dialog th,
html.${DARK_HTML_CLASS} .el-dialog td {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-dialog thead th,
html.${DARK_HTML_CLASS} .el-dialog tr:first-child th,
html.${DARK_HTML_CLASS} .el-dialog tr:first-child td {
  background-color: #252b33 !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .el-dialog tbody tr:hover,
html.${DARK_HTML_CLASS} .el-dialog tbody tr:hover td {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .el-dialog input,
html.${DARK_HTML_CLASS} .el-dialog .el-input__inner,
html.${DARK_HTML_CLASS} .el-dialog .el-date-editor .el-input__inner {
  background-color: #252b33 !important;
  border-color: #3d4654 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .staffs-contact-columns__content,
html.${DARK_HTML_CLASS} .staffs-contact-columns__column,
html.${DARK_HTML_CLASS} .sortable__columns {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .staffs-contact-columns__column_heading,
html.${DARK_HTML_CLASS} .staffs-contact-columns__column_footer {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .staffs-contact-columns__order,
html.${DARK_HTML_CLASS} .staffs-contact-columns__value,
html.${DARK_HTML_CLASS} .staffs-contact-columns__width,
html.${DARK_HTML_CLASS} .staffs-contact-columns__delete {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .staffs-contact-columns__column .el-input-number,
html.${DARK_HTML_CLASS} .staffs-contact-columns__column .el-input-number .el-input__inner,
html.${DARK_HTML_CLASS} .staffs-contact-columns__column .el-input-number__decrease,
html.${DARK_HTML_CLASS} .staffs-contact-columns__column .el-input-number__increase {
  background-color: #252b33 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .ticket-group-actions,
html.${DARK_HTML_CLASS} .ticket-group-actions .el-dialog__body,
html.${DARK_HTML_CLASS} .ticket-group-actions__content,
html.${DARK_HTML_CLASS} .ticket-group-actions__columns,
html.${DARK_HTML_CLASS} .ticket-group-actions__column,
html.${DARK_HTML_CLASS} .ticket-group-actions__footer,
html.${DARK_HTML_CLASS} .ticket-group-actions__upload-file,
html.${DARK_HTML_CLASS} .ticket-group-actions__send-mail,
html.${DARK_HTML_CLASS} .ticket-group-actions__submit-button {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-group-actions__field-label,
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-group-actions__field-name {
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-detail__tabs.el-tabs--card > .el-tabs__header,
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__nav,
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__item,
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-detail__tabs .el-tabs__content,
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-editor {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .ticket-group-actions .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-dialog {
  background-color: #1e2529 !important;
  border: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-dialog__header,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-dialog__body,
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-dialog__footer {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .ticket-list-columns__column {
  background-color: #252b33 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .ticket-list-columns__column_heading {
  background-color: transparent !important;
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-button.el-button--default {
  background-color: #2d333b !important;
  color: #dcdfe6 !important;
  border-color: #4a5563 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-button.el-button--default:hover {
  background-color: #343b45 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-list-columns .el-button.el-button--primary {
  color: #0f1419 !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list,
html.${DARK_HTML_CLASS} .ticket-filter-list__filter {
  background: #1e2529 !important;
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list,
html.${DARK_HTML_CLASS} .ticket-filter-list__filter,
html.${DARK_HTML_CLASS} .ticket-filter-list__row,
html.${DARK_HTML_CLASS} .ticket-filter-list__row_heading,
html.${DARK_HTML_CLASS} .ticket-filter-list__col,
html.${DARK_HTML_CLASS} .ticket-filter-list__col_name,
html.${DARK_HTML_CLASS} .ticket-filter-list__col_filter-type,
html.${DARK_HTML_CLASS} .ticket-filter-list__col_activity {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list__row {
  background: #252b33 !important;
  background-color: #252b33 !important;
  color: #dcdfe6 !important;
  border-bottom-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list__row_heading {
  background: #1e2529 !important;
  background-color: #1e2529 !important;
  color: #a8abb2 !important;
  border-bottom-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list__row:hover {
  background: #2d333b !important;
  background-color: #2d333b !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list__col,
html.${DARK_HTML_CLASS} .ticket-filter-list__col_name,
html.${DARK_HTML_CLASS} .ticket-filter-list__col_filter-type,
html.${DARK_HTML_CLASS} .ticket-filter-list__col_activity {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list .ticket-filter-list__col,
html.${DARK_HTML_CLASS} .ticket-filter-list .ticket-filter-list__col * {
  background-color: transparent !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list .el-button,
html.${DARK_HTML_CLASS} .ticket-filter-list button {
  background-color: #2d333b !important;
  color: #dcdfe6 !important;
  border-color: #4a5563 !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list .el-button:hover,
html.${DARK_HTML_CLASS} .ticket-filter-list button:hover {
  background-color: #343b45 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .ticket-filter-list .el-button--primary {
  color: #0f1419 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-user__field,
html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-user__fields,
html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-user__fields-heading,
html.${DARK_HTML_CLASS} #ticket-app .ticket-user__fields-heading {
  border-bottom: none !important;
  border-bottom-color: #1a1f26 !important;
  background-color: #1a1f26 !important;
  margin-bottom: 0 !important;
  padding-bottom: 0 !important;
  box-shadow: none !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-user__fields-heading::before,
html.${DARK_HTML_CLASS} #ticket-app .ticket-user__fields-heading::after {
  border-bottom: none !important;
  border-bottom-color: #1a1f26 !important;
  background-color: #1a1f26 !important;
  box-shadow: none !important;
  content: none !important;
}
html.${DARK_HTML_CLASS} .el-message-box {
  background: #1e2529 !important;
  border: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-message-box__title,
html.${DARK_HTML_CLASS} .el-message-box__message,
html.${DARK_HTML_CLASS} .el-message-box__content,
html.${DARK_HTML_CLASS} .el-message-box__headerbtn .el-message-box__close {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-message-box__input input,
html.${DARK_HTML_CLASS} .el-message-box__input textarea {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-message-box .el-button.el-button--default,
html.${DARK_HTML_CLASS} .el-button.el-button--default.el-button--small {
  background-color: #252b33 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-message-box .el-button.el-button--default:hover,
html.${DARK_HTML_CLASS} .el-button.el-button--default.el-button--small:hover {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
  border-color: #4a5563 !important;
}
html.${DARK_HTML_CLASS} .el-tag.el-tag--info,
html.${DARK_HTML_CLASS} .el-tag.el-tag--info.el-tag--mini,
html.${DARK_HTML_CLASS} .el-tag.el-tag--info.el-tag--mini.el-tag--light {
  background-color: #252b33 !important;
  color: #c0c4cc !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-picker-panel,
html.${DARK_HTML_CLASS} .el-date-picker,
html.${DARK_HTML_CLASS} .el-picker-panel__sidebar,
html.${DARK_HTML_CLASS} .el-date-picker__time-header,
html.${DARK_HTML_CLASS} .el-time-panel {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-picker-panel [class*="time"],
html.${DARK_HTML_CLASS} .el-picker-panel [class*="date"],
html.${DARK_HTML_CLASS} .el-picker-panel__content,
html.${DARK_HTML_CLASS} .el-date-table td,
html.${DARK_HTML_CLASS} .el-time-spinner__item {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-picker-panel__footer {
  background-color: #1e2529 !important;
  border-top-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-picker-panel__footer .el-button {
  background-color: #252b33 !important;
  color: #c0c4cc !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-picker-panel__footer .el-button.el-button--text {
  background-color: transparent !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .el-picker-panel__footer .el-button:hover {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .el-time-spinner__item:hover,
html.${DARK_HTML_CLASS} .el-date-table td.available:hover {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .profile,
html.${DARK_HTML_CLASS} .sidebar {
  background-color: #1a1f26 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .profile * ,
html.${DARK_HTML_CLASS} .sidebar * {
  color: inherit;
}
html.${DARK_HTML_CLASS} .el-plus-input__inner {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-plus-button,
html.${DARK_HTML_CLASS} .el-plus-radio-button__inner {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-plus-button:not(.el-plus-button--primary):not(.el-plus-button--danger) {
  background-color: #252b33 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-plus-radio-button__inner {
  background-color: #252b33 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-plus-button.el-plus-button--primary,
html.${DARK_HTML_CLASS} .el-plus-button.el-plus-button--danger,
html.${DARK_HTML_CLASS} .el-plus-radio-button.is-active .el-plus-radio-button__inner,
html.${DARK_HTML_CLASS} .el-plus-radio-button__orig-radio:checked + .el-plus-radio-button__inner {
  color: #121418 !important;
  font-weight: 600 !important;
}
html.${DARK_HTML_CLASS} .el-popover,
html.${DARK_HTML_CLASS} .el-popper,
html.${DARK_HTML_CLASS} .el-popconfirm {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-popover[x-placement^="top"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popover[x-placement^="bottom"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popover[x-placement^="left"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popover[x-placement^="right"] .popper__arrow {
  border-top-color: #3d4654 !important;
  border-bottom-color: #3d4654 !important;
  border-left-color: #3d4654 !important;
  border-right-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-popover .popper__arrow::after {
  border-top-color: #1e2529 !important;
  border-bottom-color: #1e2529 !important;
  border-left-color: #1e2529 !important;
  border-right-color: #1e2529 !important;
}
html.${DARK_HTML_CLASS} .el-popover[data-popper-placement^="top"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popover[data-popper-placement^="bottom"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popover[data-popper-placement^="left"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popover[data-popper-placement^="right"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popper[data-popper-placement^="top"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popper[data-popper-placement^="bottom"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popper[data-popper-placement^="left"] .popper__arrow,
html.${DARK_HTML_CLASS} .el-popper[data-popper-placement^="right"] .popper__arrow {
  border-top-color: #3d4654 !important;
  border-bottom-color: #3d4654 !important;
  border-left-color: #3d4654 !important;
  border-right-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-popper[data-popper-placement] .popper__arrow::after {
  border-top-color: #1e2529 !important;
  border-bottom-color: #1e2529 !important;
  border-left-color: #1e2529 !important;
  border-right-color: #1e2529 !important;
}
html.${DARK_HTML_CLASS} .ticket-tabs__close-all-popper,
html.${DARK_HTML_CLASS} .ticket-tabs__close-all-popper .el-popconfirm,
html.${DARK_HTML_CLASS} .ticket-tabs__close-all-popper .el-popconfirm__action {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .ticket-tabs__close-all-popper .el-popconfirm__action {
  border-top: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-popconfirm__main,
html.${DARK_HTML_CLASS} .el-popconfirm__main *,
html.${DARK_HTML_CLASS} .el-popover *,
html.${DARK_HTML_CLASS} .el-popper * {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .el-upload-dragger {
  background-color: #1e2529 !important;
  color: #c0c4cc !important;
  border: 1px dashed #3d4654 !important;
}
html.${DARK_HTML_CLASS} .el-upload-dragger:hover {
  background-color: #252b33 !important;
  border-color: #4a5563 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-card {
  background: #1a1f26 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-tabs__item {
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-tabs__item.is-active {
  color: #7ec8e0 !important;
}
html.${DARK_HTML_CLASS} .el-tabs__item {
  color: #a8abb2 !important;
  opacity: 1 !important;
  -webkit-text-fill-color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} .el-tabs__item.is-active {
  color: #e4e7ed !important;
  opacity: 1 !important;
  -webkit-text-fill-color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__tabs.el-tabs--card > .el-tabs__header,
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__nav,
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__item {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__item {
  background-color: #1e2529 !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__tabs.el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__tabs .el-tabs__nav-wrap::after {
  background-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-pagination,
html.${DARK_HTML_CLASS} #ticket-app .el-pagination button,
html.${DARK_HTML_CLASS} #ticket-app .el-pager li {
  color: #c0c4cc !important;
  background: transparent !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-loading-mask {
  background-color: rgba(18, 20, 24, 0.85) !important;
}
html.${DARK_HTML_CLASS} .dashboard,
html.${DARK_HTML_CLASS} .dashboard__header,
html.${DARK_HTML_CLASS} .dashboard-tabs,
html.${DARK_HTML_CLASS} .dashboard-overview,
html.${DARK_HTML_CLASS} .dashboard-overview__ticket-stats,
html.${DARK_HTML_CLASS} .dashboard-overview__filters,
html.${DARK_HTML_CLASS} .dashboard-overview__tickets-by-channels,
html.${DARK_HTML_CLASS} .dashboard-overview__chart,
html.${DARK_HTML_CLASS} .dashboard-overview__ticket-stats-chart {
  background-color: #121418 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .dashboard .el-tabs__header,
html.${DARK_HTML_CLASS} .dashboard .el-tabs__nav-wrap::after,
html.${DARK_HTML_CLASS} .dashboard .el-tabs__item {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .dashboard .el-tabs__item {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .dashboard .el-tabs__item.is-active {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .dashboard .el-input__inner,
html.${DARK_HTML_CLASS} .dashboard .el-select .el-input__inner,
html.${DARK_HTML_CLASS} .dashboard .el-select__tags,
html.${DARK_HTML_CLASS} .dashboard .el-select-dropdown,
html.${DARK_HTML_CLASS} .dashboard .el-select-dropdown__item,
html.${DARK_HTML_CLASS} .dashboard .el-scrollbar__view.el-select-dropdown__list {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .dashboard .el-select-dropdown__item.hover,
html.${DARK_HTML_CLASS} .dashboard .el-select-dropdown__item:hover,
html.${DARK_HTML_CLASS} .dashboard .el-select-dropdown__item.selected,
html.${DARK_HTML_CLASS} .dashboard .el-select-dropdown__item.is-selected {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__header,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__row,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__column {
  background-color: #121418 !important;
  color: #c0c4cc !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:hover,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:focus,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:focus-within {
  background-color: #252b33 !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:hover .dashboard-staffs__column,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:focus .dashboard-staffs__column,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:focus-within .dashboard-staffs__column {
  background-color: transparent !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:hover .el-button--text,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:hover .el-button--text span,
html.${DARK_HTML_CLASS} .dashboard .dashboard-staffs__content .dashboard-staffs__row:hover .el-button--text i {
  color: #9fd3e4 !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-overview__ticket-stats-col[style] {
  background: #1e2529 !important;
  border-color: #3d4654 !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-overview__ticket-stats-col[style*="211, 22, 22"] {
  background: #8f4a4a !important;
  border-color: #8f4a4a !important;
  color: #f2dede !important;
}
html.${DARK_HTML_CLASS} .dashboard .dashboard-overview__ticket-stats-label,
html.${DARK_HTML_CLASS} .dashboard .dashboard-overview__ticket-stats-value,
html.${DARK_HTML_CLASS} .dashboard [class*="dashboard-overview"] {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .dashboard [style*="z-index: 9999999"][style*="background-color: rgb(255, 255, 255)"] {
  background-color: #1e2529 !important;
  border-color: #3d4654 !important;
  color: #dcdfe6 !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45) !important;
}
html.${DARK_HTML_CLASS} .dashboard [style*="z-index: 9999999"][style*="background-color: rgb(255, 255, 255)"] * {
  color: #dcdfe6 !important;
}
html.${DARK_HTML_CLASS} .dashboard canvas {
  filter: saturate(0.82) brightness(0.92);
}
html.${DARK_HTML_CLASS} .contact-users,
html.${DARK_HTML_CLASS} .contact-users__filters,
html.${DARK_HTML_CLASS} .contacts__content,
html.${DARK_HTML_CLASS} .contacts__row,
html.${DARK_HTML_CLASS} .contacts__column,
html.${DARK_HTML_CLASS} .contacts__row_header,
html.${DARK_HTML_CLASS} .pagination,
html.${DARK_HTML_CLASS} .pagination__total {
  background-color: #121418 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-tabs__header,
html.${DARK_HTML_CLASS} .contact-users .el-tabs__nav-wrap::after,
html.${DARK_HTML_CLASS} .contact-users .el-tabs__item {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-tabs__item {
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-tabs__item.is-active {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-tabs__nav .el-tabs__item.is-top,
html.${DARK_HTML_CLASS} .contact-users .el-tabs__nav .el-tabs__item[id^="tab-"] {
  color: #a8abb2 !important;
  opacity: 1 !important;
  -webkit-text-fill-color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-tabs__nav .el-tabs__item.is-top.is-active,
html.${DARK_HTML_CLASS} .contact-users .el-tabs__nav .el-tabs__item[id^="tab-"].is-active {
  color: #e4e7ed !important;
  opacity: 1 !important;
  -webkit-text-fill-color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .contact-users #tab-users,
html.${DARK_HTML_CLASS} .contact-users #tab-companies,
html.${DARK_HTML_CLASS} .contact-users #tab-equipments {
  color: #a8abb2 !important;
  opacity: 1 !important;
  -webkit-text-fill-color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} .contact-users #tab-users.is-active,
html.${DARK_HTML_CLASS} .contact-users #tab-companies.is-active,
html.${DARK_HTML_CLASS} .contact-users #tab-equipments.is-active {
  color: #e4e7ed !important;
  opacity: 1 !important;
  -webkit-text-fill-color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .contact-users__filters,
html.${DARK_HTML_CLASS} .contact-users__filters .el-row,
html.${DARK_HTML_CLASS} .contact-users__filters [class*="tabs"],
html.${DARK_HTML_CLASS} .contact-users__filters [class*="tabs"] * {
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .contacts__row_header,
html.${DARK_HTML_CLASS} .contacts__row {
  border-color: #2d333b !important;
}
html.${DARK_HTML_CLASS} .contacts__row:hover {
  background-color: #1e2529 !important;
}
html.${DARK_HTML_CLASS} .contacts__column .el-button--text,
html.${DARK_HTML_CLASS} .contacts__column .el-button--text span,
html.${DARK_HTML_CLASS} .contacts__column .el-button--text i {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .contacts__column .el-button--text:hover,
html.${DARK_HTML_CLASS} .contacts__column .el-button--text:hover span,
html.${DARK_HTML_CLASS} .contacts__column .el-button--text:hover i {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-switch__core {
  background-color: #252b33 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-switch.is-checked .el-switch__core {
  background-color: #23869b !important;
  border-color: #2da1b8 !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-pagination button,
html.${DARK_HTML_CLASS} .contact-users .el-pager li {
  background-color: transparent !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .contact-users .el-pager li.active {
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor .ck-content,
html.${DARK_HTML_CLASS} #ticket-app .ticket-editor__ckeditor_comment .ck-content {
  background-color: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-cc__copy-append,
html.${DARK_HTML_CLASS} #ticket-app .ticket-cc__copy-prepend {
  background-color: #252b33 !important;
  border-color: #3d4654 !important;
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-button.ticket-editor__add-files-button,
html.${DARK_HTML_CLASS} #ticket-app .el-button.ticket-editor__add-files-button.el-button--text {
  background-color: #1e2529 !important;
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .el-button.ticket-editor__add-files-button:hover {
  background-color: #2d333b !important;
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-conversation__messages {
  background-color: #1a1f26 !important;
}
html.${DARK_HTML_CLASS} .${DATE_SEP_CLASS} {
  color: #8b9199 !important;
}
html.${DARK_HTML_CLASS} .${DATE_SEP_CLASS}::before,
html.${DARK_HTML_CLASS} .${DATE_SEP_CLASS}::after {
  background: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .${TICKET_SEP_CLASS} {
  color: #a8abb2 !important;
}
html.${DARK_HTML_CLASS} .${TICKET_SEP_CLASS}::after {
  background: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .ticket-conversation__message_user .hde-name-inside {
  color: #7ec8e0 !important;
}
html.${DARK_HTML_CLASS} .ticket-conversation__message_user .hde-time-inside {
  color: #c0c4cc !important;
  opacity: 0.75 !important;
}
html.${DARK_HTML_CLASS} .hde-tools-panel {
  background: #1e2529 !important;
  color: #e4e7ed !important;
  box-shadow: 0 4px 20px rgba(0,0,0,0.55) !important;
  border: 1px solid #3d4654 !important;
}
html.${DARK_HTML_CLASS} .hde-tools-panel h3 {
  color: #e4e7ed !important;
  border-bottom-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .hde-tools-field input[type="number"],
html.${DARK_HTML_CLASS} .hde-tools-field select {
  background: #252b33 !important;
  color: #e4e7ed !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .hde-staffs-drawer__overlay {
  background: rgba(15, 20, 25, 0.65) !important;
}
html.${DARK_HTML_CLASS} .hde-staffs-drawer__panel {
  background: #1e2529 !important;
  border-left-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .hde-staffs-drawer__header {
  color: #e4e7ed !important;
  border-bottom-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} .hde-staffs-drawer__close {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} .hde-staffs-drawer__close:hover {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .hde-staffs-drawer__frame {
  background: #1e2529 !important;
}
html.${DARK_HTML_CLASS} .hde-tools-link-btn {
  color: #c0c4cc !important;
  border: none !important;
  background: transparent !important;
}
html.${DARK_HTML_CLASS} .hde-tools-link-btn:hover {
  color: #e4e7ed !important;
}
html.${DARK_HTML_CLASS} .hde-history-close {
  background: #252b33 !important;
  color: #c0c4cc !important;
  border-bottom-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-tickets,
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-container,
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket {
  background-color: #1e2529 !important;
  color: #dcdfe6 !important;
  border-color: #3d4654 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket_current {
  background-color: #252b33 !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket a,
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket i,
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket span {
  color: #c0c4cc !important;
}
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket [style*="color: #000000"],
html.${DARK_HTML_CLASS} #ticket-app .ticket-detail__history-ticket [style*="color:#000000"] {
  color: #e4e7ed !important;
}
`;

  const DARK_THEME_CSS = [
    DARK_THEME_CSS_BASE,
    DARK_THEME_CSS_COMPONENTS
  ].join('\n\n');

  function escapeRegExp(value) {
    return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  }

  function remapCssColors(cssText, paletteMap) {
    const entries = Object.entries(paletteMap).sort((a, b) => b[0].length - a[0].length);
    let mapped = cssText;
    entries.forEach(([from, to]) => {
      mapped = mapped.replace(new RegExp(escapeRegExp(from), 'gi'), to);
    });
    return mapped;
  }

  function buildPinkThemeCssFromDark(darkCssText) {
    const pinkPaletteMap = {
      '#121418': '#fff6fa',
      '#161a1f': '#fdeff5',
      '#1a1f26': '#fbe9f2',
      '#1e2529': '#f7e1ec',
      '#1f2a32': '#f5dbe8',
      '#252b33': '#f1d3e2',
      '#2a3038': '#edcade',
      '#2d333b': '#e8c1d7',
      '#343b45': '#e3b8d0',
      '#3d4654': '#d2a9bf',
      '#4a5563': '#c699b1',
      '#154a56': '#c08aa8',
      '#1a5f6e': '#b97aa0',
      '#5eb3c9': '#be6f9d',
      '#7ec8e0': '#c57bab',
      '#a6dff0': '#d58fbb',
      '#23869b': '#b56794',
      '#409eff': '#bf73a0',
      '#0f1419': '#5f4352',
      '#dcdfe6': '#6f4d60',
      '#e4e7ed': '#5f4352',
      '#e8eaed': '#674b5b',
      '#f0f2f5': '#604453',
      '#c0c4cc': '#7a5a6b',
      '#a8abb2': '#8c6a7c',
      '#e8f4f7': '#6a4e5d',
      '#f0fafc': '#67495a',
      '#e2e8f0': '#6f5162',
      '#f5f7fa': '#f7e6ee',
      '#ecf5ff': '#f3dbe7',
      '#ebeef5': '#e8c8d9',
      '#8f4a4a': '#b9748f',
      '#000000': '#5f4352',
      '#ffffff': '#5f4352',
      '#fff': '#5f4352'
    };

    const prefixed = darkCssText.replaceAll(`html.${DARK_HTML_CLASS}`, `html.${PINK_HTML_CLASS}`);
    return remapCssColors(prefixed, pinkPaletteMap);
  }

  function buildMidnightBlueThemeCssFromDark(darkCssText) {
    const midnightPaletteMap = {
      '#121418': '#0b1220',
      '#161a1f': '#0f1728',
      '#1a1f26': '#111c2f',
      '#1e2529': '#15223a',
      '#1f2a32': '#172843',
      '#252b33': '#1b2d4a',
      '#2a3038': '#203255',
      '#2d333b': '#23395f',
      '#343b45': '#29446f',
      '#3d4654': '#33517f',
      '#4a5563': '#3f6292',
      '#154a56': '#1d416f',
      '#1a5f6e': '#245082',
      '#5eb3c9': '#74c2ff',
      '#7ec8e0': '#8dd0ff',
      '#a6dff0': '#b0e2ff',
      '#23869b': '#4ea4df',
      '#409eff': '#63b4ff',
      '#0f1419': '#08101b',
      '#dcdfe6': '#cfddf5',
      '#e4e7ed': '#d8e4f8',
      '#e8eaed': '#e2ebfa',
      '#f0f2f5': '#edf4ff',
      '#c0c4cc': '#a8b8d6',
      '#a8abb2': '#94a4c2',
      '#e8f4f7': '#deefff',
      '#f0fafc': '#e8f6ff',
      '#e2e8f0': '#d5e2f6',
      '#f5f7fa': '#f3f8ff',
      '#ecf5ff': '#e6f2ff',
      '#ebeef5': '#e4ecfa',
      '#8f4a4a': '#b87f7f',
      '#000000': '#08101b',
      '#ffffff': '#e2ebfa',
      '#fff': '#e2ebfa'
    };

    const prefixed = darkCssText.replaceAll(`html.${DARK_HTML_CLASS}`, `html.${MIDNIGHT_BLUE_HTML_CLASS}`);
    return remapCssColors(prefixed, midnightPaletteMap);
  }

  function buildTricolorThemeCssFromDark(darkCssText) {
    const tricolorPaletteMap = {
      '#121418': '#ffffff',
      '#161a1f': '#f9fbff',
      '#1a1f26': '#f6f9ff',
      '#1e2529': '#f3f6fb',
      '#1f2a32': '#f0f4fa',
      '#252b33': '#eef2f8',
      '#2a3038': '#e7edf6',
      '#2d333b': '#e2e9f4',
      '#343b45': '#d8e1ef',
      '#3d4654': '#c3cfdf',
      '#4a5563': '#acbdd4',
      '#154a56': '#b63b47',
      '#1a5f6e': '#c94956',
      '#5eb3c9': '#d85a66',
      '#7ec8e0': '#e06e79',
      '#a6dff0': '#ea8992',
      '#23869b': '#bf4854',
      '#409eff': '#245fb3',
      '#0f1419': '#1d3f73',
      '#dcdfe6': '#294d82',
      '#e4e7ed': '#1d3f73',
      '#e8eaed': '#234678',
      '#f0f2f5': '#1f4578',
      '#c0c4cc': '#4d6793',
      '#a8abb2': '#6379a1',
      '#e8f4f7': '#23497d',
      '#f0fafc': '#20477a',
      '#e2e8f0': '#2f5386',
      '#f5f7fa': '#ffffff',
      '#ecf5ff': '#f4f7ff',
      '#ebeef5': '#e7effc',
      '#8f4a4a': '#c53b49',
      '#000000': '#1d3f73',
      '#ffffff': '#1d3f73',
      '#fff': '#1d3f73'
    };

    const prefixed = darkCssText.replaceAll(`html.${DARK_HTML_CLASS}`, `html.${TRICOLOR_HTML_CLASS}`);
    return remapCssColors(prefixed, tricolorPaletteMap);
  }

  function buildMonochromeThemeCssFromDark(darkCssText) {
    const monochromePaletteMap = {
      '#121418': '#0c0c0c',
      '#161a1f': '#101010',
      '#1a1f26': '#131313',
      '#1e2529': '#171717',
      '#1f2a32': '#1b1b1b',
      '#252b33': '#212121',
      '#2a3038': '#252525',
      '#2d333b': '#292929',
      '#343b45': '#303030',
      '#3d4654': '#3a3a3a',
      '#4a5563': '#474747',
      '#154a56': '#525252',
      '#1a5f6e': '#5f5f5f',
      '#5eb3c9': '#808080',
      '#7ec8e0': '#9a9a9a',
      '#a6dff0': '#b3b3b3',
      '#c0c4cc': '#c8c8c8',
      '#dcdfe6': '#e5e5e5',
      '#e4e7ed': '#f1f1f1',
      '#ecf5ff': '#f6f6f6',
      '#409eff': '#8b8b8b',
      '#337ecc': '#767676',
      '#67c23a': '#9f9f9f',
      '#e6a23c': '#8b8b8b',
      '#f56c6c': '#a9a9a9',
      '#ff8f8f': '#c0c0c0',
      '#87bdf2': '#9d9d9d'
    };
    const prefixed = darkCssText.replaceAll(`html.${DARK_HTML_CLASS}`, `html.${MONOCHROME_HTML_CLASS}`);
    return remapCssColors(prefixed, monochromePaletteMap);
  }

  const PINK_THEME_CSS = buildPinkThemeCssFromDark(DARK_THEME_CSS);
  const MIDNIGHT_BLUE_THEME_CSS = buildMidnightBlueThemeCssFromDark(DARK_THEME_CSS);
  const TRICOLOR_THEME_CSS = buildTricolorThemeCssFromDark(DARK_THEME_CSS);
  const MONOCHROME_THEME_CSS = buildMonochromeThemeCssFromDark(DARK_THEME_CSS);
  const THEME_CSS = [DARK_THEME_CSS, PINK_THEME_CSS, MIDNIGHT_BLUE_THEME_CSS, TRICOLOR_THEME_CSS, MONOCHROME_THEME_CSS].join('\n\n');

  function injectThemeStyles() {
    const legacyStyle = document.getElementById(LEGACY_THEME_STYLE_ID);
    if (legacyStyle) legacyStyle.remove();
    const bootStyle = document.getElementById(THEME_BOOT_STYLE_ID);
    if (document.getElementById(THEME_STYLE_ID)) {
      if (bootStyle) bootStyle.remove();
      return;
    }
    const style = document.createElement('style');
    style.id = THEME_STYLE_ID;
    style.textContent = THEME_CSS;
    const target = document.head || document.documentElement;
    if (!target) return;
    target.appendChild(style);
    if (bootStyle) bootStyle.remove();
  }

  // Подключаем полный набор CSS темы как можно раньше, чтобы убрать flash default-theme.
  injectThemeStyles();

  function applyThemeFromConfig() {
    injectThemeStyles();
    CONFIG.themeMode = normalizeThemeMode(CONFIG.themeMode);
    applyThemeClass(CONFIG.themeMode);
  }

  // ─── Стили ──────────────────────────────────────────────
  const CSS = `
    /* ── Layout ── */
    .ticket-conversation__message-block {
      display: flex !important; flex-direction: row !important;
      align-items: flex-start !important; gap: 8px !important;
      flex: 1 !important; overflow: visible !important;
      margin-left: 0px !important;
    }
    .ticket-conversation__message_user > .ticket-conversation__message-block,
    .ticket-conversation__message_comment > .ticket-conversation__message-block {
      justify-content: flex-start !important;
    }
    .ticket-conversation__message_staff > .ticket-conversation__message-block {
      justify-content: flex-end !important;
    }

    /* Avatar */
    .ticket-conversation__message-image {
      width: 30px !important; height: 30px !important;
      padding: 2px !important; border-radius: 50% !important;
    }
    .ticket-conversation__message-image_user,
    .ticket-conversation__message-image_staff { margin-top: 0 !important; }

    /* Bubble / text */
    .ticket-conversation__message-text {
      font-size: 13px !important; margin: 0 !important; padding: 0 !important;
    }
    .ticket-conversation__message-html {
      padding: 6px 10px !important; min-height: auto !important;
      position: relative !important;
      border-radius: 12px !important;
    }
    /* Системные сообщения (уходят клиенту) */
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_staff.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #4a5563 !important;
      color: #f0f2f5 !important;
      border: 1px solid rgba(0, 0, 0, 0.08) !important;
      border-radius: 12px !important;
      overflow: hidden !important;
    }
    /* Системные комментарии (внутренние) */
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_comment.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #1a5f6e !important;
      color: #f0fafc !important;
      border: 1px solid rgba(0, 0, 0, 0.08) !important;
      border-radius: 12px !important;
      overflow: hidden !important;
    }
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system > .ticket-conversation__message-html a {
      color: inherit !important;
    }
    /* У системных сообщений отключаем "хвосты"/углы базовой темы */
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system {
      border-radius: 12px !important;
      background: transparent !important;
    }
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      border-radius: 12px !important;
    }
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system::before,
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system::after,
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system > .ticket-conversation__message-html::before,
    #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_system > .ticket-conversation__message-html::after {
      content: none !important;
      display: none !important;
    }
    html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_staff.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #4a5563 !important;
      color: #f0f2f5 !important;
      border-color: #3d4654 !important;
    }
    html.${DARK_HTML_CLASS} #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_comment.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #1a5f6e !important;
      color: #f0fafc !important;
      border-color: #154a56 !important;
    }
    html.${PINK_HTML_CLASS} #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_staff.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #d4b4c3 !important;
      color: #5f4352 !important;
      border-color: #c699b1 !important;
    }
    html.${PINK_HTML_CLASS} #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_comment.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #c08aa8 !important;
      color: #67495a !important;
      border-color: #b97aa0 !important;
    }
    html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_staff.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #23395f !important;
      color: #edf4ff !important;
      border-color: #33517f !important;
    }
    html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket .ticket-conversation__message-text.ticket-conversation__message-text_comment.ticket-conversation__message-text_system > .ticket-conversation__message-html {
      background: #245082 !important;
      color: #e8f6ff !important;
      border-color: #1d416f !important;
    }
    .ticket-conversation__message-html-emoji { font-size: 1.8rem !important; }

    /* Meta — hidden (всё внутри пузыря теперь) */
    .ticket-conversation__message-meta { display: none !important; }

    /* Пагинация скрывается через отдельный стиль autoLoadHistory */

    /* Имя в пузыре */
    .hde-name-inside {
      display: block !important; font-size: 12px !important;
      font-weight: 600 !important; line-height: 1.2 !important;
      margin-bottom: 2px !important;
      font-family: 'Helvetica Neue', Helvetica, 'PingFang SC',
                   'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif !important;
    }
    .ticket-conversation__message_user .hde-name-inside   { text-align: left !important; color: #1a627a !important; }
    .ticket-conversation__message_staff .hde-name-inside,
    .ticket-conversation__message-text_post-own .hde-name-inside { color: #e0e0e0 !important; text-align: right !important; }
    .ticket-conversation__message-text_system .hde-name-inside { color: rgba(255,255,255,0.7) !important; }

    /* Время в пузыре */
    .hde-time-inside {
      display: block !important; clear: both !important;
      font-size: 9px !important; line-height: 1 !important;
      text-align: right !important; margin: 2px 0 0 0 !important;
      padding: 0 4px 1px 0 !important;
      font-family: 'Helvetica Neue', Helvetica, 'PingFang SC',
                   'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif !important;
    }
    .ticket-conversation__message_user .hde-time-inside   { color: #000000 !important; opacity: 0.4 !important; }
    .ticket-conversation__message_staff .hde-time-inside,
    .ticket-conversation__message-text_post-own .hde-time-inside { color: #fff !important; opacity: 0.5 !important; }
    .hde-edited-inside {
      display: none !important;
      font-size: 9px !important;
      line-height: 1 !important;
      margin: 2px 0 0 0 !important;
      padding: 0 0 1px 0 !important;
      font-family: 'Helvetica Neue', Helvetica, 'PingFang SC',
                   'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif !important;
      opacity: 0.55 !important;
    }
    .ticket-conversation__message_user .hde-edited-inside { color: #000000 !important; }
    .ticket-conversation__message_staff .hde-edited-inside,
    .ticket-conversation__message-text_post-own .hde-edited-inside { color: #fff !important; }
    .ticket-conversation__message-html:has(.hde-edited-inside) .hde-edited-inside {
      display: inline-block !important;
      float: left !important;
      margin-right: 5px !important;
    }
    .ticket-conversation__message-html:has(.hde-edited-inside) .hde-time-inside {
      display: inline-block !important;
      float: right !important;
      clear: none !important;
      margin-top: 2px !important;
    }
    .ticket-conversation__message-updated { display: none !important; }

    /* Padding bubble */
    .ticket-conversation__message-html:has(.hde-time-inside) { padding-bottom: 3px !important; }
    .ticket-conversation__message-html:has(.hde-name-inside) { padding-top: 4px !important; }

    /* Кнопки действий */
    .ticket-conversation__actions {
      clear: none !important; padding: 0 !important; margin: 0 !important;
      line-height: 1 !important; display: inline-flex !important;
      align-items: center !important; opacity: 0 !important;
      transition: opacity 0.15s ease !important;
    }
    .ticket-conversation__message:hover .ticket-conversation__actions { opacity: 1 !important; }

    .hde-actions-row { display: inline-flex !important; flex-direction: row !important; align-items: center !important; gap: 6px !important; }
    .ticket-conversation__actions-btn { display: inline-flex !important; align-items: center !important; gap: 2px !important; flex: none !important; }
    .ticket-conversation__actions_button { padding: 2px 3px !important; margin: 0 1px !important; }

    /* Лайки */
    .ticket-conversation__like {
      display: inline-flex !important; width: auto !important; font-size: 10px !important;
      margin: 0 !important; padding: 0 !important; gap: 2px !important;
    }
    .ticket-conversation__like button { padding: 2px 3px !important; margin: 0 !important; font-size: 12px !important; }

    /* Кнопки под пузырём (вынесены из meta) */
    .hde-actions-inline {
      display: inline-flex !important; flex-direction: row !important;
      align-items: center !important; gap: 6px !important;
      align-self: center !important;
      opacity: 0 !important; transition: opacity 0.15s ease !important;
    }
    .ticket-conversation__message:hover .hde-actions-inline { opacity: 1 !important; }
    .ticket-conversation__message.hde-has-reaction > .ticket-conversation__message-block > .hde-actions-inline {
      opacity: 1 !important;
    }
    .ticket-conversation__message_user > .ticket-conversation__message-block > .hde-actions-inline,
    .ticket-conversation__message_comment > .ticket-conversation__message-block > .hde-actions-inline {
      justify-content: flex-end !important; order: 2 !important;
    }
    .ticket-conversation__message_staff > .ticket-conversation__message-block > .hde-actions-inline {
      justify-content: flex-start !important; order: -1 !important;
    }

    /* Разделитель даты */
    .${DATE_SEP_CLASS} {
      display: block !important; width: 100% !important;
      text-align: center !important; clear: both !important;
      margin: 0 !important; padding: 0 !important;
      font-size: 13px !important; line-height: 1.3 !important;
      font-weight: 700 !important; letter-spacing: 1px !important;
      font-family: 'Helvetica Neue', Helvetica, 'PingFang SC',
                   'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif !important;
      color: #999 !important; position: relative !important;
    }
    .${DATE_SEP_CLASS}::before,
    .${DATE_SEP_CLASS}::after {
      content: none !important;
      display: none !important;
    }
    .${TICKET_SEP_CLASS} {
      display: block !important;
      width: 100% !important;
      text-align: center !important;
      margin: 16px 0 8px 0 !important;
      font-size: 12px !important;
      font-weight: 600 !important;
      color: #7f8c8d !important;
      font-family: inherit !important;
      box-sizing: border-box !important;
      line-height: 1.4 !important;
    }
    .${TICKET_SEP_CLASS}::after {
      content: '' !important;
      display: block !important;
      width: 100% !important;
      height: 1px !important;
      background: #c8d6db !important;
      margin-top: 5px !important;
    }



    /* Переопределяем line-height параграфов внутри пузырей */
    #ticket-app .ticket .ticket-conversation__message-text p {
      margin: 0 !important;
      line-height: 1.1 !important;
    }

    /* Убираем разделитель/отступ у полей пользователя */
    #ticket-app .ticket .ticket-user__field {
      padding-bottom: 0 !important;
      border-bottom: none !important;
      margin-bottom: 0 !important;
    }
    #ticket-app .ticket .ticket-user__fields {
      padding-bottom: 0 !important;
      border-bottom: none !important;
    }
    #ticket-app .ticket .ticket-user__fields-heading {
      border-bottom: none !important;
      margin: 0 !important;
      padding-bottom: 0 !important;
    }
    #ticket-app .ticket-user__fields-heading,
    #ticket-app .ticket-user__fields-heading::before,
    #ticket-app .ticket-user__fields-heading::after {
      border-bottom: none !important;
      margin-bottom: 0 !important;
      box-shadow: none !important;
      content: normal !important;
    }
    .ticket-tabs .ticket-tabs__more .ticket-tabs__more-close-all {
      border-top: none !important;
    }
    .ticket-editor__with-borders {
      border-top: none !important;
    }
    .el-tabs--card > .el-tabs__header .el-tabs__nav {
      border-color: #e4e7ed !important;
    }

    /* Отступы между сообщениями */
    .ticket-conversation__message { margin-top: 5px !important; }
    .ticket-conversation__message:first-child { margin-top: 2px !important; }
  `;

  const PAGINATION_STYLE_ID = 'hde-pagination-hide-style';
  const TICKET_SEP_STYLE_ID = 'hde-ticket-sep-style';

  // ============================================================
  // 3) Compact Chat Rendering
  // ============================================================

  function injectTicketSepStyle() {
    if (document.getElementById(TICKET_SEP_STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = TICKET_SEP_STYLE_ID;
    style.textContent = `
      .${TICKET_SEP_CLASS} {
        display: block !important;
        width: 100% !important;
        text-align: center !important;
        margin: 16px 0 8px 0 !important;
        font-size: 12px !important;
        font-weight: 600 !important;
        color: #7f8c8d !important;
        font-family: inherit !important;
        box-sizing: border-box !important;
        line-height: 1.4 !important;
      }
      .${TICKET_SEP_CLASS}::after {
        content: '' !important;
        display: block !important;
        width: 100% !important;
        height: 1px !important;
        background: #c8d6db !important;
        margin-top: 5px !important;
      }
    `;
    document.head.appendChild(style);
  }

  function injectPaginationStyle() {
    if (document.getElementById(PAGINATION_STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = PAGINATION_STYLE_ID;
    style.textContent = '.ticket-conversation__pagination { display: none !important; }';
    document.head.appendChild(style);
  }

  function removePaginationStyle() {
    const el = document.getElementById(PAGINATION_STYLE_ID);
    if (el) el.remove();
  }

  function injectStyle() {
    if (!CONFIG.compactChat) return;
    if (document.getElementById(STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = STYLE_ID;
    style.textContent = CSS;
    document.head.appendChild(style);
  }

  function removeCompactStyle() {
    // Удаляем тег стилей
    const styleEl = document.getElementById(STYLE_ID);
    if (styleEl) styleEl.remove();

    // Убираем разделители дат
    document.querySelectorAll('.' + DATE_SEP_CLASS + ', .' + TICKET_SEP_CLASS).forEach(el => el.remove());

    // Убираем вставленные элементы и классы с каждого сообщения
    document.querySelectorAll('.' + DONE_CLASS).forEach(msgEl => {
      msgEl.classList.remove(DONE_CLASS, 'hde-compact-grouped');
      msgEl.querySelectorAll('.hde-name-inside, .hde-time-inside, .hde-edited-inside').forEach(el => el.remove());

      // Возвращаем кнопки/лайки обратно в meta из hde-actions-inline
      const block = msgEl.querySelector(MSG_BLOCK_SELECTOR);
      const meta  = block && block.querySelector(':scope > .ticket-conversation__message-meta');
      const actionsInline = block && block.querySelector(':scope > .hde-actions-inline');
      if (actionsInline && meta) {
        Array.from(actionsInline.children).forEach(child => meta.appendChild(child));
        actionsInline.remove();
      }
    });
  }

  function getMessageParts(msgEl) {
    const block = msgEl.querySelector(MSG_BLOCK_SELECTOR);
    if (!block) return { block: null, htmlEl: null };
    return {
      block,
      htmlEl: block.querySelector(MSG_HTML_SELECTOR)
    };
  }

  // ─── Парсинг мета ────────────────────────────────────────
  function extractTime(metaText) {
    const match = metaText.match(/(\d{1,2}:\d{2})\s*$/);
    return match ? match[1] : metaText;
  }

  function extractName(metaText) {
    return metaText.replace(/\s+\d{1,2}\.\d{2}\.?\d{0,4}\s+\d{1,2}:\d{2}\s*$/, '').trim();
  }

  function extractDate(metaText) {
    const m = metaText.match(/(\d{1,2}\.\d{2}\.?\d{0,4})/);
    if (!m) return null;
    const parts = m[1].split('.');
    const day = parseInt(parts[0], 10);
    const month = parseInt(parts[1], 10);
    const year = parts.length > 2 ? parts[2] : new Date().getFullYear();
    return String(day).padStart(2, '0') + '.' + String(month).padStart(2, '0') + '.' + year;
  }

  function extractEditedTime(msgEl) {
    const updatedEl = msgEl.querySelector(':scope > .ticket-conversation__message-block .ticket-conversation__message-updated');
    if (!updatedEl) return null;
    const text = (updatedEl.textContent || '').trim();
    const m = text.match(/(\d{1,2}:\d{2})\s*$/);
    return m ? m[1] : null;
  }

  // ─── Работа с пузырями ───────────────────────────────────
  function addInsideBubble(msgEl, className, textContent) {
    const { htmlEl } = getMessageParts(msgEl);
    if (!htmlEl) return null;

    let el = htmlEl.querySelector(':scope > .' + className);
    if (!el) {
      el = document.createElement('span');
      el.className = className;
      if (className === 'hde-name-inside') {
        htmlEl.insertBefore(el, htmlEl.firstChild);
      } else {
        htmlEl.appendChild(el);
      }
    }
    el.textContent = textContent;
    return el;
  }

  function removeFromBubble(msgEl, className) {
    const { htmlEl } = getMessageParts(msgEl);
    if (!htmlEl) return;
    const el = htmlEl.querySelector(':scope > .' + className);
    if (el) el.remove();
  }

  function getMessageMetaText(msgEl) {
    const block = msgEl.querySelector(MSG_BLOCK_SELECTOR);
    if (!block) return '';
    const meta = block.querySelector(':scope > .ticket-conversation__message-meta');
    if (!meta) return '';
    if (!meta.dataset.origText) {
      meta.dataset.origText = meta.textContent.trim();
    }
    return meta.dataset.origText || '';
  }

  function ensureActionsInlineContainer(block, meta) {
    let actionsRow = meta.querySelector(':scope > .hde-actions-row')
      || block.querySelector(':scope > .hde-actions-inline');

    if (!actionsRow) {
      actionsRow = document.createElement('div');
      actionsRow.className = 'hde-actions-inline';
      block.appendChild(actionsRow);
      return actionsRow;
    }

    if (!actionsRow.classList.contains('hde-actions-inline')) {
      actionsRow.classList.remove('hde-actions-row');
      actionsRow.classList.add('hde-actions-inline');
      block.appendChild(actionsRow);
    }

    return actionsRow;
  }

  function hasReactionSelected(likeBlock) {
    if (!likeBlock) return false;
    if (!likeBlock.classList.contains('ticket-conversation__show-on-hover')) return true;
    if (likeBlock.querySelector('.ticket-conversation__like-icon.active')) return true;
    if (likeBlock.querySelector('[aria-pressed="true"]')) return true;
    if (likeBlock.querySelector('.active, .is-active, .selected, [class*="active"], [class*="selected"]')) return true;

    const text = (likeBlock.textContent || '').trim();
    if (!text) return false;
    const nums = text.match(/\d+/g);
    if (!nums) return false;
    return nums.some(function (n) { return parseInt(n, 10) > 0; });
  }

  function getLikeBlock(msgEl) {
    return msgEl.querySelector(':scope > .ticket-conversation__message-user-block > .ticket-conversation__like')
      || msgEl.querySelector(':scope > .ticket-conversation__message-block > .hde-actions-inline > .ticket-conversation__like');
  }

  // ─── Обработка одного сообщения ─────────────────────────
  function processMessage(msgEl, isGrouped) {
    const origMetaText = getMessageMetaText(msgEl);
    const editedTime = extractEditedTime(msgEl);
    const expectedEditedText = editedTime ? ('Изм. ' + editedTime) : '';
    const currentEditedTextEl = msgEl.querySelector(':scope > .ticket-conversation__message-block > .ticket-conversation__message-text > .ticket-conversation__message-html > .hde-edited-inside');
    const currentEditedText = currentEditedTextEl ? (currentEditedTextEl.textContent || '').trim() : '';
    const editedIsSynced = expectedEditedText === currentEditedText;
    const currentLikeBlock = getLikeBlock(msgEl);
    const reactionShouldBeVisible = hasReactionSelected(currentLikeBlock);
    const reactionVisibilitySynced = msgEl.classList.contains('hde-has-reaction') === reactionShouldBeVisible;

    // Пропускаем уже обработанные, если grouped-статус не изменился
    const wasGrouped = msgEl.classList.contains('hde-compact-grouped');
    if (msgEl.classList.contains(DONE_CLASS) && wasGrouped === isGrouped && editedIsSynced && reactionVisibilitySynced) {
      return extractDate(origMetaText);
    }

    msgEl.classList.add(DONE_CLASS);

    const block = msgEl.querySelector(MSG_BLOCK_SELECTOR);
    if (!block) return;

    const meta     = block.querySelector(':scope > .ticket-conversation__message-meta');
    const actions  = block.querySelector(':scope > .ticket-conversation__actions');
    const userBlock = msgEl.querySelector(':scope > .ticket-conversation__message-user-block');
    const likeBlock = currentLikeBlock || getLikeBlock(msgEl);

    const orig = origMetaText;

    // Кнопки + лайки → выносим из meta в block
    if (meta && (actions || likeBlock)) {
      const actionsRow = ensureActionsInlineContainer(block, meta);

      if (actions && actions.parentElement !== actionsRow && actions.parentElement === block) {
        actionsRow.appendChild(actions);
      }
      if (likeBlock && likeBlock.parentElement !== actionsRow && likeBlock.parentElement === userBlock) {
        actionsRow.appendChild(likeBlock);
      }
    }

    msgEl.classList.toggle('hde-has-reaction', hasReactionSelected(likeBlock));

    if (isGrouped) {
      msgEl.classList.add('hde-compact-grouped');
      addInsideBubble(msgEl, 'hde-time-inside', extractTime(orig));
      if (editedTime) {
        addInsideBubble(msgEl, 'hde-edited-inside', 'Изм. ' + editedTime);
      } else {
        removeFromBubble(msgEl, 'hde-edited-inside');
      }
      removeFromBubble(msgEl, 'hde-name-inside');
    } else {
      msgEl.classList.remove('hde-compact-grouped');
      addInsideBubble(msgEl, 'hde-name-inside', extractName(orig));
      addInsideBubble(msgEl, 'hde-time-inside', extractTime(orig));
      if (editedTime) {
        addInsideBubble(msgEl, 'hde-edited-inside', 'Изм. ' + editedTime);
      } else {
        removeFromBubble(msgEl, 'hde-edited-inside');
      }
    }

    return extractDate(orig);
  }

  function insertDateSeparator(parent, dateStr, beforeEl) {
    const sep = document.createElement('span');
    sep.className = DATE_SEP_CLASS;
    sep.textContent = dateStr;
    parent.insertBefore(sep, beforeEl || null);
    return sep;
  }

  function insertTicketSeparator(parent, label, beforeEl) {
    const sep = document.createElement('span');
    sep.className = TICKET_SEP_CLASS;
    sep.textContent = label;
    parent.insertBefore(sep, beforeEl || null);
    return sep;
  }

  function clearPreviousDialogsFromView() {
    const container = getMessagesContainer();
    if (!container) return;
    container.querySelectorAll('[data-hde-history-ticket-id]').forEach(el => el.remove());
    container.querySelectorAll('.' + TICKET_SEP_CLASS).forEach(el => el.remove());
    processAllMessages();
  }

  function getPreviousDialogsLimit() {
    const n = parseInt(CONFIG.previousDialogsLimit, 10);
    if (!Number.isFinite(n)) return DEFAULT_PREVIOUS_TICKETS_TO_LOAD;
    return Math.min(10, Math.max(1, n));
  }

  // ─── Контейнеры ──────────────────────────────────────────
  function getMessagesContainer() {
    return document.querySelector('.ticket-conversation__messages');
  }

  function getTicketId() {
    const m = location.pathname.match(/\/ticket\/(\d+)/);
    return m ? parseInt(m[1], 10) : null;
  }

  // ─── Обработка всех сообщений ────────────────────────────
  var _lastProcessedHash = ''; // хеш для пропуска идентичных прогонов
  function processAllMessages() {
    if (!CONFIG.compactChat) return;
    const container = getMessagesContainer();
    if (!container) return;

    // Быстрый хеш: кол-во сообщений + их data-user-id + даты из meta
    const msgs = container.querySelectorAll('.ticket-conversation__message');
    let hash = msgs.length + '|';
    msgs.forEach(function (m) { hash += (m.getAttribute('data-user-id') || '') + ','; });
    // Добавляем текстовые даты из meta
    const metas = container.querySelectorAll('.ticket-conversation__message-meta');
    metas.forEach(function (m) { hash += (m.textContent || '').trim() + ';'; });
    const updated = container.querySelectorAll('.ticket-conversation__message-updated');
    updated.forEach(function (u) { hash += (u.textContent || '').trim() + ';'; });
    const likes = container.querySelectorAll('.ticket-conversation__like');
    likes.forEach(function (likeEl) { hash += (likeEl.textContent || '').trim() + ';'; });
    const reactionButtons = container.querySelectorAll('.ticket-conversation__like button');
    reactionButtons.forEach(function (btn) {
      hash += (btn.className || '') + '|';
      hash += (btn.getAttribute('aria-pressed') || '') + ';';
    });
    if (hash === _lastProcessedHash) return; // ничего не изменилось — пропускаем
    _lastProcessedHash = hash;

    container.querySelectorAll('.' + DATE_SEP_CLASS).forEach(el => el.remove());

    const messages = container.querySelectorAll('.ticket-conversation__message');
    let lastUserId = null;
    let lastDate   = null;

    messages.forEach((msgEl) => {
      const userId = msgEl.getAttribute('data-user-id') || '-1';
      const isComment = msgEl.classList.contains('ticket-conversation__message_comment');
      const isSystem = userId === '-1' || userId === '-0' || userId === '-2';
      const isSameUser = (userId === lastUserId && !isSystem && !isComment);

      const msgDate = processMessage(msgEl, isSameUser);

      if (msgDate && msgDate !== lastDate) {
        insertDateSeparator(container, msgDate, msgEl);
        lastDate = msgDate;
      } else if (msgDate) {
        lastDate = msgDate;
      }

      lastUserId = userId;
    });
  }

  // ═══════════════════════════════════════════════════════════
  // БЕСКОНЕЧНЫЙ СКРОЛЛ (загрузка старых страниц)
  // ═══════════════════════════════════════════════════════════

  const MAX_PAGES_TO_LOAD = 10;

  let _loadingOlder    = false;
  let _loadedPages     = new Set();
  let _totalPages      = 1;
  let _currentTicketId = null;
  let _historyLoadedForTicketId = null;

  /** Строит DOM-элемент сообщения из данных API (копируя реальную структуру HDE) */
  function buildMessageDOM(msg, users) {
    const user     = users[String(msg.userId)] || {};
    const userName = user.name || 'Unknown';
    const userType = user.type || 'staff';
    const userImg  = user.image || '';

    let typeClass = '_staff'; // default
    if (userType === 'user' || userType === 'client') typeClass = '_user';
    if (msg.type === 'comment' || msg.type === 'note') typeClass = '_comment';
    if (msg.userId == -1 || msg.userId == -2) typeClass = '_comment'; // Система

    // Основной контейнер сообщения
    const msgEl = document.createElement('div');
    msgEl.setAttribute('data-v-1638218a', '');
    msgEl.setAttribute('data-v-4a60d6b5', '');
    msgEl.setAttribute('data-user-id', msg.userId);
    // HDE использует data-post-id или data-comment-id
    if (typeClass === '_comment') {
      msgEl.setAttribute('data-comment-id', msg.id);
    } else {
      msgEl.setAttribute('data-post-id', msg.id);
    }
    msgEl.className = 'ticket-conversation__message ticket-conversation__message' + typeClass;

    // ── user-block (аватар) ──
    const userBlock = document.createElement('div');
    userBlock.setAttribute('data-v-1638218a', '');
    userBlock.setAttribute('data-v-169b4e77', '');
    userBlock.className = 'ticket-conversation__message-user-block';

    // Аватар — div с background-image (как в оригинале)
    const avatarDiv = document.createElement('div');
    avatarDiv.className = 'ticket-conversation__message-image ticket-conversation__message-image' + typeClass;
    avatarDiv.style.cssText = 'background-image: url("' + userImg + '"); cursor: pointer;';
    userBlock.appendChild(avatarDiv);

    // ── message-block ──
    const block = document.createElement('div');
    block.className = 'ticket-conversation__message-block';

    // Meta (скрытая CSS)
    const meta = document.createElement('div');
    meta.className = 'ticket-conversation__message-meta ticket-conversation__message-meta' + typeClass;
    meta.textContent = '  ' + userName + '  ' + msg.createdAt + '  ';
    meta.dataset.origText = userName + '  ' + msg.createdAt;
    block.appendChild(meta);

    // Text wrapper
    const textWrap = document.createElement('div');
    textWrap.className = 'ticket-conversation__message-text ticket-conversation__message-text' + typeClass;
    if (typeClass === '_comment') {
      textWrap.classList.add('ticket-conversation__message-text_system');
    }

    // HTML bubble
    const htmlDiv = document.createElement('div');
    htmlDiv.className = 'ticket-conversation__message-html';
    htmlDiv.innerHTML = msg.text || '';

    // Файлы — миниатюры если есть
    if (msg.files && msg.files.length > 0) {
      msg.files.forEach((file) => {
        const fileLink = document.createElement('div');
        fileLink.style.cssText = 'margin-top:4px;';
        if (file.previewType === 'image' || file.icon === 'icon-image') {
          const img = document.createElement('img');
          img.src = file.thumb || file.preview;
          img.style.cssText = 'max-width:200px;max-height:150px;border-radius:4px;cursor:pointer;';
          img.onclick = () => window.open(file.download || file.preview, '_blank');
          fileLink.appendChild(img);
        } else {
          const a = document.createElement('a');
          a.href = file.download;
          a.target = '_blank';
          a.textContent = file.name || 'Файл';
          a.style.cssText = 'color:#23869b;font-size:11px;text-decoration:none;display:inline-flex;align-items:center;gap:4px;';
          fileLink.appendChild(a);
        }
        htmlDiv.appendChild(fileLink);
      });
    }

    textWrap.appendChild(htmlDiv);
    block.appendChild(textWrap);


    // ★ v12.9: Аватар ВСЕГДА перед block — одинаковый порядок для обоих типов!
    // Оригинальный HDE DOM: msgEl > [userBlock-avatar, block-bubble]
    // Позиционирование через CSS flex-direction на самом msgEl:
    //   _staff:  row-reverse  → [avatar|block] рендерится как [block | avatar] = справа ✅
    //   _user:   row         → [avatar|block] рендерится как [avatar | block] = слева  ✅
    msgEl.appendChild(userBlock);   // аватар
    msgEl.appendChild(block);        // пузырь (всегда после аватара в DOM)

    return msgEl;
  }

  /** Находит первый видимый элемент сообщения (для якоря скролла) */
  function findFirstVisibleMessage(container) {
    var msgs = container.querySelectorAll(':scope > .ticket-conversation__message');
    var ctTop = container.getBoundingClientRect().top;
    for (var i = 0; i < msgs.length; i++) {
      var r = msgs[i].getBoundingClientRect();
      if (r.top - ctTop >= -50) return msgs[i];
    }
    return null;
  }

  /** Загружает страницу старых сообщений через API HDE */
  async function loadOlderPage(pageNum) {
    debugLog('[HDE Compact] → loadOlderPage(' + pageNum + ') start');
    var ticketId = getTicketId();
    if (!ticketId) { console.warn('[HDE Compact] нет ticketId'); return; }

    _loadingOlder = true;
    showLoadIndicator();

    try {
      var url = '/ru/ticket/data/conversation/id/' + ticketId + '/?page=' + pageNum;
      debugLog('[HDE Compact] fetch:', url);
      var resp = await fetch(url, {
        headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
      });
      if (!resp.ok) throw new Error('HTTP ' + resp.status);

      var data = await resp.json();
      debugLog('[HDE Compact] ответ: messages=', data.messages?.length, 'pages=', data.pagination?.totalPages);

      if (data.pagination) {
        _totalPages = data.pagination.totalPages;
      } else if (data.messages && data.messages.length > 0) {
        // Если пагинации нет в ответе но сообщения есть — продолжаем пробовать
        if (pageNum >= _totalPages) _totalPages = pageNum + 1;
      }
      if (!data.messages || data.messages.length === 0) { hideLoadIndicator(); return; }

      var container = getMessagesContainer();
      if (!container) return;

      // Якорь скролла
      var anchorMsg = findFirstVisibleMessage(container);
      var anchorOffset = anchorMsg ? anchorMsg.getBoundingClientRect().top - container.getBoundingClientRect().top : 0;
      // ★ Вставляем перед самым первым элементом контейнера — выше всех уже загруженных
      var firstExisting = container.firstChild;

      // ★ Вставка: API [новее→старее]; insertBefore перед одной refNode
      // каждый новый толкает предыдущие вниз → итог [старее...новее | существующие]
      for (var mi = 0; mi < data.messages.length; mi++) {
        var msg = data.messages[mi];
        var eid = (msg.type === 'comment' || msg.type === 'note' || msg.userId == -1 || msg.userId == -2)
          ? '[data-comment-id="' + msg.id + '"]'
          : '[data-post-id="' + msg.id + '"]';
        if (container.querySelector(eid)) continue;
        var el = buildMessageDOM(msg, data.users || {});
        el.setAttribute('data-hde-loaded', 'true');
        container.insertBefore(el, firstExisting);
      }
      debugLog('[HDE Compact] сообщения вставлены');

      // ★ Перемещаем кнопку истории наверх если есть
      var histBtn = container.querySelector(':scope > .ticket-detail__history');
      if (histBtn && firstExisting) {
        container.insertBefore(histBtn, container.firstChild);
      }

      // Компенсация
      requestAnimationFrame(function () {
        if (anchorMsg && anchorMsg.parentElement) {
          var nOff = anchorMsg.getBoundingClientRect().top - container.getBoundingClientRect().top;
          container.scrollTop += (nOff - anchorOffset);
        }
      });

      processAllMessages();
      _loadedPages.add(pageNum);
      debugLog('[HDE Compact] ← loadOk page=' + pageNum + ' total=' + _totalPages);

      // Автозагрузка следующей страницы цепочкой (не более MAX_PAGES_TO_LOAD)
      var nextP = pageNum + 1;
      var loadedCount = _loadedPages.size - 1; // минус изначальная страница
      var shouldAuto = !_loadedPages.has(nextP)
        && (nextP <= _totalPages || data.messages.length > 0)
        && loadedCount < MAX_PAGES_TO_LOAD;
      if (shouldAuto) {
        debugLog('[HDE Compact] автозагрузка page=' + nextP + ' (загружено ' + loadedCount + '/' + MAX_PAGES_TO_LOAD + ')');
        setTimeout(function () { loadOlderPage(nextP); }, 300);
      } else if (loadedCount >= MAX_PAGES_TO_LOAD) {
        debugLog('[HDE Compact] лимит ' + MAX_PAGES_TO_LOAD + ' страниц достигнут, остановка');
        hideLoadIndicator();
      }

    } catch (err) {
      console.warn('[HDE Compact] Ошибка загрузки:', err);
      console.warn('[HDE Compact] ошибка загрузки:', err.message);
    } finally {
      _loadingOlder = false;
      hideLoadIndicator();
    }
  }

  function showLoadIndicator() {}
  function hideLoadIndicator() {}

  // ============================================================
  // 4) History / Previous Dialogs Loader
  // ============================================================

  async function fetchHistoryTickets(ticketId) {
    const url = '/ru/ticket/data/history/id/' + ticketId + '/?page=1';
    const resp = await fetch(url, {
      headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
    });
    if (!resp.ok) throw new Error('History HTTP ' + resp.status);
    return resp.json();
  }

  async function fetchConversationPage(ticketId, pageNum) {
    const url = '/ru/ticket/data/conversation/id/' + ticketId + '/?page=' + pageNum;
    const resp = await fetch(url, {
      headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
    });
    const finalUrl = String(resp.url || '');
    if (!resp.ok || /captcha|recaptcha|hcaptcha/i.test(finalUrl)) {
      const err = new Error('Conversation HTTP ' + resp.status);
      err.status = Number(resp.status || 0);
      err.url = finalUrl;
      throw err;
    }
    return resp.json();
  }

  function getMessageSelectorByPayload(msg) {
    const isComment = msg.type === 'comment' || msg.type === 'note' || msg.userId == -1 || msg.userId == -2;
    return isComment ? '[data-comment-id="' + msg.id + '"]' : '[data-post-id="' + msg.id + '"]';
  }

  /** Первая нода «текущего» чата: не разделители и не подгруженные прошлые обращения */
  function getPreviousDialogsInsertAnchor(container) {
    for (let c = container.firstChild; c; c = c.nextSibling) {
      if (c.nodeType !== 1) continue;
      if (c.classList && c.classList.contains('ticket-conversation__message')) {
        if (!c.hasAttribute('data-hde-history-ticket-id')) return c;
      }
    }
    return container.firstChild;
  }

  function captureScrollAnchor(container) {
    if (!container) return null;
    const anchorEl = findFirstVisibleMessage(container);
    if (!anchorEl) {
      return { el: null, offsetTop: 0, scrollTop: container.scrollTop };
    }
    return {
      el: anchorEl,
      offsetTop: anchorEl.getBoundingClientRect().top - container.getBoundingClientRect().top,
      scrollTop: container.scrollTop
    };
  }

  function restoreScrollAnchor(container, anchor) {
    if (!container || !anchor) return;
    if (anchor.el && anchor.el.parentElement) {
      const nextOffsetTop = anchor.el.getBoundingClientRect().top - container.getBoundingClientRect().top;
      container.scrollTop += (nextOffsetTop - anchor.offsetTop);
      return;
    }
    if (Number.isFinite(anchor.scrollTop)) {
      container.scrollTop = anchor.scrollTop;
    }
  }

  async function loadPreviousTicketsHistory() {
    if (!CONFIG.autoLoadHistory || !CONFIG.autoLoadPreviousDialogs) return;
    injectTicketSepStyle();
    const currentTicketId = getTicketId();
    if (!currentTicketId || _historyLoadedForTicketId === currentTicketId) return;

    const container = getMessagesContainer();
    if (!container) return;
    const scrollAnchor = captureScrollAnchor(container);

    try {
      const historyItems = await fetchHistoryTickets(currentTicketId);
      if (!Array.isArray(historyItems) || historyItems.length === 0) {
        _historyLoadedForTicketId = currentTicketId;
        return;
      }

      // Берём N самых свежих прошлых диалогов.
      // Независимо от порядка в ответе API — сортируем по id (старше = меньший id)
      // и берём последние N (самые новые).
      const candidates = historyItems
        .filter(item => item && item.id && item.id !== currentTicketId)
        .filter(item => item.watchAccess !== false)
        .sort((a, b) => parseInt(a.id, 10) - parseInt(b.id, 10))
        .slice(-getPreviousDialogsLimit());

      // Якорь — первое сообщение текущего тикета (не кнопка истории / не hde-date-separator).
      // Иначе insertBefore(..., firstChild) вешает прошлые диалоги не туда и порядок «ломается».
      const insertAnchor = getPreviousDialogsInsertAnchor(container);
      if (!insertAnchor) {
        _historyLoadedForTicketId = currentTicketId;
        return;
      }

      // Итерируем от самого НОВОГО к самому СТАРОМУ.
      // Каждый блок вставляется перед одним и тем же insertAnchor (выше предыдущих вставок).
      // Итог (сверху вниз): [самый старый прошлый] … [самый новый прошлый] [текущий тикет]
      for (let i = candidates.length - 1; i >= 0; i--) {
        const t = candidates[i];
        let allMessages = [];
        let usersMap = {};
        let pagesToRead = 1;

        try {
          const firstPage = await fetchConversationPage(t.id, 1);
          usersMap = Object.assign({}, firstPage.users || {});
          if (Array.isArray(firstPage.messages)) {
            allMessages = allMessages.concat(firstPage.messages);
          }
          const totalPages = firstPage.pagination?.totalPages || 1;
          pagesToRead = Math.min(totalPages, MAX_PAGES_PER_PREVIOUS_TICKET);
        } catch (e) {
          continue;
        }

        for (let p = 2; p <= pagesToRead; p++) {
          try {
            const pageData = await fetchConversationPage(t.id, p);
            usersMap = Object.assign(usersMap, pageData.users || {});
            if (Array.isArray(pageData.messages)) {
              allMessages = allMessages.concat(pageData.messages);
            }
          } catch (e) {
            break;
          }
        }

        if (allMessages.length === 0) continue;

        // API отдаёт [новее -> старее], приводим к [старее -> новее]
        allMessages.reverse();

        const insertBefore = insertAnchor;
        let insertedCount = 0;

        // Дата создания тикета = createdAt самого первого сообщения.
        // Страницы грузятся [новее→старее], поэтому самое старое — на последней странице,
        // последний элемент массива на ней (до reverse). После всех загрузок и reverse
        // это allMessages[0] — но только если мы загрузили последнюю страницу.
        // Если totalPages > pagesToRead — загружаем последнюю страницу отдельно только ради даты.
        let ticketDateStr = '';
        try {
          const totalPagesForDate = (await fetchConversationPage(t.id, 1)).pagination?.totalPages || 1;
          const lastPageData = totalPagesForDate > 1 ? await fetchConversationPage(t.id, totalPagesForDate) : null;
          const oldestMsg = lastPageData && Array.isArray(lastPageData.messages) && lastPageData.messages.length > 0
            ? lastPageData.messages[0]  // первый на последней странице = самый старый (API [новее→старее])
            : (allMessages.length > 0 ? allMessages[0] : null);        // fallback: первый после reverse
          if (oldestMsg && oldestMsg.createdAt) {
            const raw = String(oldestMsg.createdAt);
            const m = raw.match(/(\d{1,2}\.\d{2}\.\d{2,4})\s+(\d{1,2}:\d{2})/);
            if (m) ticketDateStr = ' · ' + m[1] + ' ' + m[2];
            else { const d = raw.match(/(\d{1,2}\.\d{2}\.\d{2,4})/); if (d) ticketDateStr = ' · ' + d[1]; }
          }
        } catch (e) { /* дата не критична */ }
        const sep = document.createElement('span');
        sep.className = TICKET_SEP_CLASS;
        const sepLink = document.createElement('a');
        // URL формат: /ru/ticket/list/filter/id/CURRENT/ticket/TARGET
        const _base = location.pathname.match(/(\/ru\/ticket\/list\/filter\/id\/\d+)/);
        const _ticketBase = _base ? _base[1] : '/ru/ticket/list';
        sepLink.href = _ticketBase + '/ticket/' + t.id;
        sepLink.target = '_blank';
        sepLink.rel = 'noopener noreferrer';
        sepLink.textContent = '#' + (t.uniqueId || t.id);
        sepLink.style.cssText = 'color: inherit; text-decoration: none; border-bottom: 1px dashed currentColor;';
        sepLink.addEventListener('mouseover', function () { sepLink.style.opacity = '0.7'; });
        sepLink.addEventListener('mouseout', function () { sepLink.style.opacity = '1'; });
        sep.appendChild(document.createTextNode('Обращение '));
        sep.appendChild(sepLink);
        sep.appendChild(document.createTextNode(ticketDateStr));
        container.insertBefore(sep, insertBefore);

        // Затем вставляем сообщения в обратном порядке (от новых к старым),
        // чтобы после всех insertBefore они легли [старые → новые]
        for (let mi = allMessages.length - 1; mi >= 0; mi--) {
          const msg = allMessages[mi];
          const selector = getMessageSelectorByPayload(msg);
          if (container.querySelector(selector)) continue;
          const el = buildMessageDOM(msg, usersMap);
          el.setAttribute('data-hde-history-ticket-id', String(t.id));
          container.insertBefore(el, sep);
          insertedCount++;
        }

        // Если ничего не вставили — убираем сепаратор
        if (insertedCount === 0) sep.remove();
        else restoreScrollAnchor(container, scrollAnchor);
      }

      _historyLoadedForTicketId = currentTicketId;
      processAllMessages();
      requestAnimationFrame(() => {
        restoreScrollAnchor(container, scrollAnchor);
      });
    } catch (err) {
      console.warn('[HDE Compact] Ошибка подгрузки прошлых обращений:', err);
    }
  }

  /** Запускает цепочку загрузки страниц начиная с nextPage, но не более MAX_PAGES_TO_LOAD */
  function startLoadChain() {
    var ticketId = getTicketId();
    if (!ticketId) return;

    // Сброс если сменился тикет
    if (ticketId !== _currentTicketId) {
      _currentTicketId = ticketId;
      _loadedPages.clear();
      var curPageMatch = location.pathname.match(/\/page\/(\d+)/);
      var curPage = curPageMatch ? parseInt(curPageMatch[1], 10) : 1;
      for (var i = 1; i <= curPage; i++) _loadedPages.add(i);
    }

    // Ищем первую незагруженную страницу
    var nextPage = 1;
    while (_loadedPages.has(nextPage)) nextPage++;

    // Сколько страниц уже догружено (не считая изначально открытую)
    var alreadyLoaded = _loadedPages.size - 1; // минус текущая страница
    if (alreadyLoaded >= MAX_PAGES_TO_LOAD) {
      debugLog('[HDE Compact] достигнут лимит ' + MAX_PAGES_TO_LOAD + ' страниц');
      return;
    }

    if (nextPage <= _totalPages || _totalPages <= 1) {
      loadOlderPage(nextPage);
    }
  }

  /** Парсим totalPages из пагинации на странице */
  function detectTotalPages() {
    if (!CONFIG.autoLoadHistory) return;
    var pagerItems = document.querySelectorAll('.el-pager .number');
    var maxPage = 1;
    pagerItems.forEach(function (el) {
      var n = parseInt(el.textContent.trim(), 10);
      if (n && n > maxPage && n < 1000) maxPage = n;
    });
    if (maxPage > 1) _totalPages = maxPage;
  }

  function initAutoLoad() {
    if (!CONFIG.autoLoadHistory && !CONFIG.autoLoadPreviousDialogs) return;
    _currentTicketId = getTicketId();
    _loadedPages.clear();

    // Фиксируем текущую страницу как уже загруженную
    var curPageMatch = location.pathname.match(/\/page\/(\d+)/);
    var curPage = curPageMatch ? parseInt(curPageMatch[1], 10) : 1;
    for (var i = 1; i <= curPage; i++) _loadedPages.add(i);

    if (CONFIG.autoLoadHistory) detectTotalPages();

    // Запускаем цепочку через небольшую паузу — дать странице отрендериться
    if (CONFIG.autoLoadHistory) setTimeout(startLoadChain, 800);
    if (CONFIG.autoLoadHistory && CONFIG.autoLoadPreviousDialogs) setTimeout(loadPreviousTicketsHistory, 1200);
  }

  // ─── Observer ────────────────────────────────────────────
  // RAF-дебаунс: один запуск за кадр, не накапливаем очередь
  var _rafId = null;
  function scheduleProcess() {
    if (_rafId) return;
    _rafId = requestAnimationFrame(function () {
      _rafId = null;
      processAllMessages();
      if (CONFIG.leftTabsMirror) {
        // Для активного тикета превью берём прямо из DOM,
        // поэтому перерисовываем левую панель сразу на каждую порцию изменений.
        scheduleLeftTabsMirrorSync();
      }
    });
  }

  function observeMessages() {
    var target = document.getElementById('ticket-app') || document.body;
    new MutationObserver(scheduleProcess).observe(target, {
      childList: true,
      subtree: true,
      characterData: true,
      attributes: true,
      attributeFilter: ['class', 'aria-pressed']
    });
  }

  // ─── Статусы коллег в sidebar ────────────────────────────
  let _colleagueStatusesInterval = null;
  let _colleagueStatusesInFlight = false;
  let _colleagueStatusesRetryTimer = null;

  // ============================================================
  // 5) Colleague Statuses + Staffs Drawer
  // ============================================================

  function removeColleagueStatusesBlock() {
    document.querySelectorAll('.staffs-injected-block').forEach((el) => el.remove());
  }

  function stopColleagueStatuses() {
    if (_colleagueStatusesInterval) {
      clearInterval(_colleagueStatusesInterval);
      _colleagueStatusesInterval = null;
    }
    if (_colleagueStatusesRetryTimer) {
      clearTimeout(_colleagueStatusesRetryTimer);
      _colleagueStatusesRetryTimer = null;
    }
    _colleagueStatusesInFlight = false;
    removeColleagueStatusesBlock();
  }

  function updateColleagueStatusesBlock() {
    if (_colleagueStatusesInFlight) return;
    _colleagueStatusesInFlight = true;

    const sidebar = document.querySelector('.ticket-sidebar');
    if (!sidebar) {
      _colleagueStatusesInFlight = false;
      return;
    }

    let container = sidebar.querySelector('.staffs-injected-block');
    if (!container) {
      container = document.createElement('div');
      container.className = 'staffs-injected-block';
      sidebar.appendChild(container);
    }

    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = '/ru/dashboard/staffs/';
    document.body.appendChild(iframe);

    let attempts = 0;
    const finish = () => {
      setTimeout(() => iframe.remove(), 500);
      _colleagueStatusesInFlight = false;
    };

    const check = () => {
      try {
        const doc = iframe.contentDocument;
        const staffsDiv = doc?.querySelector('.dashboard-staffs__content.ps');
        const headerRow = doc?.querySelector('.dashboard-staffs__header .dashboard-staffs__row');
        if (!staffsDiv || !headerRow) {
          if (++attempts < 5) {
            _colleagueStatusesRetryTimer = setTimeout(check, 1500);
            return;
          }
          container.innerHTML = '';
          finish();
          return;
        }

        const columns = Array.from(headerRow.querySelectorAll('.dashboard-staffs__column:not(.dashboard-staffs__column_columns-settings)'));
        const nameIndex = columns.findIndex((col) => col.textContent.trim() === 'Имя');
        const groupIndex = columns.findIndex((col) => col.textContent.trim() === 'Группа');
        const statusIndex = columns.findIndex((col) => col.textContent.trim() === 'Статус');
        const ticketsIndex = columns.findIndex((col) => col.textContent.trim() === 'Активные заявки');

        if (nameIndex < 0 || groupIndex < 0 || statusIndex < 0 || ticketsIndex < 0) {
          container.innerHTML = '';
          finish();
          return;
        }

        const groups = {};
        const groupOrder = [];

        staffsDiv.querySelectorAll('.dashboard-staffs__row').forEach((row) => {
          const cols = Array.from(row.querySelectorAll('.dashboard-staffs__column:not(.dashboard-staffs__column_columns-settings)'));
          const nameEl = cols[nameIndex]?.querySelector('.el-button span');
          const name = nameEl?.textContent.trim() || 'Неизвестно';
          const group = cols[groupIndex]?.textContent.trim() || 'Неизвестно';

          let ticketsCount = 0;
          const ticketsBtn = cols[ticketsIndex]?.querySelector('.el-button span');
          if (ticketsBtn) {
            const match = ticketsBtn.textContent.match(/\d+/);
            ticketsCount = match ? parseInt(match[0], 10) : 0;
          }

          let statusText = 'Неизвестно';
          const selected = row.querySelector('.el-select-dropdown__item.selected span');
          if (selected) {
            statusText = selected.textContent.trim().replace(/^\[.*?\]\s*/, '').trim();
          } else {
            const input = row.querySelector('.el-input__inner');
            if (input?.value) statusText = input.value.trim().replace(/^\[.*?\]\s*/, '').trim();
          }

          let statusClass = 'status-offline';
          if (statusText.includes('В сети')) statusClass = 'status-online';
          else if (statusText.includes('Невидимка')) statusClass = 'status-invisible';
          else if (statusText.includes('Перерыв') || statusText.includes('Обед')) statusClass = 'status-break';

          if (!groups[group]) {
            groups[group] = [];
            groupOrder.push(group);
          }

          groups[group].push({ name, statusText, statusClass, ticketsCount });
        });

        let html = '';
        groupOrder.forEach((groupName) => {
          const totalTickets = groups[groupName].reduce((sum, member) => sum + member.ticketsCount, 0);
          html += `<div class="staffs-injected-group-header">
                     <span class="staffs-injected-group-total">${totalTickets > 0 ? totalTickets : ''}</span>
                     <span class="staffs-injected-group-name">${groupName}</span>
                   </div>
                   <ul class="staffs-injected-list">`;

          groups[groupName].forEach((member) => {
            const badgeValue = member.ticketsCount > 9 ? '9+' : (member.ticketsCount > 0 ? member.ticketsCount : '');
            const badgeClasses = `staffs-injected-badge ${member.statusClass} ${member.ticketsCount > 0 ? 'has-tickets' : 'no-tickets'}`;
            html += `<li class="staffs-injected-member-row">
                       <span class="${badgeClasses}">${badgeValue}</span>
                       <span class="staffs-injected-member-name ${member.statusClass}">${member.name}</span>
                       <span class="staffs-injected-member-status ${member.statusClass}">${member.statusText}</span>
                     </li>`;
          });

          html += '</ul>';
        });

        container.innerHTML = html;
      } catch (e) {
        container.innerHTML = '';
      } finally {
        finish();
      }
    };

    iframe.onload = () => setTimeout(check, 2000);
    iframe.onerror = () => {
      container.innerHTML = '';
      iframe.remove();
      _colleagueStatusesInFlight = false;
    };
  }

  function startColleagueStatuses() {
    if (_colleagueStatusesInterval) return;
    updateColleagueStatusesBlock();
    _colleagueStatusesInterval = setInterval(updateColleagueStatusesBlock, 10000);
  }

  function syncColleagueStatusesModule() {
    if (CONFIG.colleagueStatuses) startColleagueStatuses();
    else stopColleagueStatuses();
  }

  // ============================================================
  // 6) Left Tabs Panel (standalone)
  // ============================================================

  function removeLeftTabsMirror() {
    document.getElementById(LEFT_TABS_MIRROR_ID)?.remove();
    document.getElementById(LEFT_TABS_COLUMN_ID)?.remove();
  }

  let _leftTabsMirrorSyncScheduled = false;
  let _leftTabsMirrorSyncInProgress = false;
  let _leftTabsMirrorSyncPending = false;
  let _leftTabsMirrorLastSignature = '';
  const _leftTabsPreviewByName = Object.create(null);
  const _leftTabsPreviewByTicketId = Object.create(null);
  const _leftTabsLastMessageTsByName = Object.create(null);
  const _leftTabsLastMessageTsByTicketId = Object.create(null);
  const _leftTabsLastMessageTimeTextByName = Object.create(null);
  const _leftTabsLastMessageTimeTextByTicketId = Object.create(null);
  const _leftTabsSeenOrderByName = Object.create(null);
  const _leftTabsSeenOrderByTicketId = Object.create(null);
  const _leftTabsSeenOrderByStoreKey = Object.create(null);
  // Полностью автономный режим: без bridge к нативным вкладкам.
  let _leftTabsSeenOrderSeq = 0;
  const FILE_ONLY_PREVIEW = '📝';
  let _leftTabsPreviewPollInterval = null;
  let _leftTabsDepartmentPollInterval = null;
  let _leftTabsPreviewPollInFlight = false;
  let _leftTabsPreviewPollForcePending = false;
  let _leftTabsPreviewPollForceScheduled = false;
  const _leftTabsForcedPreviewTicketIds = new Set();
  let _leftTabsPreviewLastRunAt = 0;
  let _leftTabsPreviewBackoffUntil = 0;
  let _leftTabsPreviewErrorStreak = 0;
  let _leftTabsCaptchaCooldownUntil = 0;
  const _leftTabsLastPollAtByTicketId = Object.create(null);
  const _leftTabsRecentRequestTs = [];
  let _leftTabsCacheSaveTimer = null;
  const _leftTabsCacheSuppressByTicketId = Object.create(null);
  const _leftTabsCacheSuppressByName = Object.create(null);
  let _leftTabsCacheGlobalSuppressUntil = 0;
  const _leftTabsHydratedByTicketId = Object.create(null);
  const _leftTabsHydratedByName = Object.create(null);
  let _leftTabsNativeTabsVm = null;
  /** Собственный список открытых тикетов (только numeric ticketId), без родной панели вкладок */
  let _leftTabsOpenOrder = [];
  const _leftTabsOpenMeta = Object.create(null);
  const _leftTabsBadgeByTicketId = Object.create(null);
  /**
   * После закрытия активного тикета URL ненадолго остаётся прежним — иначе ensureOpen снова
   * добавит id в order и debounce перезатрёт localStorage. Пока URL = этому id, не регистрируем.
   */
  let _leftTabsBlockEnsureForClosedId = null;
  let _leftTabsLastHrefForSync = location.href;
  const LEFT_TABS_PREVIEW_POLL_MS = 8000;
  const LEFT_TABS_PREVIEW_MIN_GAP_MS = 5000;
  const LEFT_TABS_PREVIEW_FORCE_MIN_GAP_MS = 7000;
  const LEFT_TABS_MAX_REQUESTS_PER_RUN = 1;
  const LEFT_TABS_PER_TICKET_MIN_GAP_MS = 45 * 1000;
  const LEFT_TABS_MAX_REQUESTS_PER_MINUTE = 6;
  const LEFT_TABS_DEPARTMENT_REFRESH_MS = 10000;
  const LEFT_TABS_CAPTCHA_COOLDOWN_MS = 10 * 60 * 1000;
  const LEFT_TABS_ERROR_BASE_BACKOFF_MS = 2000;
  const LEFT_TABS_ERROR_MAX_BACKOFF_MS = 60 * 1000;
  const LEFT_TABS_CACHE_SUPPRESS_MS = 8000;

  function nowMs() {
    return Date.now();
  }

  function pruneLeftTabsCacheSuppress() {
    const now = nowMs();
    for (const [k, until] of Object.entries(_leftTabsCacheSuppressByTicketId)) {
      if (Number(until) <= now) delete _leftTabsCacheSuppressByTicketId[k];
    }
    for (const [k, until] of Object.entries(_leftTabsCacheSuppressByName)) {
      if (Number(until) <= now) delete _leftTabsCacheSuppressByName[k];
    }
  }

  function markLeftTabsCacheSuppress(entry, ms = LEFT_TABS_CACHE_SUPPRESS_MS) {
    const until = nowMs() + ms;
    const ticketId = Number.isFinite(entry?.ticketId) ? entry.ticketId : null;
    const name = String(entry?.name || '').trim();
    const norm = normalizeTabName(name);
    if (Number.isFinite(ticketId)) _leftTabsCacheSuppressByTicketId[ticketId] = until;
    if (name) _leftTabsCacheSuppressByName[name] = until;
    if (norm) _leftTabsCacheSuppressByName[norm] = until;
  }

  function isLeftTabsCacheSuppressed(name, ticketId) {
    pruneLeftTabsCacheSuppress();
    const now = nowMs();
    if (_leftTabsCacheGlobalSuppressUntil > now) return true;
    if (Number.isFinite(ticketId) && Number(_leftTabsCacheSuppressByTicketId[ticketId] || 0) > now) return true;
    const raw = String(name || '').trim();
    const norm = normalizeTabName(raw);
    return Number(_leftTabsCacheSuppressByName[raw] || 0) > now
      || Number(_leftTabsCacheSuppressByName[norm] || 0) > now;
  }

  function scheduleLeftTabsCacheSave() {
    if (_leftTabsCacheSaveTimer) return;
    _leftTabsCacheSaveTimer = setTimeout(() => {
      _leftTabsCacheSaveTimer = null;
      try {
        const payload = {
          previewByName: _leftTabsPreviewByName,
          previewByTicketId: _leftTabsPreviewByTicketId,
          timeTextByName: _leftTabsLastMessageTimeTextByName,
          timeTextByTicketId: _leftTabsLastMessageTimeTextByTicketId,
          tsByName: _leftTabsLastMessageTsByName,
          tsByTicketId: _leftTabsLastMessageTsByTicketId,
          openTabs: {
            order: _leftTabsOpenOrder.slice(),
            meta: { ..._leftTabsOpenMeta },
            badgeByTicketId: { ..._leftTabsBadgeByTicketId }
          }
        };
        localStorage.setItem(LEFT_TABS_CACHE_KEY, JSON.stringify(payload));
      } catch (e) {}
    }, 300);
  }

  function flushLeftTabsCacheNow() {
    try {
      if (_leftTabsCacheSaveTimer) {
        clearTimeout(_leftTabsCacheSaveTimer);
        _leftTabsCacheSaveTimer = null;
      }
      const payload = {
        previewByName: _leftTabsPreviewByName,
        previewByTicketId: _leftTabsPreviewByTicketId,
        timeTextByName: _leftTabsLastMessageTimeTextByName,
        timeTextByTicketId: _leftTabsLastMessageTimeTextByTicketId,
        tsByName: _leftTabsLastMessageTsByName,
        tsByTicketId: _leftTabsLastMessageTsByTicketId,
        openTabs: {
          order: _leftTabsOpenOrder.slice(),
          meta: { ..._leftTabsOpenMeta },
          badgeByTicketId: { ..._leftTabsBadgeByTicketId }
        }
      };
      localStorage.setItem(LEFT_TABS_CACHE_KEY, JSON.stringify(payload));
    } catch (e) {}
  }

  function clearLeftTabsCacheForEntry(entry) {
    markLeftTabsCacheSuppress(entry);
    const name = String(entry?.name || '').trim();
    const norm = normalizeTabName(name);
    const ticketId = Number.isFinite(entry?.ticketId) ? entry.ticketId : null;

    if (name) {
      delete _leftTabsPreviewByName[name];
      delete _leftTabsLastMessageTimeTextByName[name];
      delete _leftTabsLastMessageTsByName[name];
      delete _leftTabsSeenOrderByName[name];
    }
    if (Number.isFinite(ticketId)) {
      delete _leftTabsPreviewByTicketId[ticketId];
      delete _leftTabsLastMessageTimeTextByTicketId[ticketId];
      delete _leftTabsLastMessageTsByTicketId[ticketId];
      delete _leftTabsSeenOrderByTicketId[ticketId];
      delete _leftTabsHydratedByTicketId[ticketId];
      _leftTabsOpenOrder = _leftTabsOpenOrder.filter((id) => id !== ticketId);
      delete _leftTabsOpenMeta[ticketId];
      delete _leftTabsBadgeByTicketId[ticketId];
    }
    if (norm) delete _leftTabsHydratedByName[norm];
    flushLeftTabsCacheNow();
  }

  function clearLeftTabsCacheAll() {
    _leftTabsCacheGlobalSuppressUntil = nowMs() + LEFT_TABS_CACHE_SUPPRESS_MS;
    pruneLeftTabsCacheSuppress();
    const clearObj = (obj) => Object.keys(obj).forEach((k) => { delete obj[k]; });
    clearObj(_leftTabsPreviewByName);
    clearObj(_leftTabsPreviewByTicketId);
    clearObj(_leftTabsLastMessageTimeTextByName);
    clearObj(_leftTabsLastMessageTimeTextByTicketId);
    clearObj(_leftTabsLastMessageTsByName);
    clearObj(_leftTabsLastMessageTsByTicketId);
    clearObj(_leftTabsSeenOrderByName);
    clearObj(_leftTabsSeenOrderByTicketId);
    clearObj(_leftTabsHydratedByTicketId);
    clearObj(_leftTabsHydratedByName);
    _leftTabsOpenOrder = [];
    Object.keys(_leftTabsOpenMeta).forEach((k) => { delete _leftTabsOpenMeta[k]; });
    Object.keys(_leftTabsBadgeByTicketId).forEach((k) => { delete _leftTabsBadgeByTicketId[k]; });
    _leftTabsBlockEnsureForClosedId = null;
    try {
      localStorage.removeItem(LEFT_TABS_CACHE_KEY);
      localStorage.removeItem(LEFT_TABS_CACHE_KEY_LEGACY_V2);
    } catch (e) {}
    flushLeftTabsCacheNow();
  }

  function loadLeftTabsCache() {
    try {
      const mergeObject = (target, source) => {
        if (!source || typeof source !== 'object') return;
        for (const [k, v] of Object.entries(source)) {
          if (v == null) continue;
          target[k] = v;
        }
      };

      let raw = localStorage.getItem(LEFT_TABS_CACHE_KEY);
      if (!raw) {
        const legacyV2 = localStorage.getItem(LEFT_TABS_CACHE_KEY_LEGACY_V2);
        if (legacyV2) {
          const v2 = JSON.parse(legacyV2);
          mergeObject(_leftTabsPreviewByTicketId, v2.previewByTicketId);
          mergeObject(_leftTabsLastMessageTimeTextByTicketId, v2.timeTextByTicketId);
          mergeObject(_leftTabsLastMessageTsByTicketId, v2.tsByTicketId);
          mergeObject(_leftTabsSeenOrderByTicketId, v2.seenOrderByTicketId);
          try {
            localStorage.removeItem(LEFT_TABS_CACHE_KEY_LEGACY_V2);
          } catch (e) {}
          flushLeftTabsCacheNow();
        }
        return;
      }
      const parsed = JSON.parse(raw);
      mergeObject(_leftTabsPreviewByName, parsed.previewByName);
      mergeObject(_leftTabsPreviewByTicketId, parsed.previewByTicketId);
      mergeObject(_leftTabsLastMessageTimeTextByName, parsed.timeTextByName);
      mergeObject(_leftTabsLastMessageTimeTextByTicketId, parsed.timeTextByTicketId);
      mergeObject(_leftTabsLastMessageTsByName, parsed.tsByName);
      mergeObject(_leftTabsLastMessageTsByTicketId, parsed.tsByTicketId);
      if (parsed.openTabs && Array.isArray(parsed.openTabs.order)) {
        _leftTabsOpenOrder = parsed.openTabs.order
          .map((id) => Number(id))
          .filter((id) => Number.isFinite(id) && id > 0);
        const meta = parsed.openTabs.meta || {};
        Object.keys(meta).forEach((k) => {
          const id = Number(k);
          if (Number.isFinite(id) && id > 0) _leftTabsOpenMeta[id] = meta[k];
        });
        const badges = parsed.openTabs.badgeByTicketId || {};
        Object.keys(badges).forEach((k) => {
          const id = Number(k);
          if (Number.isFinite(id) && id > 0) _leftTabsBadgeByTicketId[id] = !!badges[k];
        });
      }
      try {
        localStorage.removeItem(LEFT_TABS_CACHE_KEY_LEGACY_V2);
      } catch (e) {}
    } catch (e) {}
  }
  loadLeftTabsCache();

  function leftTabsFieldLabelIncludes(fieldEl, needle) {
    if (!(fieldEl instanceof Element) || !needle) return false;
    const lab = fieldEl.querySelector('.ticket-fields__field-name, .ticket-user__field-label');
    const t = (lab?.textContent || '').replace(/\s+/g, ' ').trim().toLowerCase();
    return t.includes(String(needle).toLowerCase());
  }

  function extractTicketDepartmentFromPage() {
    const fields = Array.from(document.querySelectorAll('#ticket-app .ticket-fields__field'));
    for (const field of fields) {
      if (!leftTabsFieldLabelIncludes(field, 'департамент')) continue;
      const input = field.querySelector('.ticket-fields__field-input .el-input__inner');
      const v = input ? String(input.value || '').replace(/\s+/g, ' ').trim() : '';
      if (v && v !== 'Выбрать') return v;
      const sel = field.querySelector('.el-select-dropdown__item.selected, .el-select-dropdown__item.is-selected');
      const fromLi = (sel?.textContent || '').replace(/\s+/g, ' ').trim();
      if (fromLi) return fromLi;
    }
    return '';
  }

  function extractTicketClientNameFromPage() {
    const fields = Array.from(document.querySelectorAll('#ticket-app .ticket-user .ticket-user__field'));
    for (const field of fields) {
      if (!leftTabsFieldLabelIncludes(field, 'клиент')) continue;
      const input = field.querySelector('.el-input__inner');
      const v = input ? String(input.value || '').replace(/\s+/g, ' ').trim() : '';
      if (v && !/^поиск/i.test(v)) return v;
      const sel = field.querySelector('.el-select-dropdown__item.selected, .el-select-dropdown__item.is-selected');
      const fromLi = (sel?.textContent || '').replace(/\s+/g, ' ').trim();
      if (fromLi) return fromLi;
    }
    return '';
  }

  function syncLeftTabsAfterNavigationShell() {
    applyThemeFromConfig();
    syncColleagueStatusesModule();
    injectStyle();
    processAllMessages();
    initAutoLoad();
    moveHistoryButton();
  }

  function buildPathToTicket(ticketId) {
    if (!Number.isFinite(ticketId)) return null;
    const path = location.pathname || '';
    if (/\/ticket\/\d+/.test(path)) return path.replace(/\/ticket\/\d+/, `/ticket/${ticketId}`);
    const listWithFilter = path.match(/^(.*\/ticket\/list\/filter\/id\/\d+)/);
    if (listWithFilter) return `${listWithFilter[1]}/ticket/${ticketId}`;
    const locPrefix = path.match(/^(\/[^/]+)/);
    const loc = locPrefix ? locPrefix[1] : '/ru';
    return `${loc}/ticket/list/filter/id/11/ticket/${ticketId}`;
  }

  /** Абсолютный pathname → путь для $router.push (без дубля base, иначе бывает …/list/ru/ticket/list/…). */
  function pathnameForVueRouterPush(router, absolutePathname) {
    const p = String(absolutePathname || '').startsWith('/')
      ? String(absolutePathname)
      : `/${absolutePathname}`;
    let base = router && router.options && router.options.base != null
      ? String(router.options.base)
      : '/';
    if (!base || base === '/') return p;
    base = base.replace(/\/+$/, '');
    if (!base) return p;
    if (p === base || p.startsWith(`${base}/`)) {
      const rest = p.slice(base.length);
      return rest.startsWith('/') ? rest : `/${rest}`;
    }
    return p;
  }

  function navigateToTicketId(ticketId) {
    if (!Number.isFinite(ticketId)) return false;
    if (Number.isFinite(ticketId) && _leftTabsBlockEnsureForClosedId === ticketId) {
      _leftTabsBlockEnsureForClosedId = null;
    }
    const nextPath = buildPathToTicket(ticketId);
    if (!nextPath) return false;
    const nextFull = nextPath + (location.search || '');
    if (`${location.pathname}${location.search}` === nextFull) {
      ensureOpenTicketFromCurrentUrl();
      return true;
    }
    const root = document.querySelector('#ticket-app');
    try {
      const vue = root && root.__vue__;
      if (vue && vue.$router && typeof vue.$router.push === 'function') {
        const routerPath = pathnameForVueRouterPush(vue.$router, nextPath) || '/';
        vue.$router.push(routerPath + (location.search || '')).catch(() => {});
        setTimeout(() => {
          ensureOpenTicketFromCurrentUrl();
          syncLeftTabsMirror();
          syncLeftTabsAfterNavigationShell();
        }, 120);
        return true;
      }
    } catch (e) {}
    try {
      window.history.pushState({}, '', nextFull);
      window.dispatchEvent(new PopStateEvent('popstate', { state: history.state }));
    } catch (e) {
      window.location.assign(nextFull);
      return true;
    }
    ensureOpenTicketFromCurrentUrl();
    _leftTabsLastHrefForSync = location.href;
    setTimeout(() => {
      syncLeftTabsMirror();
      syncLeftTabsAfterNavigationShell();
    }, 80);
    return true;
  }

  function navigateToTicketListHome() {
    const m = location.pathname.match(/^(\/[^/]+)\/ticket\//);
    const prefix = m ? m[1] : '/ru';
    const nextFull = `${prefix}/ticket/list` + (location.search || '');
    try {
      window.history.pushState({}, '', nextFull);
      window.dispatchEvent(new PopStateEvent('popstate', { state: history.state }));
    } catch (e) {
      window.location.assign(nextFull);
      return;
    }
    _leftTabsLastHrefForSync = location.href;
    setTimeout(() => {
      syncLeftTabsMirror();
      syncLeftTabsAfterNavigationShell();
    }, 80);
  }

  function ensureOpenTicketFromCurrentUrl() {
    const tid = getTicketId();
    if (!Number.isFinite(tid)) {
      _leftTabsBlockEnsureForClosedId = null;
      return;
    }
    if (_leftTabsBlockEnsureForClosedId != null) {
      if (tid === _leftTabsBlockEnsureForClosedId) {
        return;
      }
      _leftTabsBlockEnsureForClosedId = null;
    }
    if (!_leftTabsOpenOrder.includes(tid)) _leftTabsOpenOrder.push(tid);
    if (!_leftTabsOpenMeta[tid]) _leftTabsOpenMeta[tid] = { name: '', department: '' };
    const name = extractTicketClientNameFromPage();
    const dep = extractTicketDepartmentFromPage();
    if (name) _leftTabsOpenMeta[tid].name = name;
    if (dep) _leftTabsOpenMeta[tid].department = dep;
    scheduleLeftTabsCacheSave();
  }

  function syncLeftTabsOnHrefChange() {
    if (!CONFIG.leftTabsMirror) {
      _leftTabsLastHrefForSync = location.href;
      return;
    }
    if (location.href === _leftTabsLastHrefForSync) return;
    _leftTabsLastHrefForSync = location.href;
    _loadedPages.clear();
    _historyLoadedForTicketId = null;
    ensureOpenTicketFromCurrentUrl();
    syncLeftTabsMirror();
    scheduleImmediateLeftTabsPreviewPoll();
    processAllMessages();
    initAutoLoad();
  }

  function refreshLeftTabsDepartmentMeta() {
    if (!CONFIG.leftTabsMirror) return;
    const tid = getTicketId();
    if (!Number.isFinite(tid)) return;
    if (!_leftTabsOpenMeta[tid]) _leftTabsOpenMeta[tid] = { name: '', department: '' };
    let changed = false;
    const dep = extractTicketDepartmentFromPage();
    if (dep && _leftTabsOpenMeta[tid].department !== dep) {
      _leftTabsOpenMeta[tid].department = dep;
      changed = true;
    }
    const name = extractTicketClientNameFromPage();
    if (name && _leftTabsOpenMeta[tid].name !== name) {
      _leftTabsOpenMeta[tid].name = name;
      changed = true;
    }
    if (changed) {
      scheduleLeftTabsCacheSave();
      scheduleLeftTabsMirrorSync();
    }
  }

  function inferUnreadBadgeFromConversation(payload, isActive) {
    if (isActive) return false;
    const messages = Array.isArray(payload?.messages) ? payload.messages : [];
    const users = payload?.users || {};
    for (let i = messages.length - 1; i >= 0; i--) {
      const msg = messages[i];
      if (!msg || msg.type === 'comment' || msg.type === 'note') continue;
      const u = users[String(msg.userId)] || {};
      const t = String(u.type || '').toLowerCase();
      if (t === 'user' || t === 'client') return true;
      return false;
    }
    return false;
  }

  function markLeftTabsHydrated(name, ticketId) {
    if (Number.isFinite(ticketId)) _leftTabsHydratedByTicketId[ticketId] = 1;
    const norm = normalizeTabName(name);
    if (norm) _leftTabsHydratedByName[norm] = 1;
  }

  function isLeftTabsHydrated(name, ticketId) {
    if (Number.isFinite(ticketId) && _leftTabsHydratedByTicketId[ticketId]) return true;
    const norm = normalizeTabName(name);
    return !!(norm && _leftTabsHydratedByName[norm]);
  }

  function ensureSeenOrder(name, ticketId, storeKey) {
    const normalizedStoreKey = String(storeKey || '').trim();
    if (normalizedStoreKey) {
      if (_leftTabsSeenOrderByStoreKey[normalizedStoreKey] == null) _leftTabsSeenOrderByStoreKey[normalizedStoreKey] = _leftTabsSeenOrderSeq++;
      return;
    }
    if (Number.isFinite(ticketId)) {
      if (_leftTabsSeenOrderByTicketId[ticketId] == null) _leftTabsSeenOrderByTicketId[ticketId] = _leftTabsSeenOrderSeq++;
      if (_leftTabsSeenOrderByName[name] == null) _leftTabsSeenOrderByName[name] = _leftTabsSeenOrderByTicketId[ticketId];
      return;
    }
    if (_leftTabsSeenOrderByName[name] == null) _leftTabsSeenOrderByName[name] = _leftTabsSeenOrderSeq++;
  }

  function getSeenOrder(name, ticketId, storeKey) {
    const normalizedStoreKey = String(storeKey || '').trim();
    if (normalizedStoreKey && _leftTabsSeenOrderByStoreKey[normalizedStoreKey] != null) {
      return _leftTabsSeenOrderByStoreKey[normalizedStoreKey];
    }
    if (Number.isFinite(ticketId) && _leftTabsSeenOrderByTicketId[ticketId] != null) {
      return _leftTabsSeenOrderByTicketId[ticketId];
    }
    return _leftTabsSeenOrderByName[name] ?? Number.MAX_SAFE_INTEGER;
  }

  function getLeftTabsPreview(name, ticketId) {
    if (Number.isFinite(ticketId)) return _leftTabsPreviewByTicketId[ticketId] || '';
    const byName = name ? (_leftTabsPreviewByName[name] || '') : '';
    return byName || '';
  }

  function setLeftTabsPreview(name, ticketId, preview) {
    if (!preview) return;
    const next = String(preview).trim();
    if (!next) return;
    // Маркер "Новый ответ" используем для UI, но не затираем им кэш реального текста.
    if (next === 'Новый ответ') return;
    if (!Number.isFinite(ticketId)) return;
    if (isLeftTabsCacheSuppressed(name, ticketId)) return;

    let changed = false;
    if (_leftTabsPreviewByTicketId[ticketId] !== next) {
      _leftTabsPreviewByTicketId[ticketId] = next;
      changed = true;
    }
    // Жёсткое правило: новое превью -> сразу в кэш.
    if (changed) {
      // Если превью обновилось раньше, чем пришёл точный message ts из API,
      // ставим "свежий" штамп, чтобы после reload не побеждал старый snapshot.
      const nowTs = Date.now();
      _leftTabsLastMessageTsByTicketId[ticketId] = Math.max(Number(_leftTabsLastMessageTsByTicketId[ticketId] || 0), nowTs);
      flushLeftTabsCacheNow();
    }
  }

  function getLeftTabsTimeText(name, ticketId) {
    if (Number.isFinite(ticketId)) return _leftTabsLastMessageTimeTextByTicketId[ticketId] || '';
    const byName = name ? (_leftTabsLastMessageTimeTextByName[name] || '') : '';
    return byName || '';
  }

  function setLeftTabsTimeText(name, ticketId, timeText) {
    if (!timeText) return;
    if (!Number.isFinite(ticketId)) return;
    if (isLeftTabsCacheSuppressed(name, ticketId)) return;
    _leftTabsLastMessageTimeTextByTicketId[ticketId] = timeText;
    scheduleLeftTabsCacheSave();
  }

  function getLeftTabsTs(name, ticketId) {
    if (!Number.isFinite(ticketId)) return 0;
    return Number(_leftTabsLastMessageTsByTicketId[ticketId] || 0);
  }

  function setLeftTabsTs(name, ticketId, ts) {
    if (!Number.isFinite(ts) || ts <= 0) return;
    if (!Number.isFinite(ticketId)) return;
    if (isLeftTabsCacheSuppressed(name, ticketId)) return;
    _leftTabsLastMessageTsByTicketId[ticketId] = ts;
    scheduleLeftTabsCacheSave();
  }

  function syncLeftTabsCacheFromEntries(entries) {
    for (const entry of entries || []) {
      if (!entry) continue;
      const preview = String(entry.preview || '').trim();
      if (preview && preview !== 'Новый ответ') {
        setLeftTabsPreview(entry.name, entry.ticketId, preview);
      }
      const timeText = String(entry.lastTimeText || '').trim();
      if (timeText) {
        setLeftTabsTimeText(entry.name, entry.ticketId, timeText);
      }
      const ts = Number(entry.lastMessageTs || 0);
      if (Number.isFinite(ts) && ts > 0) {
        setLeftTabsTs(entry.name, entry.ticketId, ts);
      }
    }
  }

  function sortLeftTabsEntries(entries) {
    entries.sort((a, b) => {
      const aTs = Number(a.lastMessageTs || getLeftTabsTs(a.name, a.ticketId) || 0);
      const bTs = Number(b.lastMessageTs || getLeftTabsTs(b.name, b.ticketId) || 0);
      if (aTs !== bTs) return bTs - aTs;
      const aSeen = getSeenOrder(a.name, a.ticketId, a.storeKey);
      const bSeen = getSeenOrder(b.name, b.ticketId, b.storeKey);
      return aSeen - bSeen;
    });
    return entries;
  }

  function getLeftTabsSignature(entries) {
    return entries.map((entry, idx) => {
      const isActive = entry.isActive ? '1' : '0';
      const hasBadge = entry.hasBadge ? '1' : '0';
      const tid = Number.isFinite(entry.ticketId) ? entry.ticketId : '';
      const dep = entry.department || '';
      return `${idx}:${tid}:${isActive}:${hasBadge}:${entry.name}:${dep}:${entry.preview || ''}:${entry.lastTimeText || ''}`;
    }).join('|');
  }

  function escapeHtml(value) {
    return String(value ?? '')
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  function isRedLikeColor(color) {
    if (!color) return false;
    const c = String(color).toLowerCase();
    if (c.includes('f56c6c') || c.includes('fb0a0a') || c.includes('ff0000')) return true;
    const m = c.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
    if (!m) return false;
    const r = Number(m[1]); const g = Number(m[2]); const b = Number(m[3]);
    return r >= 170 && g <= 120 && b <= 120;
  }

  function extractDateTimeText(value) {
    const str = String(value || '');
    const full = str.match(/\b(\d{1,2}\.\d{1,2}\.\d{2,4}\s+\d{1,2}:\d{2}(?::\d{2})?)\b/);
    if (full) return full[1];
    const hm = str.match(/\b(\d{1,2}:\d{2})\b/);
    return hm ? hm[1] : '';
  }

  function parseMessageDateToTs(value) {
    if (!value) return 0;
    if (Number.isFinite(value)) return Number(value);
    const str = String(value).trim();
    const full = str.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})\s+(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
    if (full) {
      let year = Number(full[3]);
      if (year < 100) year += 2000;
      const d = new Date(year, Number(full[2]) - 1, Number(full[1]), Number(full[4]), Number(full[5]), Number(full[6] || 0));
      const ts = d.getTime();
      return Number.isFinite(ts) ? ts : 0;
    }
    const hm = str.match(/^(\d{1,2}):(\d{2})$/);
    if (hm) {
      const now = new Date();
      const d = new Date(now.getFullYear(), now.getMonth(), now.getDate(), Number(hm[1]), Number(hm[2]), 0);
      const ts = d.getTime();
      return Number.isFinite(ts) ? ts : 0;
    }
    const fallback = Date.parse(str);
    return Number.isFinite(fallback) ? fallback : 0;
  }

  function formatMessageTimeLabel(value) {
    const str = String(value || '').trim();
    if (!str) return '';
    const hm = str.match(/\b(\d{1,2}:\d{2})\b/);
    return hm ? hm[1] : str;
  }

  function extractCurrentTicketPreviewMeta() {
    const bubbles = Array.from(document.querySelectorAll('#ticket-app .ticket-conversation__messages .ticket-conversation__message .ticket-conversation__message-html'));
    for (let i = bubbles.length - 1; i >= 0; i--) {
      const bubble = bubbles[i];
      if (!bubble) continue;
      const clone = bubble.cloneNode(true);
      clone.querySelectorAll('.hde-name-inside, .hde-time-inside, .hde-edited-inside, .hde-actions-inline, .ticket-conversation__message-updated').forEach((el) => el.remove());
      const txt = clone.textContent?.replace(/\s+/g, ' ').trim();
      const msgEl = bubble.closest('.ticket-conversation__message');
      const hasFiles = !!msgEl?.querySelector('.ticket-conversation__message-files .ticket-conversation__message-file');
      const timeInside = msgEl?.querySelector('.hde-time-inside')?.textContent?.trim() || '';
      const metaRaw = msgEl?.querySelector('.ticket-conversation__message-meta')?.textContent || '';
      const dateText = extractDateTimeText(metaRaw) || extractDateTimeText(timeInside);
      const timeText = formatMessageTimeLabel(dateText || timeInside);
      const ts = parseMessageDateToTs(dateText || timeInside);
      if (hasFiles && (!txt || txt === '_')) {
        return { preview: FILE_ONLY_PREVIEW, timeText, ts };
      }
      if (!txt) continue;
      return {
        preview: txt.length > 140 ? `${txt.slice(0, 140)}…` : txt,
        timeText,
        ts
      };
    }
    return null;
  }

  function htmlToPlainText(html) {
    if (!html) return '';
    const div = document.createElement('div');
    div.innerHTML = String(html);
    return (div.textContent || '').replace(/\s+/g, ' ').trim();
  }

  function pickLatestPreviewFromConversation(payload) {
    const messages = Array.isArray(payload?.messages) ? payload.messages : [];
    // API обычно отдает сообщения в хронологическом порядке (старые -> новые),
    // поэтому идем с конца, чтобы взять последнее актуальное сообщение.
    for (let i = messages.length - 1; i >= 0; i--) {
      const msg = messages[i];
      const txt = htmlToPlainText(msg?.text || '');
      const hasFiles = Array.isArray(msg?.files) && msg.files.length > 0;
      const rawTime = msg?.createdAt || msg?.date || msg?.created_at || '';
      const timeText = formatMessageTimeLabel(rawTime);
      const ts = parseMessageDateToTs(rawTime);
      if (hasFiles && (!txt || txt === '_')) {
        return { preview: FILE_ONLY_PREVIEW, timeText, ts };
      }
      if (txt) {
        return {
          preview: txt.length > 140 ? `${txt.slice(0, 140)}…` : txt,
          timeText,
          ts
        };
      }
    }
    return null;
  }

  function normalizeTabName(name) {
    return String(name || '').replace(/\s+/g, ' ').trim().toLowerCase();
  }

  function normalizeLooseTabName(name) {
    return normalizeTabName(name)
      .replace(/[.…]+$/g, '')
      .replace(/[^\p{L}\p{N}\s-]/gu, '')
      .trim();
  }

  // Ранее здесь был парсер нативных вкладок/Vue-состояния.
  // Удален, т.к. панель теперь полностью автономна и не зеркалит HDE tabs.

  /**
   * Единая разметка #ticket-app: колонка зеркала вставляется между sidebar и чатом.
   */
  function findTicketMetroLayout() {
    const metroContainer = Array.from(document.querySelectorAll('section.el-container.metro-padding'))
      .find((el) => el.querySelector('.ticket-sidebar') && el.querySelector('section.el-container.ticket-container'));
    if (!metroContainer) return null;
    const sidebar = metroContainer.querySelector('.ticket-sidebar');
    const ticketContainer = metroContainer.querySelector('section.el-container.ticket-container');
    if (!sidebar || !ticketContainer) return null;
    return { metroContainer, sidebar, ticketContainer };
  }

  function ensureLeftTabsColumnInLayout(metroContainer, ticketContainer) {
    let column = document.getElementById(LEFT_TABS_COLUMN_ID);
    if (!column) {
      column = document.createElement('div');
      column.id = LEFT_TABS_COLUMN_ID;
      column.className = 'hde-left-tabs-column';
    }
    if (column.parentElement !== metroContainer || column.nextElementSibling !== ticketContainer) {
      metroContainer.insertBefore(column, ticketContainer);
    }
    return column;
  }

  function leftTabsLooksLikeNativeTabsVm(vm) {
    if (!vm || typeof vm !== 'object') return false;
    const tabs = vm.ticketTabs;
    if (!Array.isArray(tabs)) return false;
    return tabs.every((tab) => tab && typeof tab === 'object' && 'id' in tab && 'type' in tab);
  }

  function getLeftTabsNativeTabsVm() {
    if (leftTabsLooksLikeNativeTabsVm(_leftTabsNativeTabsVm)) return _leftTabsNativeTabsVm;
    const root = document.querySelector('.ticket-topbar__tabs');
    if (!(root instanceof Element)) return null;
    const queue = [];
    if (root.__vue__) queue.push(root.__vue__);
    if (root.__vueParentComponent?.proxy) queue.push(root.__vueParentComponent.proxy);
    let cur = root.parentElement;
    let depth = 0;
    while (cur && depth < 6) {
      if (cur.__vue__) queue.push(cur.__vue__);
      if (cur.__vueParentComponent?.proxy) queue.push(cur.__vueParentComponent.proxy);
      cur = cur.parentElement;
      depth += 1;
    }
    const visited = new WeakSet();
    while (queue.length) {
      const node = queue.shift();
      if (!node || typeof node !== 'object') continue;
      if (visited.has(node)) continue;
      visited.add(node);
      if (leftTabsLooksLikeNativeTabsVm(node)) {
        _leftTabsNativeTabsVm = node;
        return node;
      }
      const buckets = [node.$children, node.$parent, node.$root, node.$refs, node._provided];
      for (const bucket of buckets) {
        if (!bucket) continue;
        if (Array.isArray(bucket)) {
          bucket.forEach((child) => { if (child && typeof child === 'object') queue.push(child); });
        } else if (typeof bucket === 'object') {
          Object.values(bucket).forEach((child) => { if (child && typeof child === 'object') queue.push(child); });
        }
      }
    }
    return null;
  }

  function collectNativeTicketTabs() {
    const vm = getLeftTabsNativeTabsVm();
    const tabs = Array.isArray(vm?.ticketTabs) ? vm.ticketTabs : [];
    return tabs
      .filter((tab) => tab && typeof tab === 'object' && String(tab.type) === 'ticket')
      .map((tab) => {
        const id = Number(tab.id);
        return {
          id: Number.isFinite(id) && id > 0 ? id : null,
          type: String(tab.type || 'ticket'),
          title: String(tab.title || '').trim(),
          updated: !!tab.updated
        };
      })
      .filter((tab) => Number.isFinite(tab.id));
  }

  function syncOpenOrderFromNativeTabs(currentTicketId) {
    const nativeTabs = collectNativeTicketTabs();
    if (!nativeTabs.length) {
      if (Number.isFinite(currentTicketId) && !_leftTabsOpenOrder.includes(currentTicketId)) {
        _leftTabsOpenOrder.push(currentTicketId);
        scheduleLeftTabsCacheSave();
      }
      return [];
    }
    const ids = nativeTabs.map((tab) => tab.id);
    const changed = ids.length !== _leftTabsOpenOrder.length
      || ids.some((id, idx) => id !== _leftTabsOpenOrder[idx]);
    if (changed) {
      _leftTabsOpenOrder = ids.slice();
      scheduleLeftTabsCacheSave();
    }
    const badgeRaisedIds = [];
    nativeTabs.forEach((tab) => {
      if (!_leftTabsOpenMeta[tab.id]) _leftTabsOpenMeta[tab.id] = { name: '', department: '' };
      if (tab.title) _leftTabsOpenMeta[tab.id].name = tab.title;
      const prevBadge = !!_leftTabsBadgeByTicketId[tab.id];
      _leftTabsBadgeByTicketId[tab.id] = !!tab.updated;
      if (!prevBadge && !!tab.updated) badgeRaisedIds.push(tab.id);
    });
    badgeRaisedIds.forEach((ticketId) => {
      scheduleImmediateLeftTabsPreviewPollForTicket(ticketId);
    });
    return nativeTabs;
  }

  function normalizeLeftTabsOpenOrder() {
    const normalized = [];
    const seen = new Set();
    for (const idRaw of _leftTabsOpenOrder) {
      const id = Number(idRaw);
      if (!Number.isFinite(id) || id <= 0) continue;
      if (seen.has(id)) continue;
      seen.add(id);
      normalized.push(id);
    }
    if (normalized.length !== _leftTabsOpenOrder.length
      || normalized.some((id, idx) => id !== _leftTabsOpenOrder[idx])) {
      _leftTabsOpenOrder = normalized;
      scheduleLeftTabsCacheSave();
    }
  }

  function getNextTicketIdAfterClose(closingTicketId) {
    const orderCopy = _leftTabsOpenOrder.slice();
    const idx = orderCopy.indexOf(closingTicketId);
    if (idx < 0) return null;
    return orderCopy[idx + 1] ?? orderCopy[idx - 1] ?? null;
  }

  function closeTicketViaNativeBridge(ticketId) {
    const vm = getLeftTabsNativeTabsVm();
    if (!vm || typeof vm.removeTab !== 'function' || !Array.isArray(vm.ticketTabs)) return false;
    const nativeTab = vm.ticketTabs.find((tab) => Number(tab?.id) === Number(ticketId) && String(tab?.type) === 'ticket');
    if (!nativeTab) return false;
    try {
      vm.removeTab(nativeTab);
      return true;
    } catch (e) {
      return false;
    }
  }

  function collectTicketTabEntries() {
    const currentTicketId = getTicketId();
    ensureOpenTicketFromCurrentUrl();
    const nativeTabs = syncOpenOrderFromNativeTabs(currentTicketId);
    normalizeLeftTabsOpenOrder();
    const nativeById = Object.create(null);
    nativeTabs.forEach((tab) => { nativeById[tab.id] = tab; });

    const entries = _leftTabsOpenOrder
      .filter((ticketId) => Number.isFinite(ticketId) && ticketId > 0)
      .map((ticketId) => {
        const nativeTab = nativeById[ticketId] || null;
        const meta = _leftTabsOpenMeta[ticketId] || {};
        const nativeTitle = String(nativeTab?.title || '').trim();
        const name = nativeTitle || (meta.name && String(meta.name).trim()) || `Заявка ${ticketId}`;
        const department = String(meta.department || '').trim();
        const isActive = Number.isFinite(currentTicketId) && ticketId === currentTicketId;
        const hasBadge = nativeTab ? !!nativeTab.updated : !!_leftTabsBadgeByTicketId[ticketId];
        _leftTabsBadgeByTicketId[ticketId] = hasBadge;
        const liveMeta = isActive ? extractCurrentTicketPreviewMeta() : null;
        const cachedPreview = getLeftTabsPreview(name, ticketId);
        const preview = liveMeta?.preview
          || cachedPreview
          || (hasBadge ? 'Новый ответ' : '');
        setLeftTabsPreview(name, ticketId, preview);
        if (liveMeta?.timeText) setLeftTabsTimeText(name, ticketId, liveMeta.timeText);
        if (liveMeta?.ts) setLeftTabsTs(name, ticketId, liveMeta.ts);

        const storeKey = `id:${ticketId}`;
        ensureSeenOrder(name, ticketId, storeKey);
        return {
          source: 'registry',
          domUid: '',
          storeKey,
          name,
          department,
          ticketId,
          isActive,
          hasBadge,
          preview,
          lastTimeText: getLeftTabsTimeText(name, ticketId),
          lastMessageTs: getLeftTabsTs(name, ticketId),
          onOpen: () => {
            navigateToTicketId(ticketId);
          },
          onClose: () => {
            const wasActive = getTicketId() === ticketId;
            const nextId = getNextTicketIdAfterClose(ticketId);
            if (closeTicketViaNativeBridge(ticketId)) {
              clearLeftTabsCacheForEntry({ name, ticketId });
              scheduleLeftTabsMirrorSync();
              return;
            }
            clearLeftTabsCacheForEntry({ name, ticketId });
            if (wasActive) {
              _leftTabsBlockEnsureForClosedId = ticketId;
              if (Number.isFinite(nextId)) navigateToTicketId(nextId);
              else navigateToTicketListHome();
            }
            scheduleLeftTabsMirrorSync();
          }
        };
      });

    return sortLeftTabsEntries(entries);
  }

  function scheduleLeftTabsMirrorSync() {
    if (!CONFIG.leftTabsMirror || _leftTabsMirrorSyncScheduled) return;
    _leftTabsMirrorSyncScheduled = true;
    requestAnimationFrame(() => {
      _leftTabsMirrorSyncScheduled = false;
      syncLeftTabsMirror();
    });
  }

  function scheduleImmediateLeftTabsPreviewPoll() {
    if (!CONFIG.leftTabsMirror || _leftTabsPreviewPollForceScheduled) return;
    _leftTabsPreviewPollForceScheduled = true;
    requestAnimationFrame(() => {
      _leftTabsPreviewPollForceScheduled = false;
      pollLeftTabsPreviews(true);
    });
  }

  function scheduleImmediateLeftTabsPreviewPollForTicket(ticketId) {
    if (!Number.isFinite(ticketId) || ticketId <= 0) return;
    _leftTabsForcedPreviewTicketIds.add(ticketId);
    scheduleImmediateLeftTabsPreviewPoll();
  }

  function clickNativeCloseAllTabs() {
    const nativeCloseAllBtn = document.querySelector('.ticket-tabs__close-all, .ticket-tabs__more-close-all');
    if (!(nativeCloseAllBtn instanceof HTMLElement)) return false;
    nativeCloseAllBtn.click();
    return true;
  }

  function clickNativeCloseAllConfirm() {
    const candidates = Array.from(document.querySelectorAll('.el-popover .el-button.el-button--primary.el-button--mini, .el-popconfirm .el-button.el-button--primary.el-button--mini'));
    const confirmBtn = candidates.find((btn) => /закрыть/i.test((btn.textContent || '').trim()));
    if (!(confirmBtn instanceof HTMLElement)) return false;
    confirmBtn.click();
    return true;
  }

  function closeAllTabsFromMirror() {
    const openedBefore = _leftTabsOpenOrder
      .map((id) => Number(id))
      .filter((id) => Number.isFinite(id) && id > 0);

    let nativeCloseTriggered = false;
    const vm = getLeftTabsNativeTabsVm();
    if (vm && typeof vm.removeTab === 'function' && Array.isArray(vm.ticketTabs)) {
      const nativeTicketTabs = vm.ticketTabs
        .filter((tab) => Number.isFinite(Number(tab?.id)) && String(tab?.type) === 'ticket')
        .slice();
      nativeTicketTabs.forEach((tab) => {
        try {
          vm.removeTab(tab);
          nativeCloseTriggered = true;
        } catch (e) {}
      });
    }

    if (!nativeCloseTriggered && clickNativeCloseAllTabs()) {
      nativeCloseTriggered = true;
      setTimeout(() => { clickNativeCloseAllConfirm(); }, 80);
      setTimeout(() => { clickNativeCloseAllConfirm(); }, 220);
    }

    if (nativeCloseTriggered) {
      navigateToTicketListHome();
      setTimeout(() => {
        const remainingIds = new Set(
          collectNativeTicketTabs()
            .map((tab) => Number(tab.id))
            .filter((id) => Number.isFinite(id) && id > 0)
        );
        if (remainingIds.size === 0) {
          clearLeftTabsCacheAll();
        } else {
          openedBefore.forEach((id) => {
            if (remainingIds.has(id)) return;
            const meta = _leftTabsOpenMeta[id] || {};
            clearLeftTabsCacheForEntry({ ticketId: id, name: meta.name || '' });
          });
        }
        scheduleLeftTabsMirrorSync();
      }, 260);
      return;
    }

    // Fallback: если нативный close-all недоступен, не стираем всё без фактического закрытия.
    navigateToTicketListHome();
    scheduleLeftTabsMirrorSync();
  }

  function leftTabsIsCaptchaLikely() {
    const href = String(location.href || '');
    if (/captcha|recaptcha|hcaptcha/i.test(href)) return true;
    const title = String(document.title || '');
    if (/captcha|капча|я не робот/i.test(title)) return true;
    return false;
  }

  function markLeftTabsPollError(err) {
    const now = Date.now();
    _leftTabsPreviewErrorStreak += 1;
    const backoff = Math.min(
      LEFT_TABS_ERROR_MAX_BACKOFF_MS,
      LEFT_TABS_ERROR_BASE_BACKOFF_MS * Math.pow(2, Math.min(_leftTabsPreviewErrorStreak, 5))
    );
    _leftTabsPreviewBackoffUntil = now + backoff;
    const msg = String(err?.message || err || '');
    const status = Number(err?.status || 0);
    const url = String(err?.url || '');
    if (status === 403 || status === 429 || /captcha|recaptcha|hcaptcha/i.test(`${msg} ${url}`)) {
      _leftTabsCaptchaCooldownUntil = now + LEFT_TABS_CAPTCHA_COOLDOWN_MS;
    }
  }

  function markLeftTabsPollSuccess() {
    _leftTabsPreviewErrorStreak = 0;
    _leftTabsPreviewBackoffUntil = 0;
  }

  function pruneLeftTabsRecentRequests(now = Date.now()) {
    const edge = now - 60 * 1000;
    while (_leftTabsRecentRequestTs.length && _leftTabsRecentRequestTs[0] < edge) {
      _leftTabsRecentRequestTs.shift();
    }
  }

  function canLeftTabsDoRequest(now = Date.now()) {
    pruneLeftTabsRecentRequests(now);
    return _leftTabsRecentRequestTs.length < LEFT_TABS_MAX_REQUESTS_PER_MINUTE;
  }

  function markLeftTabsRequest(now = Date.now()) {
    pruneLeftTabsRecentRequests(now);
    _leftTabsRecentRequestTs.push(now);
  }

  async function pollLeftTabsPreviews(force = false) {
    if (!CONFIG.leftTabsMirror) return;
    if (_leftTabsPreviewPollInFlight) {
      if (force) _leftTabsPreviewPollForcePending = true;
      return;
    }
    const now = Date.now();
    if (_leftTabsCaptchaCooldownUntil > now) return;
    if (_leftTabsPreviewBackoffUntil > now) return;
    if (!force && document.hidden) return;
    if (leftTabsIsCaptchaLikely()) {
      _leftTabsCaptchaCooldownUntil = now + LEFT_TABS_CAPTCHA_COOLDOWN_MS;
      return;
    }
    const minGap = force ? LEFT_TABS_PREVIEW_FORCE_MIN_GAP_MS : LEFT_TABS_PREVIEW_MIN_GAP_MS;
    if ((now - _leftTabsPreviewLastRunAt) < minGap) return;
    _leftTabsPreviewLastRunAt = now;
    _leftTabsPreviewPollInFlight = true;
    try {
      const entries = collectTicketTabEntries();
      const known = entries.filter((e) => Number.isFinite(e.ticketId));
      if (!known.length) return;

      // Активный тикет читаем прямо из DOM (extractCurrentTicketPreviewMeta).
      // Приоритет №1: принудительный точечный тикет (когда badge поднялся только у него).
      const forcedTargets = [];
      if (_leftTabsForcedPreviewTicketIds.size > 0) {
        for (const forcedId of _leftTabsForcedPreviewTicketIds) {
          const forcedEntry = known.find((e) => e.ticketId === forcedId && !e.isActive);
          if (forcedEntry) forcedTargets.push(forcedEntry);
        }
      }
      const targets = forcedTargets.length
        ? forcedTargets
        : known.filter((e) => e.hasBadge && !e.isActive);
      if (!targets.length) return;

      const nowTs = Date.now();
      const dueTargets = forcedTargets.length
        ? forcedTargets
        : targets
          .filter((e) => {
            const lastAt = Number(_leftTabsLastPollAtByTicketId[e.ticketId] || 0);
            if (!lastAt) return true;
            return (nowTs - lastAt) >= LEFT_TABS_PER_TICKET_MIN_GAP_MS;
          })
          .sort((a, b) => {
            const aLast = Number(_leftTabsLastPollAtByTicketId[a.ticketId] || 0);
            const bLast = Number(_leftTabsLastPollAtByTicketId[b.ticketId] || 0);
            return aLast - bLast;
          });
      if (!dueTargets.length) return;

      let changed = false;
      const maxRequestsThisRun = Math.max(1, LEFT_TABS_MAX_REQUESTS_PER_RUN);
      let requestsDone = 0;
      for (const entry of dueTargets) {
        if (requestsDone >= maxRequestsThisRun) break;
        if (!canLeftTabsDoRequest()) break;
        try {
          markLeftTabsRequest();
          const payload = await fetchConversationPage(entry.ticketId, 1);
          requestsDone += 1;
          _leftTabsLastPollAtByTicketId[entry.ticketId] = Date.now();
          _leftTabsForcedPreviewTicketIds.delete(entry.ticketId);
          const latestMeta = pickLatestPreviewFromConversation(payload);
          markLeftTabsHydrated(entry.name, entry.ticketId);
          const latest = latestMeta?.preview || '';
          if (latest) {
            const prevByIdPreview = Number.isFinite(entry.ticketId) ? String(_leftTabsPreviewByTicketId[entry.ticketId] || '') : '';
            setLeftTabsPreview(entry.name, entry.ticketId, latest);
            if (prevByIdPreview !== latest) changed = true;
          }
          if (latestMeta?.timeText) {
            const prevByIdTimeText = Number.isFinite(entry.ticketId) ? String(_leftTabsLastMessageTimeTextByTicketId[entry.ticketId] || '') : '';
            setLeftTabsTimeText(entry.name, entry.ticketId, latestMeta.timeText);
            if (prevByIdTimeText !== latestMeta.timeText) changed = true;
          }
          if (latestMeta?.ts) {
            const prevByIdTs = Number.isFinite(entry.ticketId) ? Number(_leftTabsLastMessageTsByTicketId[entry.ticketId] || 0) : 0;
            setLeftTabsTs(entry.name, entry.ticketId, latestMeta.ts);
            if (prevByIdTs !== latestMeta.ts) changed = true;
          }
          const nextBadge = inferUnreadBadgeFromConversation(payload, !!entry.isActive);
          if (_leftTabsBadgeByTicketId[entry.ticketId] !== nextBadge) {
            _leftTabsBadgeByTicketId[entry.ticketId] = nextBadge;
            changed = true;
          }
        } catch (e) {
          _leftTabsForcedPreviewTicketIds.delete(entry.ticketId);
          markLeftTabsPollError(e);
        }
      }
      if (requestsDone > 0) {
        markLeftTabsPollSuccess();
      }
      if (changed) {
        flushLeftTabsCacheNow();
      }
      // Рендерим каждую секунду: актуализируем preview/department даже без API-дельты.
      scheduleLeftTabsMirrorSync();
    } finally {
      _leftTabsPreviewPollInFlight = false;
      if (_leftTabsPreviewPollForcePending) {
        _leftTabsPreviewPollForcePending = false;
        setTimeout(() => {
          pollLeftTabsPreviews(true);
        }, LEFT_TABS_PREVIEW_FORCE_MIN_GAP_MS);
      }
    }
  }

  function syncLeftTabsPreviewPolling() {
    if (!CONFIG.leftTabsMirror) {
      if (_leftTabsPreviewPollInterval) {
        clearInterval(_leftTabsPreviewPollInterval);
        _leftTabsPreviewPollInterval = null;
      }
      _leftTabsForcedPreviewTicketIds.clear();
      _leftTabsPreviewLastRunAt = 0;
      return;
    }
    if (!_leftTabsPreviewPollInterval) {
      _leftTabsPreviewPollInterval = setInterval(pollLeftTabsPreviews, LEFT_TABS_PREVIEW_POLL_MS);
      pollLeftTabsPreviews(true);
      return;
    }
    if ((Date.now() - _leftTabsPreviewLastRunAt) > LEFT_TABS_PREVIEW_POLL_MS * 2) {
      pollLeftTabsPreviews(true);
    }
  }

  function syncLeftTabsDepartmentPolling() {
    if (!CONFIG.leftTabsMirror) {
      if (_leftTabsDepartmentPollInterval) {
        clearInterval(_leftTabsDepartmentPollInterval);
        _leftTabsDepartmentPollInterval = null;
      }
      return;
    }
    if (!_leftTabsDepartmentPollInterval) {
      _leftTabsDepartmentPollInterval = setInterval(refreshLeftTabsDepartmentMeta, LEFT_TABS_DEPARTMENT_REFRESH_MS);
      refreshLeftTabsDepartmentMeta();
    }
  }

  function syncLeftTabsMirror() {
    if (_leftTabsMirrorSyncInProgress) {
      _leftTabsMirrorSyncPending = true;
      return;
    }
    syncNativeTicketTabsVisibilityClass();
    if (!CONFIG.leftTabsMirror) {
      removeLeftTabsMirror();
      _leftTabsMirrorLastSignature = '';
      syncLeftTabsPreviewPolling();
      syncLeftTabsDepartmentPolling();
      return;
    }

    const layout = findTicketMetroLayout();
    if (!layout) {
      removeLeftTabsMirror();
      _leftTabsMirrorLastSignature = '';
      syncLeftTabsPreviewPolling();
      syncLeftTabsDepartmentPolling();
      return;
    }
    const { metroContainer, ticketContainer } = layout;

    const entries = collectTicketTabEntries();
    if (!entries.length) {
      removeLeftTabsMirror();
      _leftTabsMirrorLastSignature = '';
      syncLeftTabsPreviewPolling();
      syncLeftTabsDepartmentPolling();
      return;
    }
    syncLeftTabsCacheFromEntries(entries);

    const signature = getLeftTabsSignature(entries);
    const mirror = document.getElementById(LEFT_TABS_MIRROR_ID);
    if (mirror && signature === _leftTabsMirrorLastSignature) {
      const col = ensureLeftTabsColumnInLayout(metroContainer, ticketContainer);
      if (mirror.parentElement !== col) col.appendChild(mirror);
      syncLeftTabsPreviewPolling();
      syncLeftTabsDepartmentPolling();
      return;
    }

    _leftTabsMirrorSyncInProgress = true;
    try {
      const column = ensureLeftTabsColumnInLayout(metroContainer, ticketContainer);
      let mirrorEl = document.getElementById(LEFT_TABS_MIRROR_ID);
      if (!mirrorEl) {
        mirrorEl = document.createElement('div');
        mirrorEl.id = LEFT_TABS_MIRROR_ID;
        mirrorEl.className = 'hde-left-tabs-mirror';
        mirrorEl.innerHTML = `
        <div class="hde-left-tabs-mirror__title">
          <span class="hde-left-tabs-mirror__title-text">Тикеты</span>
          <button type="button" class="hde-left-tabs-mirror__close-all" title="Закрыть все тикеты" aria-label="Закрыть все тикеты">✕</button>
        </div>
        <div class="hde-left-tabs-mirror__list"></div>
      `;
        column.appendChild(mirrorEl);
        const closeAllBtn = mirrorEl.querySelector('.hde-left-tabs-mirror__close-all');
        closeAllBtn?.addEventListener('click', (e) => {
          e.stopPropagation();
          closeAllTabsFromMirror();
        });
      } else if (mirrorEl.parentElement !== column) {
        column.appendChild(mirrorEl);
      }
      mirrorEl.className = 'hde-left-tabs-mirror';

      const titleEl = mirrorEl.querySelector('.hde-left-tabs-mirror__title');
      if (titleEl && !titleEl.querySelector('.hde-left-tabs-mirror__close-all')) {
        const rawTitle = (titleEl.textContent || '').trim() || 'Тикеты';
        titleEl.innerHTML = `
        <span class="hde-left-tabs-mirror__title-text">${escapeHtml(rawTitle)}</span>
        <button type="button" class="hde-left-tabs-mirror__close-all" title="Закрыть все тикеты" aria-label="Закрыть все тикеты">✕</button>
      `;
        titleEl.querySelector('.hde-left-tabs-mirror__close-all')?.addEventListener('click', (e) => {
          e.stopPropagation();
          closeAllTabsFromMirror();
        });
      }

      const list = mirrorEl.querySelector('.hde-left-tabs-mirror__list');
      if (!list) {
        return;
      }
      list.innerHTML = '';
      const duplicateNameCount = entries.reduce((acc, entry) => {
        const key = normalizeTabName(entry.name || '');
        if (!key) return acc;
        acc[key] = (acc[key] || 0) + 1;
        return acc;
      }, Object.create(null));

      entries.forEach((entry) => {
        const normName = normalizeTabName(entry.name || '');
        const hasDuplicateName = normName && duplicateNameCount[normName] > 1;
        const displayName = hasDuplicateName && Number.isFinite(entry.ticketId)
          ? `${entry.name} #${entry.ticketId}`
          : entry.name;
        const item = document.createElement('button');
        item.type = 'button';
        item.className = `hde-left-tabs-mirror__item${entry.isActive ? ' is-active' : ''}`;
        item.innerHTML = `
        <span class="hde-left-tabs-mirror__indicator${entry.hasBadge ? ' has-badge' : ''}" aria-hidden="true"></span>
        <span class="hde-left-tabs-mirror__content">
          <span class="hde-left-tabs-mirror__head">
            <span class="hde-left-tabs-mirror__name">${escapeHtml(displayName)}</span>
            <span class="hde-left-tabs-mirror__time">${escapeHtml(entry.lastTimeText || '')}</span>
          </span>
          <span class="hde-left-tabs-mirror__department">${escapeHtml(String(entry.department || '').trim())}</span>
          <span class="hde-left-tabs-mirror__preview">${escapeHtml(entry.preview || (entry.hasBadge ? 'Новый ответ' : ''))}</span>
        </span>
        <span class="hde-left-tabs-mirror__close" aria-hidden="true" role="button" tabindex="0">✕</span>
      `;
        item.addEventListener('click', (e) => {
          if (e.target instanceof Element
            && e.target.closest('.hde-left-tabs-mirror__close')) {
            return;
          }
          entry.onOpen?.();
        });

        const close = item.querySelector('.hde-left-tabs-mirror__close');
        close?.addEventListener('click', (e) => {
          e.stopPropagation();
          e.preventDefault();
          entry.onClose?.();
        });

        list.appendChild(item);
      });
      _leftTabsMirrorLastSignature = signature;
    } finally {
      _leftTabsMirrorSyncInProgress = false;
      if (_leftTabsMirrorSyncPending) {
        _leftTabsMirrorSyncPending = false;
        requestAnimationFrame(() => {
          syncLeftTabsMirror();
        });
      } else {
        syncLeftTabsPreviewPolling();
        syncLeftTabsDepartmentPolling();
      }
    }
  }

  function initLeftTabsMirrorObserver() {
    if (window.__hdeLeftTabsMirrorObserver) return;
    window.__hdeLeftTabsMirrorObserver = true;

    const onLocationMaybeChanged = () => {
      syncLeftTabsOnHrefChange();
    };
    window.addEventListener('popstate', onLocationMaybeChanged);
    window.addEventListener('hashchange', onLocationMaybeChanged);

    // Vue-router часто делает history.pushState без popstate — ловим расхождение href.
    if (!window.__hdeLeftTabsHrefPollInterval) {
      window.__hdeLeftTabsHrefPollInterval = setInterval(() => {
        if (location.href !== _leftTabsLastHrefForSync) onLocationMaybeChanged();
      }, 400);
    }

    if (!window.__hdeLeftTabsMirrorClickBound) {
      window.__hdeLeftTabsMirrorClickBound = true;
      document.addEventListener('click', (e) => {
        const target = e.target;
        if (!(target instanceof Element)) return;
        if (target.closest('.hde-left-tabs-mirror__item')) {
          setTimeout(scheduleLeftTabsMirrorSync, 0);
          setTimeout(scheduleImmediateLeftTabsPreviewPoll, 0);
        }
      });
    }
  }

  // ============================================================
  // 5.1) Staffs Drawer
  // ============================================================

  function applyStaffsFrameTypography(frame) {
    const doc = frame?.contentDocument;
    if (!doc?.head) return;
    if (doc.getElementById('hde-staffs-frame-font-style')) return;
    const style = doc.createElement('style');
    style.id = 'hde-staffs-frame-font-style';
    style.textContent = `
      body,
      input,
      textarea,
      select,
      button,
      .el-input__inner,
      .el-select-dropdown__item,
      .el-tag,
      .el-cascader-node__label,
      .el-checkbox__label {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important;
      }
    `;
    doc.head.appendChild(style);
  }

  function ensureStaffsDrawer() {
    let drawer = document.getElementById(STAFFS_DRAWER_ID);
    if (drawer) return drawer;

    drawer = document.createElement('div');
    drawer.id = STAFFS_DRAWER_ID;
    drawer.className = 'hde-staffs-drawer';
    drawer.innerHTML = `
      <div class="hde-staffs-drawer__overlay" data-role="overlay"></div>
      <div class="hde-staffs-drawer__panel" role="dialog" aria-label="Управление статусами сотрудников">
        <div class="hde-staffs-drawer__header">
          <span>Статусы сотрудников</span>
          <button type="button" class="hde-staffs-drawer__close" aria-label="Закрыть">×</button>
        </div>
        <iframe class="hde-staffs-drawer__frame" title="Staff statuses" loading="lazy"></iframe>
      </div>
    `;
    document.body.appendChild(drawer);

    const closeBtn = drawer.querySelector('.hde-staffs-drawer__close');
    const overlay = drawer.querySelector('[data-role="overlay"]');
    const frame = drawer.querySelector('.hde-staffs-drawer__frame');
    const closeDrawer = () => {
      drawer.classList.remove('active');
      if (CONFIG.colleagueStatuses) updateColleagueStatusesBlock();
    };

    if (frame && !frame.dataset.hdeFontBound) {
      frame.dataset.hdeFontBound = '1';
      frame.addEventListener('load', () => {
        applyStaffsFrameTypography(frame);
      });
    }

    closeBtn?.addEventListener('click', closeDrawer);
    overlay?.addEventListener('click', closeDrawer);
    if (!window.__hdeStaffsDrawerEscBound) {
      window.__hdeStaffsDrawerEscBound = true;
      document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
          const d = document.getElementById(STAFFS_DRAWER_ID);
          if (d?.classList.contains('active')) {
            d.classList.remove('active');
            if (CONFIG.colleagueStatuses) updateColleagueStatusesBlock();
          }
        }
      });
    }

    return drawer;
  }

  function openStaffsDrawer() {
    const drawer = preloadStaffsDrawer();
    drawer.classList.add('active');
  }

  function preloadStaffsDrawer() {
    const drawer = ensureStaffsDrawer();
    const frame = drawer.querySelector('.hde-staffs-drawer__frame');
    if (frame && !frame.src) frame.src = '/ru/dashboard/staffs/';
    if (frame?.contentDocument?.readyState === 'complete') applyStaffsFrameTypography(frame);
    return drawer;
  }

  // ─── UI Настроек ─────────────────────────────────────────
  // ============================================================
  // 7) Settings Panel + Menu Actions
  // ============================================================

  function initSettingsMenu() {
    // Не возвращаемся сразу, если кнопка есть — нам важно уметь переткнуть её при SPA-перерисовке.
    // Но если кнопка уже есть и она уже стоит в правильном месте — выходим.
    const existingBtn = document.getElementById('hde-tools-menu');

    const menu = document.querySelector('.menu');
    const menuPlugins = document.querySelector('.menu-plugins');

    // Правильное место: внутрь '.menu' (или в крайнем случае рядом с menu__items)
    function isButtonInExpectedPlace() {
      if (!existingBtn) return false;
      if (menu && menu.contains(existingBtn)) return true;
      return false;
    }

    if (existingBtn && isButtonInExpectedPlace()) {
      const existingPanel = document.getElementById(MENU_PANEL_ID);
      const hasColleagueToggle = !!existingPanel?.querySelector('#hde-cfg-colleague-statuses');
      const hasLeftTabsToggle = !!existingPanel?.querySelector('#hde-cfg-left-tabs-mirror');
      if (existingPanel && existingPanel.dataset.hdePanelVersion === SETTINGS_PANEL_VERSION && hasColleagueToggle && hasLeftTabsToggle) return;
    }

    if (!menu && !menuPlugins && !existingBtn) {
      const observer = new MutationObserver(function () {
        if (document.querySelector('.menu') || document.querySelector('.menu-plugins')) {
          observer.disconnect();
          initSettingsMenu();
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
      return;
    }

    let style = document.getElementById(MENU_STYLE_ID);
    if (!style) {
      style = document.createElement('style');
      style.id = MENU_STYLE_ID;
      style.textContent = `

      .hde-tools-panel {
        position: fixed; width: 280px;
        background: #fff; color: #333; border-radius: 6px;
        box-shadow: 0 4px 16px rgba(0,0,0,0.25); padding: 15px; display: none; z-index: 99999;
        font-family: sans-serif; cursor: default;
      }
      .hde-tools-panel.active { display: block; }
      .hde-tools-panel h3 { margin: 0 0 15px 0; font-size: 14px; border-bottom: 1px solid #eee; padding-bottom: 8px; text-align: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-weight: 600; color: #333; }

      .hde-tools-toggle {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        column-gap: 10px;
        margin-bottom: 10px;
        font-size: 13px;
        cursor: pointer;
      }
      .hde-tools-note {
        font-size: 11px;
        opacity: 0.8;
      }
      .hde-tools-toggle input[type="checkbox"] { appearance: none; width: 34px; height: 18px; background: #ddd; border-radius: 9px; position: relative; outline: none; cursor: pointer; transition: 0.3s; }
      .hde-tools-toggle input[type="checkbox"]::after { content: ''; position: absolute; left: 2px; top: 2px; width: 14px; height: 14px; background: #fff; border-radius: 50%; transition: 0.3s; }
      .hde-tools-toggle input[type="checkbox"]:checked { background: #4caf50; }
      .hde-tools-toggle input[type="checkbox"]:checked::after { left: 18px; }
      .hde-tools-toggle-actions { display: inline-flex; align-items: center; margin-left: auto; }
      .hde-tools-link-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        padding: 0;
        border: none;
        background: transparent;
        color: #606266;
        text-decoration: none;
        line-height: 1 !important;
      }
      .hde-tools-link-btn i {
        font-size: 18px;
        line-height: 1;
      }
      .hde-tools-toggle-actions .hde-tools-link-btn {
        margin-right: 8px;
      }
      .hde-tools-link-btn:hover {
        color: #409eff;
      }
      .hde-tools-field { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; font-size: 13px; }
      .hde-tools-field input[type="number"],
      .hde-tools-field select {
        width: 72px; padding: 4px 6px; font-size: 12px; border: 1px solid #dcdfe6;
        border-radius: 6px; text-align: right; outline: none;
      }
      .hde-tools-field select {
        width: 120px; text-align: left; background: #fff;
      }
      .hde-staffs-drawer {
        position: fixed;
        inset: 0;
        z-index: 100001;
        visibility: hidden;
        pointer-events: none;
        transition: visibility 0s linear 0.3s;
      }
      .hde-staffs-drawer.active {
        visibility: visible;
        pointer-events: auto;
        transition-delay: 0s;
      }
      .hde-staffs-drawer__overlay {
        position: absolute;
        inset: 0;
        background: rgba(15, 20, 25, 0.45);
        opacity: 0;
        transition: opacity 0.3s ease;
      }
      .hde-staffs-drawer__panel {
        position: absolute;
        top: 0;
        right: 0;
        width: min(900px, 88vw);
        height: 100%;
        background: #fff;
        border-left: 1px solid #dcdfe6;
        box-shadow: -8px 0 24px rgba(0,0,0,0.18);
        display: flex;
        flex-direction: column;
        transform: translateX(100%);
        transition: transform 0.3s ease;
      }
      .hde-staffs-drawer.active .hde-staffs-drawer__overlay {
        opacity: 1;
      }
      .hde-staffs-drawer.active .hde-staffs-drawer__panel {
        transform: translateX(0);
      }
      .hde-staffs-drawer__header {
        height: 44px;
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 12px;
        font-weight: 600;
        border-bottom: 1px solid #ebeef5;
      }
      .hde-staffs-drawer__close {
        width: 28px;
        height: 28px;
        border: none;
        background: transparent;
        color: #606266;
        font-size: 22px;
        line-height: 1;
        cursor: pointer;
      }
      .hde-staffs-drawer__close:hover {
        color: #303133;
      }
      .hde-staffs-drawer__frame {
        width: 100%;
        height: calc(100% - 44px);
        border: 0;
        background: #fff;
      }
      .hde-left-tabs-column {
        flex: 0 0 180px;
        width: 180px;
        min-width: 180px;
        box-sizing: border-box;
        background: #ffffff;
      }
      .hde-left-tabs-column .hde-left-tabs-mirror {
        margin: 0;
      }
      .hde-left-tabs-mirror {
        margin: 0 0 10px 0;
        border-radius: 6px;
        background: #fff;
        overflow: hidden;
        font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif !important;
        font-size: 12px !important;
        color: #606266;
      }
      .hde-left-tabs-mirror,
      .hde-left-tabs-mirror * {
        font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif !important;
      }
      .hde-left-tabs-mirror__title {
        padding: 6px 8px;
        background: #F5F7FA;
        display: flex;
        width: 100%;
        box-sizing: border-box;
        min-height: 44px;
        max-height: 44px;
        align-items: center;
        justify-content: space-between;
        text-align: center;
        font-size: 12px !important;
        font-weight: 600;
        color: #303133;
        border-bottom: 1px solid #E5E5E5;
      }
      .hde-left-tabs-mirror__title-text {
        flex: 1;
        min-width: 0;
        text-align: center;
        padding-left: 22px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .hde-left-tabs-mirror__close-all {
        position: relative;
        z-index: 2;
        flex: 0 0 auto;
        border: 0;
        background: transparent;
        color: inherit;
        cursor: pointer;
        font-size: 13px !important;
        font-weight: 700;
        line-height: 1;
        padding: 0 8px;
        opacity: .72;
      }
      .hde-left-tabs-mirror__close-all:hover {
        opacity: 1;
      }
      .hde-left-tabs-mirror__list {
        max-height: 100%;
        overflow: auto;
      }
      .hde-left-tabs-mirror__item {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        position: relative;
        width: 100%;
        border: 0;
        border-bottom: 1px solid #f0f2f5;
        background: transparent;
        color: #606266;
        font-size: 12px !important;
        font-weight: 400;
        line-height: 1.4;
        font-family: inherit !important;
        text-align: left;
        padding: 6px 0px;
        cursor: pointer;
      }
      .hde-left-tabs-mirror__indicator {
        width: 8px;
        min-width: 8px;
        height: 8px;
        border-radius: 50%;
        background: transparent;
        margin-right: 6px;
        margin-top: 4px;
      }
      .hde-left-tabs-mirror__indicator.has-badge {
        background: #f56c6c;
      }
      .hde-left-tabs-mirror__content {
        min-width: 0;
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 2px;
      }
      .hde-left-tabs-mirror__head {
        display: flex;
        align-items: baseline;
        gap: 6px;
        min-width: 0;
        width: 100%;
      }
      .hde-left-tabs-mirror__department {
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        width: 100%;
        font-size: 10px !important;
        line-height: 1.2 !important;
        opacity: 0.75;
        font-weight: 500;
        color: #909399;
      }
      .hde-left-tabs-mirror__department:empty {
        display: none;
      }
      .hde-left-tabs-mirror__item:last-child {
        border-bottom: 0;
      }
      .hde-left-tabs-mirror__item:hover {
        background: #f5f7fa;
      }
      .hde-left-tabs-mirror__item.is-active {
        background: #ecf5ff;
        color: #409eff;
      }
      .hde-left-tabs-mirror__name {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        min-width: 0;
        flex: 1;
        font-family: inherit !important;
        font-size: inherit !important;
        font-weight: 600;
      }
      .hde-left-tabs-mirror__time {
        flex: 0 0 auto;
        font-size: 10px !important;
        line-height: 1.1 !important;
        opacity: 0.7;
        white-space: nowrap;
        margin-left: auto;
        padding-right: 4px;
      }
      .hde-left-tabs-mirror__preview {
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        width: 100%;
        font-size: 11px !important;
        line-height: 1.25 !important;
        opacity: 0.8;
      }
      .hde-left-tabs-mirror__close {
        position: absolute;
        right: 2px;
        top: 50%;
        transform: translateY(-50%);
        z-index: 1;
        flex: 0 0 auto;
        align-self: flex-start;
        border: 0;
        background: transparent;
        color: inherit;
        font-size: inherit !important;
        font-family: inherit !important;
        cursor: pointer;
        padding: 2px 4px;
        margin: 0;
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: opacity .15s ease, visibility .15s ease;
      }
      .hde-left-tabs-mirror__item:hover .hde-left-tabs-mirror__close,
      .hde-left-tabs-mirror__item:focus-within .hde-left-tabs-mirror__close {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-mirror {
        background: #1e2529;
        border-color: #3d4654;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-column {
        border-right: 1px solid #2d333b;
        background: #1a1f26;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-mirror__title {
        background: #252b33;
        color: #e4e7ed;
        border-bottom-color: #3d4654;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-mirror__item {
        color: #c0c4cc;
        border-bottom-color: #2d333b;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-mirror__item:hover {
        background: #252b33;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-mirror__item.is-active {
        background: #2d333b;
        color: #e4e7ed;
      }
      html.${DARK_HTML_CLASS} .hde-left-tabs-mirror__department {
        color: #909399;
        opacity: 0.9;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-column {
        border-right: 1px solid #e3ccd8;
        background: #fbe9f2;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror {
        background: #fff6fb;
        border: 1px solid #eed9e5;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__title {
        background: #f8eaf2;
        color: #7a5a6b;
        border-bottom-color: #e3ccd8;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__item {
        color: #7a5a6b;
        border-bottom-color: #edd9e5;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__item:hover {
        background: #f9edf4;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__item.is-active {
        background: #f4e1eb;
        color: #6b4c5d;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__department {
        color: #9a778b;
        opacity: 0.95;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__preview {
        color: #8b687c;
        opacity: 0.92;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__time {
        color: #a78699;
      }
      html.${PINK_HTML_CLASS} .hde-left-tabs-mirror__indicator.has-badge {
        background: #cf7a8f;
      }
      html.${PINK_HTML_CLASS} #ticket-app .el-loading-mask,
      html.${PINK_HTML_CLASS} .el-loading-mask {
        background-color: rgba(251, 233, 242, 0.92) !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-column {
        border-right: 1px solid #2a4266;
        background: #111c2f;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror {
        background: #0f1728;
        border: 1px solid #2a4266;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__title {
        background: #16243b;
        color: #d4e4fb;
        border-bottom-color: #2a4266;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__item {
        color: #b7cae7;
        border-bottom-color: #233a5d;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__item:hover {
        background: #1b2d4a;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__item.is-active {
        background: #23395f;
        color: #e5efff;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__department {
        color: #89a2c5;
        opacity: 0.95;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__preview {
        color: #9bb3d4;
        opacity: 0.93;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__time {
        color: #7f98bb;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .hde-left-tabs-mirror__indicator.has-badge {
        background: #6cb8ff;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-column {
        border-right: 1px solid #bfd0ec;
        background: #f6f9ff;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror {
        background: #ffffff;
        border: 1px solid #d7e3f8;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__title {
        background: #edf4ff;
        color: #1d3f73;
        border-bottom-color: #bfd0ec;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__item {
        color: #2a4d82;
        border-bottom-color: #e4ecfb;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__item:hover {
        background: #f3f7ff;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__item.is-active {
        background: #e1ebff;
        color: #173968;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__department {
        color: #5570a0;
        opacity: 0.95;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__preview {
        color: #4d6793;
        opacity: 0.93;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__time {
        color: #6a81ac;
      }
      html.${TRICOLOR_HTML_CLASS} .hde-left-tabs-mirror__indicator.has-badge {
        background: #d63445;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-column {
        border-right: 1px solid #3a3a3a;
        background: #121212;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror {
        background: #171717;
        border: 1px solid #3a3a3a;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__title {
        background: #202020;
        color: #efefef;
        border-bottom-color: #3a3a3a;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__item {
        color: #dedede;
        border-bottom-color: #323232;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__item:hover {
        background: #232323;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__item.is-active {
        background: #2b2b2b;
        color: #ffffff;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__department {
        color: #bbbbbb;
        opacity: 0.95;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__preview {
        color: #c4c4c4;
        opacity: 0.93;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__time {
        color: #a6a6a6;
      }
      html.${MONOCHROME_HTML_CLASS} .hde-left-tabs-mirror__indicator.has-badge {
        background: #f1f1f1;
      }
      /* Унификация цвета стрелок popper под текущую тему */
      :root {
        --hde-popper-bg: #ffffff;
        --hde-popper-border: #dcdfe6;
      }
      html.${DARK_HTML_CLASS} {
        --hde-popper-bg: #1e2529;
        --hde-popper-border: #3d4654;
      }
      html.${PINK_HTML_CLASS} {
        --hde-popper-bg: #fff6fb;
        --hde-popper-border: #e3ccd8;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} {
        --hde-popper-bg: #15223a;
        --hde-popper-border: #2a4266;
      }
      html.${TRICOLOR_HTML_CLASS} {
        --hde-popper-bg: #ffffff;
        --hde-popper-border: #bfd0ec;
      }
      html.${MONOCHROME_HTML_CLASS} {
        --hde-popper-bg: #1b1b1b;
        --hde-popper-border: #3a3a3a;
      }
      .el-popover,
      .el-popper {
        border-color: var(--hde-popper-border) !important;
      }
      .el-popover[x-placement^="top"] .popper__arrow,
      .el-popover[x-placement^="bottom"] .popper__arrow,
      .el-popover[x-placement^="left"] .popper__arrow,
      .el-popover[x-placement^="right"] .popper__arrow,
      .el-popper[data-popper-placement^="top"] .popper__arrow,
      .el-popper[data-popper-placement^="bottom"] .popper__arrow,
      .el-popper[data-popper-placement^="left"] .popper__arrow,
      .el-popper[data-popper-placement^="right"] .popper__arrow,
      .el-popover[data-popper-placement^="top"] .popper__arrow,
      .el-popover[data-popper-placement^="bottom"] .popper__arrow,
      .el-popover[data-popper-placement^="left"] .popper__arrow,
      .el-popover[data-popper-placement^="right"] .popper__arrow {
        border-top-color: var(--hde-popper-border) !important;
        border-bottom-color: var(--hde-popper-border) !important;
        border-left-color: var(--hde-popper-border) !important;
        border-right-color: var(--hde-popper-border) !important;
      }
      .el-popover .popper__arrow::after,
      .el-popper[data-popper-placement] .popper__arrow::after {
        border-top-color: var(--hde-popper-bg) !important;
        border-bottom-color: var(--hde-popper-bg) !important;
        border-left-color: var(--hde-popper-bg) !important;
        border-right-color: var(--hde-popper-bg) !important;
      }
      /* Popup уведомлений — явные цвета под темы */
      html.${DARK_HTML_CLASS} .notifications {
        background: #1e2529 !important;
        color: #e4e7ed !important;
        border: 1px solid #3d4654 !important;
      }
      html.${DARK_HTML_CLASS} .notifications__heading,
      html.${DARK_HTML_CLASS} .notifications__filters,
      html.${DARK_HTML_CLASS} .notifications__item {
        border-color: #3d4654 !important;
      }
      html.${DARK_HTML_CLASS} .notifications__heading-text,
      html.${DARK_HTML_CLASS} .notifications__item-name,
      html.${DARK_HTML_CLASS} .notifications__item-text,
      html.${DARK_HTML_CLASS} .notifications__close-button,
      html.${DARK_HTML_CLASS} .notifications__item-icon i {
        color: #e4e7ed !important;
      }
      html.${DARK_HTML_CLASS} .notifications__item-date {
        color: #a8abb2 !important;
      }
      html.${DARK_HTML_CLASS} .notifications__filter button {
        background: #252b33 !important;
        color: #c0c4cc !important;
        border: 1px solid #3d4654 !important;
      }
      html.${DARK_HTML_CLASS} .notifications__filter button.active,
      html.${DARK_HTML_CLASS} .notifications__filter button:hover {
        background: #2d333b !important;
        color: #e4e7ed !important;
        border-color: #4a5563 !important;
      }
      html.${DARK_HTML_CLASS} .notifications__item:hover,
      html.${DARK_HTML_CLASS} .notifications__item_unread {
        background: #252b33 !important;
      }

      html.${PINK_HTML_CLASS} .notifications {
        background: #fff6fb !important;
        color: #6b4c5d !important;
        border: 1px solid #e3ccd8 !important;
      }
      html.${PINK_HTML_CLASS} .notifications__heading,
      html.${PINK_HTML_CLASS} .notifications__filters,
      html.${PINK_HTML_CLASS} .notifications__item {
        border-color: #e3ccd8 !important;
      }
      html.${PINK_HTML_CLASS} .notifications__heading-text,
      html.${PINK_HTML_CLASS} .notifications__item-name,
      html.${PINK_HTML_CLASS} .notifications__item-text,
      html.${PINK_HTML_CLASS} .notifications__close-button,
      html.${PINK_HTML_CLASS} .notifications__item-icon i {
        color: #6b4c5d !important;
      }
      html.${PINK_HTML_CLASS} .notifications__item-date {
        color: #9a778b !important;
      }
      html.${PINK_HTML_CLASS} .notifications__filter button {
        background: #f8eaf2 !important;
        color: #7a5a6b !important;
        border: 1px solid #e3ccd8 !important;
      }
      html.${PINK_HTML_CLASS} .notifications__filter button.active,
      html.${PINK_HTML_CLASS} .notifications__filter button:hover {
        background: #f4e1eb !important;
        color: #6b4c5d !important;
        border-color: #dcbdd0 !important;
      }
      html.${PINK_HTML_CLASS} .notifications__item:hover,
      html.${PINK_HTML_CLASS} .notifications__item_unread {
        background: #fdf1f7 !important;
      }

      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications {
        background: #0f1728 !important;
        color: #d4e4fb !important;
        border: 1px solid #2a4266 !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__heading,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__filters,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item {
        border-color: #2a4266 !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__heading-text,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item-name,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item-text,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__close-button,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item-icon i {
        color: #d4e4fb !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item-date {
        color: #89a2c5 !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__filter button {
        background: #16243b !important;
        color: #b7cae7 !important;
        border: 1px solid #2a4266 !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__filter button.active,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__filter button:hover {
        background: #23395f !important;
        color: #e5efff !important;
        border-color: #3f6292 !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item:hover,
      html.${MIDNIGHT_BLUE_HTML_CLASS} .notifications__item_unread {
        background: #1b2d4a !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications {
        background: #ffffff !important;
        color: #1d3f73 !important;
        border: 1px solid #bfd0ec !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications__heading,
      html.${TRICOLOR_HTML_CLASS} .notifications__filters,
      html.${TRICOLOR_HTML_CLASS} .notifications__item {
        border-color: #d6e2f7 !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications__heading-text,
      html.${TRICOLOR_HTML_CLASS} .notifications__item-name,
      html.${TRICOLOR_HTML_CLASS} .notifications__item-text,
      html.${TRICOLOR_HTML_CLASS} .notifications__close-button,
      html.${TRICOLOR_HTML_CLASS} .notifications__item-icon i {
        color: #1d3f73 !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications__item-date {
        color: #6a81ac !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications__filter button {
        background: #edf4ff !important;
        color: #2a4d82 !important;
        border: 1px solid #bfd0ec !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications__filter button.active,
      html.${TRICOLOR_HTML_CLASS} .notifications__filter button:hover {
        background: #e1ebff !important;
        color: #173968 !important;
        border-color: #a8c0e7 !important;
      }
      html.${TRICOLOR_HTML_CLASS} .notifications__item:hover,
      html.${TRICOLOR_HTML_CLASS} .notifications__item_unread {
        background: #f3f7ff !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications {
        background: #171717 !important;
        color: #f1f1f1 !important;
        border: 1px solid #3a3a3a !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications__heading,
      html.${MONOCHROME_HTML_CLASS} .notifications__filters,
      html.${MONOCHROME_HTML_CLASS} .notifications__item {
        border-color: #3a3a3a !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications__heading-text,
      html.${MONOCHROME_HTML_CLASS} .notifications__item-name,
      html.${MONOCHROME_HTML_CLASS} .notifications__item-text,
      html.${MONOCHROME_HTML_CLASS} .notifications__close-button,
      html.${MONOCHROME_HTML_CLASS} .notifications__item-icon i {
        color: #f1f1f1 !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications__item-date {
        color: #a9a9a9 !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications__filter button {
        background: #222222 !important;
        color: #d8d8d8 !important;
        border: 1px solid #3a3a3a !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications__filter button.active,
      html.${MONOCHROME_HTML_CLASS} .notifications__filter button:hover {
        background: #2c2c2c !important;
        color: #ffffff !important;
        border-color: #535353 !important;
      }
      html.${MONOCHROME_HTML_CLASS} .notifications__item:hover,
      html.${MONOCHROME_HTML_CLASS} .notifications__item_unread {
        background: #242424 !important;
      }
      /* Контрастные сине-красные акценты для основных action-кнопок */
      html.${TRICOLOR_HTML_CLASS} #ticket-app .el-button.el-button--primary,
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-editor__action_type_post,
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-editor__action_type_comment {
        background: #d63445 !important;
        border-color: #bf2f3f !important;
        color: #ffffff !important;
      }
      html.${TRICOLOR_HTML_CLASS} #ticket-app .el-button.el-button--primary:hover,
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-editor__action_type_post:hover,
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-editor__action_type_comment:hover {
        background: #c42f3f !important;
        border-color: #a92836 !important;
      }
      html.${MONOCHROME_HTML_CLASS} #ticket-app .el-button.el-button--primary,
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-editor__action_type_post,
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-editor__action_type_comment {
        background: #f1f1f1 !important;
        border-color: #d3d3d3 !important;
        color: #121212 !important;
      }
      html.${MONOCHROME_HTML_CLASS} #ticket-app .el-button.el-button--primary:hover,
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-editor__action_type_post:hover,
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-editor__action_type_comment:hover {
        background: #dcdcdc !important;
        border-color: #c4c4c4 !important;
      }
      /* Акцентные фильтры sidebar: сохраняем смысл цвета, но смягчаем оттенок в темах */
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(255, 0, 0)"],
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(225, 18, 18)"],
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(255, 0, 0)"],
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(225, 18, 18)"] {
        color: #ff8f8f !important;
      }
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(81, 169, 251)"],
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(13, 113, 207)"],
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(81, 169, 251)"],
      html.${DARK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(13, 113, 207)"] {
        color: #87bdf2 !important;
      }
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(255, 0, 0)"],
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(225, 18, 18)"],
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(255, 0, 0)"],
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(225, 18, 18)"] {
        color: #c8657b !important;
      }
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(81, 169, 251)"],
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(13, 113, 207)"],
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(81, 169, 251)"],
      html.${PINK_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(13, 113, 207)"] {
        color: #6f9ccc !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(255, 0, 0)"],
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(225, 18, 18)"],
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(255, 0, 0)"],
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(225, 18, 18)"] {
        color: #ff9a9a !important;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(81, 169, 251)"],
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(13, 113, 207)"],
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(81, 169, 251)"],
      html.${MIDNIGHT_BLUE_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(13, 113, 207)"] {
        color: #8ec2ff !important;
      }
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(255, 0, 0)"],
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(225, 18, 18)"],
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(255, 0, 0)"],
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(225, 18, 18)"] {
        color: #d63445 !important;
      }
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(81, 169, 251)"],
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(13, 113, 207)"],
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(81, 169, 251)"],
      html.${TRICOLOR_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(13, 113, 207)"] {
        color: #1f6fc5 !important;
      }
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(255, 0, 0)"],
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(225, 18, 18)"],
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(255, 0, 0)"],
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(225, 18, 18)"] {
        color: #d6d6d6 !important;
      }
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(81, 169, 251)"],
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-button[style*="rgb(13, 113, 207)"],
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(81, 169, 251)"],
      html.${MONOCHROME_HTML_CLASS} #ticket-app .ticket-sidebar__filter-name[style*="rgb(13, 113, 207)"] {
        color: #a6a6a6 !important;
      }

      .staffs-injected-block {
        border-radius: 3px;
        padding-bottom: 10px;
        margin-bottom: 12px;
        text-align: center;
        --staff-status-online: #3e9a55;
        --staff-status-invisible: #3f78b8;
        --staff-status-break: #c9872c;
        --staff-status-offline: #c25353;
        --staffs-muted: #c5c9d0;
        --staffs-group-color: #555;
      }
      .staffs-injected-group-header {
        display: flex;
        align-items: center;
        margin: 0;
        font-weight: 700;
        color: var(--staffs-group-color);
      }
      .staffs-injected-group-total {
        flex: 0 0 auto;
        padding-right: 0;
        margin: 0 0 0 6px;
      }
      .staffs-injected-group-name {
        flex: 1;
        text-align: center;
      }
      .staffs-injected-list {
        list-style: none;
        padding: 0;
        margin: 0 0 8px 0;
      }
      .staffs-injected-member-row {
        display: flex;
        align-items: center;
        padding: 0;
      }
      .staffs-injected-badge {
        display: inline-block;
        width: 18px;
        text-align: center;
        font-size: 13px;
        line-height: 1;
      }
      .staffs-injected-badge.no-tickets {
        color: var(--staffs-muted);
      }
      .staffs-injected-member-name {
        font-weight: 400;
        flex: 1;
        text-align: left;
      }
      .staffs-injected-member-status {
        white-space: nowrap;
        margin: 0 5px 0 0;
      }
      .staffs-injected-member-name.status-online,
      .staffs-injected-member-status.status-online,
      .staffs-injected-badge.status-online.has-tickets {
        color: var(--staff-status-online);
      }
      .staffs-injected-member-name.status-invisible,
      .staffs-injected-member-status.status-invisible,
      .staffs-injected-badge.status-invisible.has-tickets {
        color: var(--staff-status-invisible);
      }
      .staffs-injected-member-name.status-break,
      .staffs-injected-member-status.status-break,
      .staffs-injected-badge.status-break.has-tickets {
        color: var(--staff-status-break);
      }
      .staffs-injected-member-name.status-offline,
      .staffs-injected-member-status.status-offline,
      .staffs-injected-badge.status-offline.has-tickets {
        color: var(--staff-status-offline);
      }

      html.${DARK_HTML_CLASS} .staffs-injected-block {
        --staff-status-online: #78c18b;
        --staff-status-invisible: #7cb5ff;
        --staff-status-break: #f4b562;
        --staff-status-offline: #ef8a8a;
        --staffs-muted: #6f7883;
        --staffs-group-color: #c0c4cc;
      }
      html.${PINK_HTML_CLASS} .staffs-injected-block {
        --staff-status-online: #7fae7f;
        --staff-status-invisible: #8aa4d6;
        --staff-status-break: #d5a06a;
        --staff-status-offline: #cf7a8f;
        --staffs-muted: #b79fb0;
        --staffs-group-color: #7a5a6b;
      }
      html.${MIDNIGHT_BLUE_HTML_CLASS} .staffs-injected-block {
        --staff-status-online: #7bcf9a;
        --staff-status-invisible: #8ec2ff;
        --staff-status-break: #e3b679;
        --staff-status-offline: #ff9a9a;
        --staffs-muted: #7f98bb;
        --staffs-group-color: #b7cae7;
      }
      html.${TRICOLOR_HTML_CLASS} .staffs-injected-block {
        --staff-status-online: #4cae7d;
        --staff-status-invisible: #1f6fc5;
        --staff-status-break: #c08a45;
        --staff-status-offline: #d63445;
        --staffs-muted: #6a81ac;
        --staffs-group-color: #2a4d82;
      }
      html.${MONOCHROME_HTML_CLASS} .staffs-injected-block {
        --staff-status-online: #dcdcdc;
        --staff-status-invisible: #c4c4c4;
        --staff-status-break: #adadad;
        --staff-status-offline: #8f8f8f;
        --staffs-muted: #787878;
        --staffs-group-color: #efefef;
      }

      /* Чтобы пункт меню/кнопка НИКОГДА не прятались (Vue может менять display/opacity) */
      #hde-tools-menu { display: inline-flex !important; opacity: 1 !important; visibility: visible !important; }
      #hde-tools-menu .menu__item { display: inline-flex !important; opacity: 1 !important; visibility: visible !important; }
      #hde-tools-menu * { opacity: 1 !important; }
      a.menu__item.menu__item_logo {
        position: relative !important;
        background-image: none !important;
        background-color: transparent !important;
        color: var(--menu-item-color, #606266) !important;
      }
      a.menu__item.menu__item_logo::before {
        content: '';
        position: absolute;
        inset: 0;
        background: currentColor;
        -webkit-mask: url("//cdn5.helpdeskeddy.com//img/menu-logo-white.svg") center / contain no-repeat;
        mask: url("//cdn5.helpdeskeddy.com//img/menu-logo-white.svg") center / contain no-repeat;
      }
      a.menu__item.menu__item_logo:hover {
        color: var(--menu-item-color-hover, #409eff) !important;
      }
      a.menu__item[href="/ru/dashboard"],
      a.menu__item[href="/ru/dashboard/"] {
        display: none !important;
      }
      #hde-tools-btn {
        flex-direction: column !important;
        align-items: center !important;
        justify-content: center !important;
        gap: 4px !important;
        text-align: center !important;
      }
      #hde-tools-btn .menu__item-icon,
      #hde-tools-btn .menu__item-name {
        display: block !important;
        margin: 0 !important;
      }

      #hde-tools-btn .menu__item-icon {
        position: relative;
        width: 25px;
        height: 25px;
      }
      #hde-tools-btn .menu__item-icon .hde-dino-source {
        display: none !important;
      }
      #hde-tools-btn .menu__item-icon .hde-dino-mask {
        position: absolute;
        inset: 0;
        background: currentColor;
        -webkit-mask-size: contain;
        mask-size: contain;
        -webkit-mask-repeat: no-repeat;
        mask-repeat: no-repeat;
        -webkit-mask-position: center;
        mask-position: center;
      }
      html.${LEFT_TABS_ONLY_CLASS} #ticket-app .ticket-topbar__tabs {
        display: none !important;
      }
      html.${LEFT_TABS_ONLY_CLASS} .ticket-tabs__show-more-popper {
        display: none !important;
      }
    `;
      document.head.appendChild(style);
    }

    const menuItems = document.querySelector('.menu__items');

    const btnContainer = existingBtn || document.createElement('div');
    btnContainer.id = 'hde-tools-menu';
    btnContainer.style.position = 'relative';
    if (!existingBtn) {
      const btn = document.createElement('a');
      btn.className = 'menu__item';
      btn.href = 'javascript:void(0)';
      btn.id = 'hde-tools-btn';
      btn.title = 'HDE Tools Settings';
      btn.innerHTML = `<div data-v-808034fc="" class="menu__item-icon"><img width="25" height="25" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAFOElEQVR4nO2ae4jVRRTHz9WydbPWntKLyiyIMoLsjwqR7OWiZe8MooLe9MTIKLZcgtISgiIjUwMrSgx7/VFbLaZkBVbW+kel9jC3tujllrmaun7itN/f7ni7j9+9d+7uFfrC5d6Z35wzc34z851zzlyz/1EagLOB9cB3wFm2KwI4AeiiD5uA462WABwHLAHeAM7J08afO54C5uh3q9UQMsAnwZveAUwNG/ib17NOM9vbzBqAP1RXG7MCnKIBfQM0A9tlzJVBm/uT2QjqnlbdfVYLAO7SgB5X+VqVN5jZQap7XXUXB3KXqO41qwUAj2lAt6lqEPCB6tqBDs1QPnQCs4DTzWy3gTRktgZ0O3AzsI7y4cvzejMbMhCGJOt/SzCgtcADQKOZHWxmg3OI7g4cAZwBzATWBPJtzoT9bcjdwQC+Aib78ipDlS/JS4HV0uVnzoXVoFjn/1+BX4C3geuAy4Gt6niBmdVF6GtP4BnpdN3nWywA44qs7egUCjwk3ZujLTNgkpS+ZWYHaDYSJpofpZPc/c5THyujEABwrBR2aC3fqvKXZlZv1cMw7TvEZlH2iFOjY7K8V8dFVmXQd3CuzcN+JSu8Qwp/1/dqN7BA+4nA9zoUG0voZ2KW3GDRuWN8xYaY2R6BQseDRQbkA0mwvgRD2rPldM44ZhaSTcv5f5uZ+0pbVF5q/YdWfY+NplHT7jiySLtGvV2PCCeUoL8xWw44XH1+a5FQl7gi7mJY/2GoDOmqSAtwMvBSGKpGG2L6MfyLShTcC3T3qOn9Llkh8K4cw2k6qf38qVf0OE1EsrwqhgBjJL8NeETearmGLKU4qmbIaZLf4CFthQrdI5gAPK/TepM+PhPPaWPnZdCKDNGJ/oJ0eCw+t1KF5YII/Q5RKOqG9ML6GcTqV5sy1YwA7wPLygywciL6C0xpSBK2TordL9DiJFSOjv3lyF0DTElpSOJgtpQ98ixksdt2BXOZtMJXK0LLxp9Bm2XACs8eBqINYqRuM9snVWfFx5Lg0WC/3plW2HNSjveUGVys8sdBm5Wqeyd0WzyajLm8EPT73CAJmEo4yelOUfk8lWcHbY5WUsLxchIxAtNV1xzTEOAm4FP9XpNW+EYJdMgDXRAaFrQ7SRlDZPyYIByeFdmQBJ4IPDGtvEdnyyX4ufaLxyP75uhodBBfOzbGjLXpwyvAVR7olarjQGBVoOjFAm0bFM0ls+MkMMwiAKFSJb50UAoozXT6QXhoxAOxrtR4xH2rJ7WEfnYm8qWhm6gkmzgQOEz9t6dqDZxKfjjVjSjgkrjxP4qqnesv0+1UxaCPLVtLuXV1vOkHGTAjMOSKAnI++FzwiHI+MKpCQ+ZI38NpBUZJwBPVI4NEw7MpxD2BPQI4E7hHl5/dQTK6ucy0Z31AHp4vmJ5KT5C78j3iWFIO1UnXSOVvE4M8hTS8RB1NwcvdEYxpeFpBR1upHefROTZIvH2WlpLpOZvcZ0M3AuOCVdKW5d/tJDg+cDc+NLP9LC7zfCHdC1O0PyQ4YOfl0dPyH4rX/Z8nGRyvViPLDhwF/KY+bigyE1+r3Uee18p67u7ST3p+S7YRCWbEjOxyDPKC4IpiaI6N3RQspxX5wgC/yVKbH8LK5C01VcuAPH/nmKoUk7vlTwSZfsfcQqtCs+ubf2vy4v00X2Vmo/25mXkGfJ2ZbTazjZIbFGysvUQAyacsRouIxZlMpuePCMAxwKKAcncFdIk0ej3xneJenzKxlbsX/kluibaZ2V9m5o5bZyaT8T/IuNviM1cT+AdBA3PwGaO09gAAAABJRU5ErkJggg==" alt="kawaii-dinosaur--v2"></div><div data-v-808034fc="" class="menu__item-name"> HDE toys </div>`;
      btnContainer.appendChild(btn);
    }

    const btn = btnContainer.querySelector('#hde-tools-btn') || btnContainer.querySelector('a');
    const dinoIconWrap = btn.querySelector('.menu__item-icon');
    const dinoSourceImg = dinoIconWrap?.querySelector('img');
    if (dinoIconWrap && dinoSourceImg) {
      dinoSourceImg.classList.add('hde-dino-source');
      let dinoMask = dinoIconWrap.querySelector('.hde-dino-mask');
      if (!dinoMask) {
        dinoMask = document.createElement('span');
        dinoMask.className = 'hde-dino-mask';
        dinoMask.setAttribute('aria-hidden', 'true');
        dinoIconWrap.appendChild(dinoMask);
      }
      const src = dinoSourceImg.currentSrc || dinoSourceImg.src;
      dinoMask.style.webkitMaskImage = `url("${src}")`;
      dinoMask.style.maskImage = `url("${src}")`;
    }

    const panel = document.getElementById(MENU_PANEL_ID) || document.createElement('div');
    panel.id = MENU_PANEL_ID;
    panel.className = 'hde-tools-panel';
    panel.innerHTML = `
      <label class="hde-tools-field">
        <span>Тема интерфейса</span>
        <select id="hde-cfg-theme-mode">
          ${renderThemeOptions(CONFIG.themeMode)}
        </select>
      </label>
      <label class="hde-tools-toggle">
        <span>Компактный чат</span>
        <input type="checkbox" id="hde-cfg-compact" ${CONFIG.compactChat ? 'checked' : ''}>
      </label>
      <label class="hde-tools-toggle">
        <span>Левая панель тикетов<br><span class="hde-tools-note">может вызывать капчку</span></span>
        <input type="checkbox" id="hde-cfg-left-tabs-mirror" ${CONFIG.leftTabsMirror ? 'checked' : ''}>
      </label>
      <label class="hde-tools-toggle">
        <span>Скрыть родную панель тикетов<br><span class="hde-tools-note">временный режим для тестов</span></span>
        <input type="checkbox" id="hde-cfg-hide-native-tabs" ${CONFIG.hideNativeTicketTabs ? 'checked' : ''}>
      </label>
      <label class="hde-tools-toggle hde-tools-toggle-colleague">
        <span>Статусы коллег</span>
        <span class="hde-tools-toggle-actions">
          <a
            id="hde-colleague-staffs-link"
            class="hde-tools-link-btn"
            href="/ru/dashboard/staffs/"
            target="_blank"
            rel="noopener noreferrer"
            title="Открыть аналитику сотрудников"
            aria-label="Открыть аналитику сотрудников"
          ><i class="el-icon-setting"></i></a>
          <input type="checkbox" id="hde-cfg-colleague-statuses" ${CONFIG.colleagueStatuses ? 'checked' : ''}>
        </span>
      </label>
      <label class="hde-tools-toggle">
        <span>Подгружать историю</span>
        <input type="checkbox" id="hde-cfg-autoload" ${CONFIG.autoLoadHistory ? 'checked' : ''}>
      </label>
      <label class="hde-tools-toggle">
        <span>Подгружать прошлые диалоги</span>
        <input type="checkbox" id="hde-cfg-prev-dialogs" ${CONFIG.autoLoadPreviousDialogs ? 'checked' : ''}>
      </label>
      <label class="hde-tools-field">
        <span>Кол-во подгружаемых диалогов</span>
        <input type="number" id="hde-cfg-prev-limit" min="1" max="10" step="1" value="${getPreviousDialogsLimit()}">
      </label>
    `;
    panel.dataset.hdePanelVersion = SETTINGS_PANEL_VERSION;

    // Иконка динозаврика в меню

    function positionPanel() {
      const rect = btn.getBoundingClientRect();
      panel.style.left = (rect.right + 8) + 'px';
      panel.style.top = rect.top + 'px';
    }

    // Клик по нативному menu__item — предотвращаем переход по href
    if (!btn.dataset.hdeToolsBound) {
      btn.dataset.hdeToolsBound = '1';
      btn.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        if (CONFIG.colleagueStatuses) preloadStaffsDrawer();
        const isActive = panel.classList.contains('active');
        if (isActive) {
          panel.classList.remove('active');
        } else {
          positionPanel();
          panel.classList.add('active');
        }
      });
    }

    if (!window.__hdeToolsDocClickBound) {
      window.__hdeToolsDocClickBound = true;
      document.addEventListener('click', (e) => {
        const currentPanel = document.getElementById(MENU_PANEL_ID);
        const currentBtn = document.getElementById('hde-tools-btn');
        if (!currentPanel || !currentBtn) return;
        if (!currentPanel.contains(e.target) && e.target !== currentBtn && !currentBtn.contains(e.target)) {
          currentPanel.classList.remove('active');
        }
      });
    }

    panel.querySelector('#hde-cfg-theme-mode').onchange = (e) => {
      CONFIG.themeMode = normalizeThemeMode(e.target.value);
      saveConfig();
      applyThemeFromConfig();
    };

    panel.querySelector('#hde-cfg-compact').onchange = (e) => {
      CONFIG.compactChat = e.target.checked;
      saveConfig();
      if (CONFIG.compactChat) {
        injectStyle();
        processAllMessages();
      } else {
        alert('Для отключения компактного вида необходимо обновить страницу');
      }
    };

    panel.querySelector('#hde-cfg-left-tabs-mirror').onchange = (e) => {
      CONFIG.leftTabsMirror = e.target.checked;
      saveConfig();
      syncNativeTicketTabsVisibilityClass();
      syncLeftTabsOnHrefChange();
      syncLeftTabsMirror();
    };

    panel.querySelector('#hde-cfg-hide-native-tabs').onchange = (e) => {
      CONFIG.hideNativeTicketTabs = e.target.checked;
      saveConfig();
      syncNativeTicketTabsVisibilityClass();
      syncLeftTabsMirror();
    };

    panel.querySelector('#hde-cfg-colleague-statuses').onchange = (e) => {
      CONFIG.colleagueStatuses = e.target.checked;
      saveConfig();
      syncColleagueStatusesModule();
      syncColleagueStaffsLinkVisibility();
      if (!CONFIG.colleagueStatuses) {
        const drawer = document.getElementById(STAFFS_DRAWER_ID);
        if (drawer) drawer.classList.remove('active');
      }
    };

    panel.querySelector('#hde-cfg-autoload').onchange = (e) => {
      CONFIG.autoLoadHistory = e.target.checked;
      saveConfig();
      syncPrevDialogsVisibility();
      if (CONFIG.autoLoadHistory) {
        injectPaginationStyle();
        initAutoLoad();
      } else {
        removePaginationStyle();
      }
    };

    panel.querySelector('#hde-cfg-prev-dialogs').onchange = (e) => {
      CONFIG.autoLoadPreviousDialogs = e.target.checked;
      const prevLimitField = panel.querySelector('#hde-cfg-prev-limit')?.closest('label');
      if (prevLimitField) prevLimitField.style.display = CONFIG.autoLoadPreviousDialogs ? 'flex' : 'none';
      saveConfig();
      if (CONFIG.autoLoadPreviousDialogs) {
        _historyLoadedForTicketId = null;
        initAutoLoad();
      } else {
        clearPreviousDialogsFromView();
      }
    };

    panel.querySelector('#hde-cfg-prev-limit').onchange = (e) => {
      const nextValue = parseInt(e.target.value, 10);
      CONFIG.previousDialogsLimit = Number.isFinite(nextValue)
        ? Math.min(10, Math.max(1, nextValue))
        : DEFAULT_PREVIOUS_TICKETS_TO_LOAD;
      e.target.value = String(CONFIG.previousDialogsLimit);
      saveConfig();
      if (CONFIG.autoLoadPreviousDialogs) {
        _historyLoadedForTicketId = null;
        clearPreviousDialogsFromView();
        initAutoLoad();
      }
    };

    const prevLimitField = panel.querySelector('#hde-cfg-prev-limit')?.closest('label');
    const prevDialogsToggle = panel.querySelector('#hde-cfg-prev-dialogs');
    const prevDialogsLabel = prevDialogsToggle && prevDialogsToggle.closest('label');
    const colleagueStaffsLink = panel.querySelector('#hde-colleague-staffs-link');

    if (colleagueStaffsLink && !colleagueStaffsLink.dataset.hdeBound) {
      colleagueStaffsLink.dataset.hdeBound = '1';
      colleagueStaffsLink.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        openStaffsDrawer();
      });
    }

    function syncPrevDialogsVisibility() {
      const show = CONFIG.autoLoadHistory;
      if (prevDialogsLabel) prevDialogsLabel.style.display = show ? '' : 'none';
      if (prevLimitField) prevLimitField.style.display = (show && CONFIG.autoLoadPreviousDialogs) ? 'flex' : 'none';
    }

    function syncColleagueStaffsLinkVisibility() {
      if (!colleagueStaffsLink) return;
      colleagueStaffsLink.style.display = CONFIG.colleagueStatuses ? 'inline-flex' : 'none';
    }

    syncPrevDialogsVisibility();
    syncColleagueStaffsLinkVisibility();

    // btnContainer мог уже существовать (SPA-перерисовка). Не дублируем btn.
    if (!btnContainer.querySelector('#hde-tools-btn')) {
      btnContainer.appendChild(btn);
    }

    if (!panel.parentElement) {
      document.body.appendChild(panel);
    }

    // Вставляем на уровень выше, чем '.menu-plugins' (внутрь '.menu')
    // Иначе SPA может выкинуть/пересобрать узел '.menu__items'.
    if (menu && btnContainer && !menu.contains(btnContainer)) {
      menu.appendChild(btnContainer);
    } else if (!menu && (menuItems && !menuItems.contains(btnContainer))) {
      menuItems.appendChild(btnContainer);
    }

    // Если '.menu-plugins' уже есть — можно попробовать вставить рядом, но без риска отката
    // (главное — чтобы контейнер был в '.menu' и был виден сразу)
    if (menuPlugins && menuItems && menu && btnContainer) {
      try { menuItems.insertBefore(btnContainer, menuPlugins); } catch (e) {}
    }

    // Наблюдатель: если Vue снова пересобирает '.menu__items' — переткнём в ближайший '.menu'
    // (а не в "первый найденный .menu" — это ломается, если элементов несколько)
    if (!window.__hdeToolsMenuObserver) {
      window.__hdeToolsMenuObserver = true;
      const menuObserver = new MutationObserver(function () {
        const b = document.getElementById('hde-tools-menu');
        if (!b) return;

        const targetMenu = b.closest('.menu') || document.querySelector('.menu');
        if (targetMenu && !targetMenu.contains(b)) {
          try { targetMenu.appendChild(b); } catch (e) {}
        }
      });
      menuObserver.observe(document.body, { childList: true, subtree: true });
    }
  }

  // ─── Перемещение кнопки истории в .ticket-detail__title ────────
  // Физически переносим в нужное место. Vue-обработчики сидят на элементе,
  // поэтому дропдаун работает. Проблема закрытия — Vue слушает document click
  // и проверяет contains() относительно исходного парента —
  // после переноса это сохраняется, поэтому всё должно работать.
  function moveHistoryButton() {
    if (!CONFIG.autoLoadHistory || !CONFIG.autoLoadPreviousDialogs) return;
    const origBtn = document.querySelector('.ticket-detail__history');
    const titleEl = document.querySelector('.ticket-detail__title');
    if (!origBtn || !titleEl) return;
    if (titleEl.contains(origBtn)) return;
    titleEl.appendChild(origBtn);
  }

  function onBodyReady(fn) {
    if (document.body) {
      fn();
      return;
    }
    document.addEventListener('DOMContentLoaded', fn, { once: true });
  }

  // Ранний плейсхолдер левой колонки, чтобы не было "вспышки" при перезагрузке.
  (function bootLeftTabsColumnEarly() {
    if (!getEarlyLeftTabsMirrorFromStorage()) return;

    const tryInsert = () => {
      const layout = findTicketMetroLayout();
      if (!layout) return false;
      const column = ensureLeftTabsColumnInLayout(layout.metroContainer, layout.ticketContainer);
      ensureEarlyLeftTabsSkeleton(column);
      return true;
    };

    onBodyReady(() => {
      if (tryInsert()) return;
      const observer = new MutationObserver(() => {
        if (tryInsert()) observer.disconnect();
      });
      observer.observe(document.body, { childList: true, subtree: true });
      setTimeout(() => observer.disconnect(), 5000);
    });
  })();

  // Ранний запуск меню: показываем кнопку сразу после появления body/menu,
  // не дожидаясь полного init(), чтобы убрать визуальную задержку.
  (function bootSettingsMenuEarly() {
    if (window.__hdeToolsMenuEarlyBoot) return;
    window.__hdeToolsMenuEarlyBoot = true;

    const isReady = () => {
      const btn = document.getElementById('hde-tools-btn');
      const panel = document.getElementById(MENU_PANEL_ID);
      return !!(btn && panel && btn.dataset.hdeToolsBound === '1');
    };

    const start = () => {
      loadConfig();
      initSettingsMenu();

      // На некоторых загрузках Vue дорисовывает меню с задержкой.
      // Короткий "быстрый догон" делает появление кнопки визуально мгновенным.
      if (window.__hdeToolsMenuEarlyRetryTimer) {
        clearInterval(window.__hdeToolsMenuEarlyRetryTimer);
      }
      const startedAt = Date.now();
      window.__hdeToolsMenuEarlyRetryTimer = setInterval(() => {
        if (isReady() || (Date.now() - startedAt) > 5000) {
          clearInterval(window.__hdeToolsMenuEarlyRetryTimer);
          window.__hdeToolsMenuEarlyRetryTimer = null;
          return;
        }
        initSettingsMenu();
      }, 80);

      if (!window.__hdeToolsMenuEarlyObserver && document.body) {
        window.__hdeToolsMenuEarlyObserver = new MutationObserver(() => {
          if (!isReady()) initSettingsMenu();
        });
        window.__hdeToolsMenuEarlyObserver.observe(document.body, { childList: true, subtree: true });
      }
    };

    if (document.body) {
      start();
      return;
    }

    const root = document.documentElement;
    if (!root) return;
    const observer = new MutationObserver(() => {
      if (!document.body) return;
      observer.disconnect();
      start();
    });
    observer.observe(root, { childList: true });
  })();

  (function initHistoryButtonMover() {
    onBodyReady(function () {
      moveHistoryButton();
      if (!window.__hdeHistoryBtnObserver) {
        window.__hdeHistoryBtnObserver = true;
        new MutationObserver(function () {
          moveHistoryButton();
          injectHistoryCloseButton();
        }).observe(document.body, { childList: true, subtree: true });
      }
    });
  })();

  // ─── Кнопка «закрыть» в дропдауне истории ────────────────
  function injectHistoryCloseButton() {
    if (!CONFIG.autoLoadHistory || !CONFIG.autoLoadPreviousDialogs) return;
    const panel = document.querySelector('.ticket-detail__history-tickets');
    if (!panel) return;
    if (panel.querySelector('.hde-history-close')) return;

    const btn = document.createElement('button');
    btn.className = 'hde-history-close';
    btn.title = 'Скрыть';
    btn.textContent = '✕ Скрыть';
    btn.style.cssText = [
      'display:block',
      'width:100%',
      'margin:0',
      'padding:6px 12px',
      'background:#f5f7fa',
      'border:none',
      'border-bottom:1px solid #ebeef5',
      'cursor:pointer',
      'font-size:12px',
      'color:#606266',
      'text-align:left'
    ].join(';');
    btn.addEventListener('mouseenter', function () { btn.style.background = '#ecf5ff'; btn.style.color = '#409eff'; });
    btn.addEventListener('mouseleave', function () { btn.style.background = '#f5f7fa'; btn.style.color = '#606266'; });
    btn.addEventListener('click', function (e) {
      e.stopPropagation();
      panel.style.display = 'none';
    });

    panel.insertBefore(btn, panel.firstChild);
  }

  // ─── Init ────────────────────────────────────────────────
  // ============================================================
  // 8) Boot / Init / Cleanup
  // ============================================================

  function init() {
    loadConfig();
    syncNativeTicketTabsVisibilityClass();
    applyThemeFromConfig();
    initSettingsMenu();
    initLeftTabsMirrorObserver();
    syncLeftTabsOnHrefChange();
    syncLeftTabsMirror();
    syncColleagueStatusesModule();
    injectStyle();
    if (CONFIG.autoLoadHistory) injectPaginationStyle();
    processAllMessages();
    initAutoLoad();
    observeMessages();
    moveHistoryButton();
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }

  window.addEventListener('beforeunload', () => {
    flushLeftTabsCacheNow();
    stopColleagueStatuses();
    if (_leftTabsPreviewPollInterval) clearInterval(_leftTabsPreviewPollInterval);
    if (_leftTabsDepartmentPollInterval) clearInterval(_leftTabsDepartmentPollInterval);
  });
  window.addEventListener('pagehide', () => {
    flushLeftTabsCacheNow();
  });

  // SPA навигация — перезапуск при смене URL
  var lastUrl = location.href;
  onBodyReady(function () {
    new MutationObserver(function () {
      if (location.href !== lastUrl) {
        lastUrl = location.href;
        _loadedPages.clear(); // сбрасываем загруженные страницы
        _historyLoadedForTicketId = null;
        syncLeftTabsOnHrefChange();
        setTimeout(function () {
          syncNativeTicketTabsVisibilityClass();
          applyThemeFromConfig();
          syncLeftTabsOnHrefChange();
          syncLeftTabsMirror();
          syncColleagueStatusesModule();
          injectStyle();
          processAllMessages();
          initAutoLoad();
          moveHistoryButton();
        }, 500);
      }
    // Только прямые дети body — нам нужна лишь смена URL, не весь DOM
    }).observe(document.body, { childList: true });
  });

})();