<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TelePush — Telegram</title>
    <link rel="icon" href="/static/favicon.ico" type="image/x-icon">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <style>
        * { box-sizing: border-box; }
        /* Telegram Desktop dark blue palette (как в Desktop клиенте) */
        :root {
            --bg-app: #17212b;
            --bg-side: #17212b;
            --bg-side-hover: #202b36;
            --bg-side-active: #2b5278;
            --bg-chat: #0e1621;
            --bg-chat-pattern: #0e1621;
            --bg-input: #242f3d;
            --bg-bubble-in: #182533;
            --bg-bubble-out: #2b5278;
            --border: #1f2c38;
            --divider: #0c151e;
            --text: #ffffff;
            --text-muted: #6c7883;
            --text-secondary: #7e899c;
            --accent: #5288c1;
            --accent-light: #6ab2f2;
            --link: #6ab2f2;
            --success: #4dcd5e;
            --time-out: #7da8d3;
            --time-in: #6c7883;
        }
        html, body {
            margin: 0;
            padding: 0;
            height: 100vh;
            background: var(--bg-app);
            color: var(--text);
            font-family: "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
            font-size: 14px;
            overflow: hidden;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }
        .layout {
            display: grid;
            grid-template-columns: 260px 1fr;
            height: 100vh;
        }
        @media (min-width: 1100px) {
            .layout { grid-template-columns: 300px 1fr; }
        }
        @media (min-width: 1400px) {
            .layout { grid-template-columns: 360px 1fr; }
        }
        .layout.with-info {
            grid-template-columns: 260px 1fr 320px;
        }
        @media (min-width: 1100px) {
            .layout.with-info { grid-template-columns: 300px 1fr 320px; }
        }
        @media (min-width: 1400px) {
            .layout.with-info { grid-template-columns: 360px 1fr 360px; }
        }
        /* === LEFT SIDEBAR === */
        .sidebar {
            background: var(--bg-side);
            border-right: 1px solid var(--divider);
            display: flex;
            flex-direction: column;
            min-width: 0;
        }
        .sidebar-top {
            padding: 8px 8px 8px 12px;
            display: flex;
            align-items: center;
            gap: 10px;
            min-height: 56px;
        }
        .menu-btn {
            background: transparent;
            border: none;
            color: var(--text-secondary);
            cursor: pointer;
            font-size: 20px;
            padding: 8px;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.15s;
        }
        .menu-btn:hover { background: var(--bg-side-hover); color: var(--text); }
        .search-wrap {
            flex: 1;
            position: relative;
        }
        .search-wrap i {
            position: absolute;
            left: 14px;
            top: 50%;
            transform: translateY(-50%);
            color: var(--text-muted);
            font-size: 16px;
        }
        .search-wrap input {
            width: 100%;
            background: var(--bg-input);
            border: none;
            border-radius: 22px;
            color: var(--text);
            padding: 10px 16px 10px 40px;
            font-size: 14px;
            outline: none;
            font-family: inherit;
        }
        .search-wrap input:focus { background: #2a3441; }
        .search-wrap input::placeholder { color: var(--text-muted); }
        .acc-bar {
            padding: 10px 16px;
            border-bottom: 1px solid var(--divider);
            display: flex;
            align-items: center;
            gap: 10px;
            background: rgba(0,0,0,0.15);
        }
        .acc-bar .acc-info {
            flex: 1;
            min-width: 0;
            overflow: hidden;
        }
        .acc-bar .acc-info > div:first-child {
            font-weight: 500;
            font-size: 13px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .acc-bar .acc-info > div:last-child {
            font-size: 11px;
            color: var(--text-muted);
        }
        .dialogs {
            flex: 1;
            overflow-y: auto;
        }
        .dialog-item {
            padding: 9px 12px 9px 12px;
            cursor: pointer;
            display: flex;
            gap: 10px;
            align-items: center;
            transition: background 0.1s;
            position: relative;
        }
        .dialog-item:hover { background: var(--bg-side-hover); }
        .dialog-item.active {
            background: var(--bg-side-active) !important;
        }
        .dialog-item.active .dialog-name,
        .dialog-item.active .dialog-time,
        .dialog-item.active .dialog-last { color: #fff !important; }
        .dialog-item.active .badge-unread { background: #fff; color: var(--bg-side-active); }
        .avatar {
            width: 54px;
            height: 54px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 500;
            font-size: 20px;
            color: #fff;
            flex-shrink: 0;
            position: relative;
            overflow: hidden;
            background: linear-gradient(135deg, #72d5fd, #2a82e7);
        }
        .avatar img {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        .dialog-text { flex: 1; min-width: 0; padding-top: 2px; }
        .dialog-title-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 2px;
        }
        .dialog-name {
            font-weight: 500;
            font-size: 14.5px;
            color: var(--text);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .dialog-time {
            font-size: 12px;
            color: var(--text-muted);
            flex-shrink: 0;
            margin-left: 8px;
        }
        .dialog-bottom-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .dialog-last {
            font-size: 13px;
            color: var(--text-muted);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            line-height: 1.3;
        }
        .badge-unread {
            background: var(--accent);
            color: #fff;
            border-radius: 12px;
            padding: 1px 7px;
            font-size: 12px;
            font-weight: 500;
            min-width: 22px;
            height: 22px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            margin-left: 6px;
        }
        /* === MIDDLE: CHAT === */
        .chat {
            display: flex;
            flex-direction: column;
            min-width: 0;
            background: var(--bg-chat);
            position: relative;
        }
        .chat::before {
            /* Subtle pattern like Telegram Desktop */
            content: '';
            position: absolute;
            inset: 0;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='420' height='420' viewBox='0 0 420 420'><g fill='%23182533' fill-opacity='0.4'><circle cx='30' cy='30' r='2'/><circle cx='90' cy='80' r='1.5'/><circle cx='160' cy='40' r='2'/><circle cx='230' cy='90' r='1.5'/><circle cx='320' cy='60' r='2'/><circle cx='390' cy='110' r='1.5'/><circle cx='50' cy='180' r='2'/><circle cx='130' cy='200' r='1.5'/><circle cx='210' cy='230' r='2'/><circle cx='290' cy='180' r='1.5'/><circle cx='370' cy='220' r='2'/><circle cx='80' cy='300' r='1.5'/><circle cx='180' cy='340' r='2'/><circle cx='270' cy='310' r='1.5'/><circle cx='340' cy='370' r='2'/><circle cx='40' cy='400' r='1.5'/></g></svg>");
            opacity: 0.4;
            pointer-events: none;
            z-index: 0;
        }
        .chat-empty {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--text-muted);
            flex-direction: column;
            gap: 8px;
            position: relative;
            z-index: 1;
        }
        .chat-empty .empty-pill {
            background: rgba(0, 0, 0, 0.4);
            backdrop-filter: blur(10px);
            padding: 12px 24px;
            border-radius: 20px;
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .chat-header {
            padding: 8px 16px;
            border-bottom: 1px solid var(--divider);
            display: flex;
            align-items: center;
            gap: 12px;
            background: var(--bg-side);
            min-height: 56px;
            position: relative;
            z-index: 2;
        }
        .chat-header .info-btn {
            background: transparent;
            border: none;
            color: var(--text-secondary);
            cursor: pointer;
            font-size: 20px;
            padding: 8px;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.15s;
        }
        .chat-header .info-btn:hover { background: var(--bg-side-hover); color: var(--text); }
        .chat-header .header-info {
            flex: 1;
            min-width: 0;
            cursor: pointer;
        }
        .chat-title {
            font-weight: 500;
            font-size: 15.5px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .chat-sub {
            font-size: 13px;
            color: var(--text-muted);
            margin-top: 1px;
        }
        .chat-sub.online { color: var(--accent-light); }
        .messages {
            flex: 1;
            overflow-y: auto;
            padding: 12px 0 8px;
            display: flex;
            flex-direction: column;
            gap: 2px;
            position: relative;
            z-index: 1;
        }
        .messages-inner {
            display: flex;
            flex-direction: column;
            max-width: 728px;
            width: 100%;
            margin: 0 auto;
            padding: 0 12px;
            gap: 2px;
        }
        .date-divider {
            text-align: center;
            margin: 16px 0 8px;
            position: sticky;
            top: 8px;
            z-index: 5;
        }
        .date-divider span {
            background: rgba(0, 0, 0, 0.4);
            backdrop-filter: blur(10px);
            color: #fff;
            padding: 4px 10px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: 500;
        }
        .msg-row {
            display: flex;
            margin: 1px 0;
        }
        .msg-row.cluster-end { margin-bottom: 8px; }
        .msg-row.out { justify-content: flex-end; }
        .bubble {
            max-width: min(70%, 520px);
            padding: 6px 9px 6px 11px;
            border-radius: 12px;
            background: var(--bg-bubble-in);
            position: relative;
            word-wrap: break-word;
            font-size: 14.5px;
            line-height: 1.36;
            color: var(--text);
        }
        .msg-row.out .bubble { background: var(--bg-bubble-out); }
        /* Tail for last bubble in cluster (real Telegram style) */
        .msg-row.cluster-end:not(.out) .bubble {
            border-bottom-left-radius: 4px;
        }
        .msg-row.cluster-end:not(.out) .bubble::before {
            content: '';
            position: absolute;
            bottom: 0;
            left: -8px;
            width: 12px;
            height: 18px;
            background: var(--bg-bubble-in);
            clip-path: path('M 12 18 L 0 18 Q 8 18 8 10 Q 8 14 12 14 Z');
        }
        .msg-row.cluster-end.out .bubble {
            border-bottom-right-radius: 4px;
        }
        .msg-row.cluster-end.out .bubble::after {
            content: '';
            position: absolute;
            bottom: 0;
            right: -8px;
            width: 12px;
            height: 18px;
            background: var(--bg-bubble-out);
            clip-path: path('M 0 18 L 12 18 Q 4 18 4 10 Q 4 14 0 14 Z');
        }
        /* Cluster: middle bubbles get reduced corners */
        .msg-row.cluster-middle:not(.out) .bubble {
            border-bottom-left-radius: 4px;
            border-top-left-radius: 4px;
        }
        .msg-row.cluster-middle.out .bubble {
            border-bottom-right-radius: 4px;
            border-top-right-radius: 4px;
        }
        .msg-row.cluster-start:not(.out) .bubble {
            border-bottom-left-radius: 4px;
        }
        .msg-row.cluster-start.out .bubble {
            border-bottom-right-radius: 4px;
        }
        .bubble .sender {
            font-size: 13px;
            color: #6ab2f2;
            font-weight: 500;
            margin-bottom: 1px;
            cursor: pointer;
        }
        .bubble .text {
            white-space: pre-wrap;
            word-wrap: break-word;
            overflow-wrap: anywhere;
        }
        .bubble .meta {
            display: inline-block;
            float: right;
            margin: 6px 0 -2px 8px;
            font-size: 11px;
            color: var(--time-in);
            line-height: 1;
            user-select: none;
            white-space: nowrap;
        }
        .msg-row.out .bubble .meta { color: var(--time-out); }
        .bubble .meta .check {
            display: inline-block;
            margin-left: 2px;
            color: var(--accent-light);
            font-size: 13px;
            line-height: 1;
        }
        .bubble.media-only { padding: 3px; }
        .bubble.media-only .text { padding: 3px 8px 3px; }
        .bubble.media-only .meta { padding: 0 6px 4px; float: right; }
        .bubble img.media,
        .bubble video.media {
            max-width: 100%;
            border-radius: 8px;
            margin: 0;
            cursor: pointer;
            max-height: 380px;
            display: block;
        }
        .bubble.sticker {
            background: transparent !important;
            padding: 0;
            box-shadow: none;
        }
        .bubble.sticker::before, .bubble.sticker::after { display: none !important; }
        .bubble.sticker img.media {
            max-width: 180px;
            max-height: 180px;
            border-radius: 0;
        }
        .bubble audio.media {
            width: 100%;
            max-width: 280px;
            height: 36px;
            margin: 4px 0;
        }
        .bubble .file-att {
            display: flex;
            gap: 10px;
            align-items: center;
            padding: 4px 0;
            cursor: pointer;
        }
        .bubble .file-att .file-icon {
            width: 44px;
            height: 44px;
            border-radius: 50%;
            background: var(--accent-light);
            color: #fff;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
        }
        .bubble .file-att .file-name {
            font-size: 14px;
            font-weight: 500;
            color: var(--text);
        }
        .bubble .file-att .file-size {
            font-size: 12px;
            color: var(--time-in);
        }
        .msg-row.out .bubble .file-att .file-size { color: var(--time-out); }

        /* Context menu (right click on bubble) */
        .ctx-menu {
            position: fixed;
            background: #2c3e50;
            border-radius: 10px;
            padding: 4px 0;
            box-shadow: 0 4px 24px rgba(0,0,0,0.6);
            z-index: 10000;
            min-width: 180px;
            font-size: 14px;
        }
        .ctx-menu .item {
            padding: 9px 16px;
            cursor: pointer;
            display: flex;
            align-items: center;
            gap: 12px;
            color: var(--text);
        }
        .ctx-menu .item:hover { background: var(--bg-side-hover); }
        .ctx-menu .item.danger { color: #e25555; }
        .ctx-menu .item i { font-size: 16px; width: 20px; }

        /* Input row */
        .input-row {
            border-top: 1px solid var(--divider);
            padding: 8px 16px;
            display: flex;
            gap: 8px;
            align-items: flex-end;
            background: var(--bg-side);
            position: relative;
            z-index: 2;
        }
        .input-attach, .input-emoji {
            background: transparent;
            border: none;
            color: var(--text-secondary);
            cursor: pointer;
            font-size: 22px;
            padding: 0 6px;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: color 0.15s;
        }
        .input-attach:hover, .input-emoji:hover { color: var(--accent-light); }
        .input-row .input-wrap {
            flex: 1;
            background: var(--bg-input);
            border-radius: 12px;
            display: flex;
            align-items: flex-end;
            padding: 0 8px;
        }
        .input-row textarea {
            flex: 1;
            background: transparent;
            border: none;
            color: var(--text);
            padding: 10px 8px;
            font-size: 15px;
            font-family: inherit;
            resize: none;
            outline: none;
            min-height: 24px;
            max-height: 200px;
            line-height: 1.4;
        }
        .input-row textarea::placeholder { color: var(--text-muted); }
        .send-btn {
            background: var(--accent);
            border: none;
            color: #fff;
            border-radius: 50%;
            width: 44px;
            height: 44px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 18px;
            flex-shrink: 0;
            transition: background 0.15s;
        }
        .send-btn:hover { background: var(--accent-light); }
        .send-btn:disabled { background: #2a3a4a; cursor: not-allowed; }
        /* === RIGHT INFO PANEL === */
        .chat-info {
            background: var(--bg-side);
            border-left: 1px solid var(--divider);
            overflow-y: auto;
            display: none;
            padding: 0;
        }
        .layout.with-info .chat-info { display: block; }
        .info-header {
            background: var(--bg-side);
            padding: 16px;
            text-align: center;
            border-bottom: 1px solid var(--divider);
        }
        .info-avatar {
            width: 120px;
            height: 120px;
            margin: 0 auto 12px;
            border-radius: 50%;
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 44px;
            font-weight: 500;
            color: #fff;
            background: linear-gradient(135deg, #72d5fd, #2a82e7);
            position: relative;
        }
        .info-avatar img {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        .info-name {
            font-size: 18px;
            font-weight: 500;
            margin-bottom: 4px;
        }
        .info-status {
            font-size: 13px;
            color: var(--text-muted);
        }
        .info-section {
            padding: 8px 0;
            border-bottom: 8px solid var(--divider);
        }
        .info-row {
            padding: 10px 16px;
            display: flex;
            align-items: center;
            gap: 16px;
            cursor: pointer;
        }
        .info-row:hover { background: var(--bg-side-hover); }
        .info-row i {
            font-size: 20px;
            color: var(--text-muted);
            width: 24px;
            text-align: center;
        }
        .info-row .row-content {
            flex: 1;
            min-width: 0;
        }
        .info-row .row-value {
            font-size: 14.5px;
            color: var(--text);
            word-break: break-all;
        }
        .info-row .row-label {
            font-size: 13px;
            color: var(--text-muted);
            margin-top: 1px;
        }

        /* Scrollbar */
        ::-webkit-scrollbar { width: 8px; }
        ::-webkit-scrollbar-track { background: transparent; }
        ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 4px; }
        ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.2); }
        /* Spinner */
        @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
        .spin { animation: spin 1s linear infinite; }
        .toast {
            position: fixed;
            bottom: 24px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0,0,0,0.8);
            color: #fff;
            padding: 10px 20px;
            border-radius: 8px;
            box-shadow: 0 6px 20px rgba(0,0,0,0.6);
            z-index: 10001;
            font-size: 14px;
            opacity: 0;
            transition: opacity 0.2s, transform 0.2s;
            pointer-events: none;
        }
        .toast.show { opacity: 1; transform: translateX(-50%) translateY(-4px); }
        .toast.error { background: #c0392b; }
        .toast.success { background: #2c8f4a; }

        /* Reactions popup (наведение на бабблу) */
        .reactions-popup {
            position: absolute;
            top: -36px;
            background: #2c3e50;
            border-radius: 22px;
            padding: 4px 8px;
            display: flex;
            gap: 4px;
            box-shadow: 0 4px 16px rgba(0,0,0,0.5);
            z-index: 50;
        }
        .msg-row.out .reactions-popup { right: 0; }
        .msg-row:not(.out) .reactions-popup { left: 0; }
        .reactions-popup .react-btn {
            background: transparent;
            border: none;
            color: #fff;
            cursor: pointer;
            font-size: 18px;
            padding: 4px 6px;
            border-radius: 50%;
            transition: transform 0.15s, background 0.15s;
            line-height: 1;
        }
        .reactions-popup .react-btn:hover {
            transform: scale(1.4);
            background: rgba(255,255,255,0.1);
        }
        .msg-reactions {
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            margin-top: 4px;
        }
        .msg-reactions .reaction {
            background: rgba(106, 178, 242, 0.2);
            border: 1px solid rgba(106, 178, 242, 0.4);
            border-radius: 12px;
            padding: 2px 8px;
            font-size: 12px;
            color: var(--accent-light);
            display: inline-flex;
            align-items: center;
            gap: 3px;
        }
        .msg-reactions .reaction.mine {
            background: rgba(82, 136, 193, 0.4);
            border-color: var(--accent-light);
            color: #fff;
        }

        /* Drag & drop overlay */
        .dnd-overlay {
            position: fixed;
            inset: 0;
            background: rgba(43, 82, 120, 0.85);
            backdrop-filter: blur(8px);
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 9999;
            pointer-events: none;
        }
        .dnd-overlay.active { display: flex; }
        .dnd-overlay .dnd-msg {
            background: var(--bg-side);
            padding: 32px 48px;
            border-radius: 16px;
            border: 3px dashed var(--accent-light);
            text-align: center;
            color: #fff;
            font-size: 16px;
        }
        .dnd-overlay .dnd-msg i {
            font-size: 64px;
            display: block;
            margin-bottom: 12px;
            color: var(--accent-light);
        }

        /* Emoji picker */
        .emoji-panel {
            position: absolute;
            bottom: 60px;
            left: 12px;
            background: var(--bg-side);
            border: 1px solid var(--border);
            border-radius: 12px;
            padding: 8px;
            display: none;
            grid-template-columns: repeat(8, 1fr);
            gap: 4px;
            box-shadow: 0 6px 24px rgba(0,0,0,0.5);
            z-index: 100;
            max-width: 320px;
        }
        .emoji-panel.show { display: grid; }
        .emoji-panel button {
            background: transparent;
            border: none;
            font-size: 22px;
            cursor: pointer;
            padding: 4px;
            border-radius: 6px;
            transition: background 0.15s;
            line-height: 1;
        }
        .emoji-panel button:hover { background: var(--bg-side-hover); }
    </style>
</head>
<body>
    <div class="layout" id="root-layout">
        <!-- LEFT: dialogs -->
        <div class="sidebar">
            <div class="sidebar-top">
                <button class="menu-btn" onclick="loadDialogs()" title="Обновить">
                    <i class="bi bi-arrow-clockwise"></i>
                </button>
                <div class="search-wrap">
                    <i class="bi bi-search"></i>
                    <input type="text" id="search-input" placeholder="Поиск" oninput="filterDialogs()">
                </div>
            </div>
            <div class="acc-bar">
                <div class="avatar" style="width:36px;height:36px;font-size:14px;" id="acc-avatar">
                    <img id="acc-avatar-img" src="" onerror="this.style.display='none'">
                    <span id="acc-avatar-letter">?</span>
                </div>
                <div class="acc-info">
                    <div id="acc-name">+{{ phone }}</div>
                    <div id="acc-phone">+{{ phone }}</div>
                </div>
                <button class="menu-btn" onclick="openStories()" title="Истории" style="width:36px;height:36px;font-size:18px;">
                    <i class="bi bi-circle-half" style="background:linear-gradient(135deg,#ff885e,#a855f7);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;"></i>
                </button>
            </div>
            <!-- Stories carousel (hidden by default) -->
            <div id="stories-bar" style="display:none;padding:10px 12px;border-bottom:1px solid var(--divider);overflow-x:auto;white-space:nowrap;">
                <div id="stories-list" style="display:inline-flex;gap:10px;"></div>
            </div>
            <div class="dialogs" id="dialogs-list">
                <div style="text-align:center;color:var(--text-muted);padding:40px 20px;">
                    <i class="bi bi-arrow-repeat spin" style="font-size:24px;display:block;margin-bottom:8px;"></i>
                    Загрузка диалогов…
                </div>
            </div>
        </div>

        <!-- MIDDLE: chat -->
        <div class="chat">
            <div class="chat-empty" id="chat-empty">
                <div class="empty-pill">
                    <i class="bi bi-chat-square-dots"></i>
                    Выберите чат
                </div>
            </div>
            <div id="chat-view" style="display:none;flex-direction:column;flex:1;min-height:0;">
                <div class="chat-header">
                    <div class="header-info" onclick="toggleInfo()" style="display:flex;align-items:center;gap:12px;flex:1;">
                        <div class="avatar" id="chat-avatar" style="width:42px;height:42px;font-size:16px;">
                            <img id="chat-avatar-img" src="" onerror="this.style.display='none'">
                            <span id="chat-avatar-letter">?</span>
                        </div>
                        <div style="flex:1;min-width:0;overflow:hidden;">
                            <div class="chat-title" id="chat-title">—</div>
                            <div class="chat-sub" id="chat-sub"></div>
                        </div>
                    </div>
                    <button class="info-btn" onclick="toggleSearch()" title="Поиск в чате">
                        <i class="bi bi-search"></i>
                    </button>
                    <button class="info-btn" onclick="toggleInfo()" title="Информация">
                        <i class="bi bi-three-dots-vertical"></i>
                    </button>
                </div>
                <div id="search-bar" style="display:none;padding:8px 12px;background:var(--bg-input);border-bottom:1px solid var(--divider);position:relative;z-index:2;">
                    <input type="text" id="search-msg-input" placeholder="Поиск в этом чате…" onkeydown="onSearchKey(event)"
                           style="width:100%;background:var(--bg-side);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:8px 14px;font-size:14px;outline:none;font-family:inherit;">
                    <div id="search-results" style="margin-top:8px;max-height:300px;overflow-y:auto;font-size:13px;"></div>
                </div>
                <div class="messages" id="messages">
                    <div class="messages-inner" id="messages-inner"></div>
                </div>
                <div class="input-row" style="position:relative;">
                    <button class="input-attach" onclick="toggleEmojiPanel()" title="Эмодзи" style="position:relative;">
                        <i class="bi bi-emoji-smile"></i>
                    </button>
                    <button class="input-attach" onclick="attachFile()" title="Прикрепить файл">
                        <i class="bi bi-paperclip"></i>
                    </button>
                    <div class="input-wrap">
                        <textarea id="msg-input" placeholder="Сообщение" rows="1" onkeydown="onInputKey(event)" oninput="autoResize(this)"></textarea>
                    </div>
                    <button class="send-btn" id="send-btn" onclick="sendMessage()" title="Отправить">
                        <i class="bi bi-send-fill"></i>
                    </button>
                    <div class="emoji-panel" id="emoji-panel"></div>
                </div>
                <input type="file" id="file-picker" style="display:none" onchange="onFilePicked(event)" multiple>
            </div>
        </div>
        <!-- Stories viewer (overlay) -->
        <div id="stories-viewer" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.94);z-index:9000;align-items:center;justify-content:center;">
            <div id="stories-content" style="position:relative;max-width:420px;width:90%;height:85vh;display:flex;align-items:center;justify-content:center;flex-direction:column;">
                <div id="stories-progress" style="position:absolute;top:0;left:0;right:0;display:flex;gap:3px;padding:6px;z-index:2;"></div>
                <div id="stories-meta" style="position:absolute;top:18px;left:0;right:0;display:flex;align-items:center;gap:10px;padding:6px 12px;z-index:2;color:#fff;">
                    <div class="avatar" id="stories-avatar" style="width:32px;height:32px;font-size:12px;"></div>
                    <div style="flex:1;font-size:14px;font-weight:500;" id="stories-name">—</div>
                    <button onclick="closeStories()" style="background:transparent;border:none;color:#fff;font-size:24px;cursor:pointer;">✕</button>
                </div>
                <img id="stories-img" style="max-width:100%;max-height:100%;border-radius:8px;display:none;" />
                <video id="stories-video" style="max-width:100%;max-height:100%;border-radius:8px;display:none;" autoplay muted playsinline></video>
                <div style="position:absolute;left:0;top:0;bottom:0;width:50%;cursor:pointer;" onclick="storyPrev()"></div>
                <div style="position:absolute;right:0;top:0;bottom:0;width:50%;cursor:pointer;" onclick="storyNext()"></div>
                <div id="stories-caption" style="position:absolute;bottom:12px;left:12px;right:12px;color:#fff;font-size:13px;background:rgba(0,0,0,0.5);padding:8px 12px;border-radius:8px;display:none;"></div>
            </div>
        </div>

        <!-- DnD overlay -->
        <div class="dnd-overlay" id="dnd-overlay">
            <div class="dnd-msg">
                <i class="bi bi-cloud-upload"></i>
                <div>Отпусти файл чтобы отправить</div>
            </div>
        </div>

        <!-- RIGHT: chat info -->
        <div class="chat-info" id="chat-info-panel"></div>
    </div>

    <div class="toast" id="toast"></div>

    <script>
        const PHONE = "{{ phone }}";
        let _allDialogs = [];
        let _currentChat = null;
        let _refreshTimer = null;
        let _myId = null;

        function escHtml(s) {
            if (s === null || s === undefined) return '';
            return String(s)
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;');
        }

        function showToast(msg, kind) {
            const t = document.getElementById('toast');
            t.textContent = msg;
            t.className = 'toast show' + (kind === 'error' ? ' error' : (kind === 'success' ? ' success' : ''));
            clearTimeout(t._tt);
            t._tt = setTimeout(() => { t.className = 'toast'; }, 2400);
        }

        // Telegram-like avatar gradient palette (8 colors)
        function avatarGradient(id) {
            const grads = [
                'linear-gradient(135deg,#ff885e,#ff516a)', // red
                'linear-gradient(135deg,#ffcd6a,#ffa85c)', // orange
                'linear-gradient(135deg,#e0a2f3,#d669ed)', // violet
                'linear-gradient(135deg,#a0de7e,#54cb68)', // green
                'linear-gradient(135deg,#53edd6,#28c9b7)', // cyan
                'linear-gradient(135deg,#72d5fd,#2a82e7)', // blue
                'linear-gradient(135deg,#fb8b6f,#dd587a)', // pink
                'linear-gradient(135deg,#a4ce92,#629558)'  // dark green
            ];
            return grads[Math.abs(id|0) % grads.length];
        }

        function timeStr(iso) {
            if (!iso) return '';
            try {
                const dt = new Date(iso);
                const now = new Date();
                if (dt.toDateString() === now.toDateString()) {
                    return dt.getHours() + ':' + (dt.getMinutes()<10?'0':'') + dt.getMinutes();
                }
                const diffDays = Math.floor((now - dt) / 86400000);
                if (diffDays < 7) {
                    const days = ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'];
                    return days[dt.getDay()];
                }
                return dt.getDate() + '.' + ((dt.getMonth()+1)<10?'0':'') + (dt.getMonth()+1) + '.' + String(dt.getFullYear()).slice(-2);
            } catch(e) { return ''; }
        }
        function fullTimeStr(iso) {
            try {
                const dt = new Date(iso);
                return dt.getHours() + ':' + (dt.getMinutes()<10?'0':'') + dt.getMinutes();
            } catch(e) { return ''; }
        }
        function dateLabel(iso) {
            try {
                const dt = new Date(iso);
                const now = new Date();
                if (dt.toDateString() === now.toDateString()) return 'Сегодня';
                const yesterday = new Date(now.getTime() - 86400000);
                if (dt.toDateString() === yesterday.toDateString()) return 'Вчера';
                const months = ['января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'];
                if (dt.getFullYear() === now.getFullYear()) {
                    return dt.getDate() + ' ' + months[dt.getMonth()];
                }
                return dt.getDate() + ' ' + months[dt.getMonth()] + ' ' + dt.getFullYear();
            } catch(e) { return ''; }
        }

        function loadAccountInfo() {
            fetch('/api/tg/user_info?chat_id=me').then(r => r.json()).then(d => {
                if (d && (d.first_name || d.title)) {
                    const name = ((d.first_name || '') + ' ' + (d.last_name || '')).trim();
                    document.getElementById('acc-name').textContent = name || ('+' + PHONE);
                    document.getElementById('acc-avatar-letter').textContent = (name || '?').charAt(0).toUpperCase();
                    const av = document.getElementById('acc-avatar');
                    av.style.background = avatarGradient(d.id || 0);
                    const img = document.getElementById('acc-avatar-img');
                    img.src = '/api/tg/avatar?chat_id=me';
                    img.style.display = '';
                    img.onerror = function() { this.style.display = 'none'; };
                    if (d.id) _myId = d.id;
                }
            }).catch(() => {});
        }

        function loadDialogs() {
            const list = document.getElementById('dialogs-list');
            fetch('/api/tg/dialogs').then(r => r.json()).then(d => {
                if (d.error) {
                    list.innerHTML = '<div style="text-align:center;color:#f87171;padding:32px 20px;font-size:13px;"><i class="bi bi-exclamation-triangle" style="font-size:22px;display:block;margin-bottom:8px;"></i>' + escHtml(d.error) + '</div>';
                    return;
                }
                if (d.busy) {
                    list.innerHTML = '<div style="text-align:center;color:#f59e0b;padding:32px 20px;font-size:13px;"><i class="bi bi-lock" style="font-size:22px;display:block;margin-bottom:8px;"></i>' + escHtml(d.msg || 'Аккаунт занят') + '</div>';
                    return;
                }
                _allDialogs = d.dialogs || [];
                renderDialogs(_allDialogs);
            }).catch(() => {
                list.innerHTML = '<div style="text-align:center;color:#f87171;padding:32px 20px;">Ошибка загрузки</div>';
            });
        }

        function renderDialogs(arr) {
            const list = document.getElementById('dialogs-list');
            if (!arr.length) {
                list.innerHTML = '<div style="text-align:center;color:var(--text-muted);padding:40px 20px;"><i class="bi bi-inbox" style="font-size:24px;display:block;margin-bottom:8px;"></i>Нет чатов</div>';
                return;
            }
            list.innerHTML = arr.map(c => {
                const ini = (c.name || '?').charAt(0).toUpperCase();
                const ts = timeStr(c.date);
                const unread = c.unread > 0 ? '<span class="badge-unread">' + c.unread + '</span>' : '';
                const isActive = _currentChat && _currentChat.id === c.id ? ' active' : '';
                return '<div class="dialog-item' + isActive + '" data-id="' + c.id + '" data-name="' + escHtml(c.name) + '" data-type="' + escHtml(c.type) + '">' +
                    '<div class="avatar" style="background:' + avatarGradient(c.id) + ';">' +
                        '<img src="/api/tg/avatar?chat_id=' + c.id + '" onerror="this.style.display=\'none\'">' +
                        '<span>' + escHtml(ini) + '</span>' +
                    '</div>' +
                    '<div class="dialog-text">' +
                        '<div class="dialog-title-row">' +
                            '<span class="dialog-name">' + escHtml(c.name) + '</span>' +
                            '<span class="dialog-time">' + escHtml(ts) + '</span>' +
                        '</div>' +
                        '<div class="dialog-bottom-row">' +
                            '<span class="dialog-last">' + escHtml(c.last_message || '') + '</span>' +
                            unread +
                        '</div>' +
                    '</div>' +
                '</div>';
            }).join('');
            if (!list._bound) {
                list.addEventListener('click', function(e) {
                    const item = e.target.closest('.dialog-item');
                    if (!item) return;
                    const id = parseInt(item.dataset.id);
                    const name = item.dataset.name;
                    const type = item.dataset.type;
                    if (!isNaN(id)) openChat(id, name, type);
                });
                list._bound = true;
            }
        }

        function filterDialogs() {
            const q = document.getElementById('search-input').value.trim().toLowerCase();
            if (!q) { renderDialogs(_allDialogs); return; }
            const filtered = _allDialogs.filter(c =>
                (c.name || '').toLowerCase().includes(q) ||
                (c.last_message || '').toLowerCase().includes(q));
            renderDialogs(filtered);
        }

        function openChat(id, name, type) {
            _currentChat = { id: id, name: name, type: type };
            document.getElementById('chat-empty').style.display = 'none';
            document.getElementById('chat-view').style.display = 'flex';
            document.getElementById('chat-title').textContent = name;
            document.getElementById('chat-sub').textContent = type === 'user' ? 'был(а) недавно' : (type === 'channel' ? 'канал' : 'группа');
            const ini = (name || '?').charAt(0).toUpperCase();
            document.getElementById('chat-avatar-letter').textContent = ini;
            document.getElementById('chat-avatar').style.background = avatarGradient(id);
            const img = document.getElementById('chat-avatar-img');
            img.src = '/api/tg/avatar?chat_id=' + id;
            img.style.display = '';
            img.onerror = function() { this.style.display = 'none'; };
            document.querySelectorAll('.dialog-item').forEach(it => it.classList.toggle('active', parseInt(it.dataset.id) === id));
            document.getElementById('root-layout').classList.remove('with-info');
            loadMessages();
        }

        function loadMessages() {
            if (!_currentChat) return;
            const wrap = document.getElementById('messages-inner');
            if (!wrap.children.length) {
                wrap.innerHTML = '<div style="text-align:center;color:var(--text-muted);padding:24px;"><i class="bi bi-arrow-repeat spin" style="font-size:18px;"></i></div>';
            }
            fetch('/api/tg/messages?chat_id=' + _currentChat.id).then(r => r.json()).then(d => {
                renderMessages(d.messages || []);
            }).catch(() => {
                wrap.innerHTML = '<div style="text-align:center;color:#f87171;padding:24px;">Ошибка загрузки</div>';
            });
        }

        function renderMedia(m) {
            if (!m.media) return '';
            const url = '/api/tg/media?chat_id=' + m.chat_id + '&msg_id=' + m.id;
            const thumb = url + '&thumb=1';
            if (m.media === 'photo') {
                return '<img class="media" src="' + thumb + '" onclick="window.open(\'' + url + '\',\'_blank\')" loading="lazy">';
            }
            if (m.media === 'video' || m.media === 'gif' || m.media === 'video_note') {
                return '<video class="media" src="' + url + '" controls ' + (m.media === 'gif' ? 'autoplay loop muted' : '') + '></video>';
            }
            if (m.media === 'sticker') {
                return '<img class="media" src="' + url + '" loading="lazy">';
            }
            if (m.media === 'voice' || m.media === 'audio') {
                return '<audio class="media" src="' + url + '" controls></audio>';
            }
            if (m.media === 'document') {
                return '<div class="file-att" onclick="window.open(\'' + url + '\',\'_blank\')">' +
                    '<div class="file-icon"><i class="bi bi-file-earmark"></i></div>' +
                    '<div><div class="file-name">' + escHtml(m.media_name || 'Файл') + '</div><div class="file-size">Скачать</div></div>' +
                '</div>';
            }
            return '';
        }

        function renderMessages(msgs) {
            const wrap = document.getElementById('messages-inner');
            if (!msgs.length) {
                wrap.innerHTML = '<div style="text-align:center;color:var(--text-muted);padding:24px;">Сообщений нет</div>';
                return;
            }
            // chronological order: API returns newest first → reverse
            const chrono = msgs.slice().reverse();
            const isGroupChat = _currentChat && _currentChat.type !== 'user';
            let html = '';
            let lastDate = '';
            for (let i = 0; i < chrono.length; i++) {
                const m = chrono[i];
                const prev = i > 0 ? chrono[i-1] : null;
                const next = i < chrono.length - 1 ? chrono[i+1] : null;

                // Date divider
                const curDateStr = m.date ? new Date(m.date).toDateString() : '';
                if (curDateStr && curDateStr !== lastDate) {
                    html += '<div class="date-divider"><span>' + escHtml(dateLabel(m.date)) + '</span></div>';
                    lastDate = curDateStr;
                }

                const isOut = !!m.out;
                const sameSenderPrev = prev && prev.out === m.out && prev.sender_id === m.sender_id
                                       && prev.date && m.date && (new Date(m.date) - new Date(prev.date)) < 5 * 60 * 1000;
                const sameSenderNext = next && next.out === m.out && next.sender_id === m.sender_id
                                       && next.date && m.date && (new Date(next.date) - new Date(m.date)) < 5 * 60 * 1000;

                let clusterCls = '';
                if (sameSenderPrev && sameSenderNext) clusterCls = 'cluster-middle';
                else if (sameSenderPrev) clusterCls = 'cluster-end';
                else if (sameSenderNext) clusterCls = 'cluster-start';
                else clusterCls = 'cluster-end'; // single

                const showSender = !isOut && isGroupChat && !sameSenderPrev;

                const ts = fullTimeStr(m.date);
                const checks = isOut ? '<span class="check"><i class="bi bi-check2-all"></i></span>' : '';
                const meta = '<span class="meta">' + ts + checks + '</span>';

                const txt = m.text ? '<div class="text">' + escHtml(m.text) + '</div>' : '';
                const media = renderMedia(m);
                const sender = showSender ? '<div class="sender">' + escHtml(m.sender_name || '') + '</div>' : '';
                const stickerCls = m.media === 'sticker' ? ' sticker' : '';
                const mediaOnlyCls = (media && !m.text && m.media !== 'sticker' && m.media !== 'document' && m.media !== 'voice' && m.media !== 'audio') ? ' media-only' : '';

                html += '<div class="msg-row ' + clusterCls + (isOut ? ' out' : '') + '" data-msg-id="' + m.id + '" oncontextmenu="return showCtxMenu(event,' + m.id + ',' + (isOut ? 1 : 0) + ',\'' + escHtml((m.text || '').slice(0, 80).replace(/'/g, "\\'")) + '\')">' +
                    '<div class="bubble' + stickerCls + mediaOnlyCls + '">' +
                        sender +
                        media +
                        txt +
                        meta +
                    '</div>' +
                '</div>';
            }
            wrap.innerHTML = html;
            const scroller = document.getElementById('messages');
            scroller.scrollTop = scroller.scrollHeight;
            fetch('/api/tg/read', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ chat_id: _currentChat.id })
            }).catch(() => {});
        }

        // === Context menu (right-click) ===
        function showCtxMenu(ev, msgId, isOut, snippet) {
            ev.preventDefault();
            const old = document.getElementById('ctx-menu');
            if (old) old.remove();
            const menu = document.createElement('div');
            menu.id = 'ctx-menu';
            menu.className = 'ctx-menu';
            let html = '';
            html += '<div class="item" onclick="showReactionsPopup(event,' + msgId + ');document.getElementById(\'ctx-menu\').remove();"><i class="bi bi-emoji-smile"></i> Реакция</div>';
            html += '<div class="item" onclick="copyMsgText(' + msgId + ')"><i class="bi bi-files"></i> Копировать</div>';
            html += '<div class="item" onclick="forwardMsg(' + msgId + ')"><i class="bi bi-share"></i> Переслать</div>';
            if (isOut) {
                html += '<div class="item" onclick="editMsg(' + msgId + ')"><i class="bi bi-pencil"></i> Изменить</div>';
            }
            html += '<div class="item danger" onclick="deleteMsg(' + msgId + ',' + isOut + ')"><i class="bi bi-trash"></i> Удалить</div>';
            menu.innerHTML = html;
            document.body.appendChild(menu);
            // position near click
            const x = Math.min(ev.clientX, window.innerWidth - 200);
            const y = Math.min(ev.clientY, window.innerHeight - menu.offsetHeight - 10);
            menu.style.left = x + 'px';
            menu.style.top = y + 'px';
            return false;
        }
        document.addEventListener('click', function(e) {
            const menu = document.getElementById('ctx-menu');
            if (menu && !menu.contains(e.target)) menu.remove();
        });

        function copyMsgText(msgId) {
            const row = document.querySelector('.msg-row[data-msg-id="' + msgId + '"]');
            if (!row) return;
            const txt = row.querySelector('.text');
            if (!txt) { showToast('В сообщении нет текста', 'error'); return; }
            const t = txt.textContent;
            try {
                navigator.clipboard.writeText(t);
                showToast('Скопировано', 'success');
            } catch(e) { showToast('Скопировать не удалось', 'error'); }
        }
        function deleteMsg(msgId, isOut) {
            if (!confirm('Удалить сообщение?')) return;
            fetch('/api/tg/delete', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ chat_id: _currentChat.id, msg_id: msgId, revoke: isOut ? true : false })
            }).then(r => r.json()).then(d => {
                if (d.ok) { showToast('Удалено', 'success'); loadMessages(); }
                else showToast(d.error || 'Не удалось удалить', 'error');
            }).catch(() => showToast('Ошибка сети', 'error'));
        }
        function editMsg(msgId) {
            const row = document.querySelector('.msg-row[data-msg-id="' + msgId + '"]');
            if (!row) return;
            const txt = row.querySelector('.text');
            const cur = txt ? txt.textContent : '';
            const next = prompt('Редактировать сообщение:', cur);
            if (next === null || next === cur) return;
            fetch('/api/tg/edit', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ chat_id: _currentChat.id, msg_id: msgId, text: next })
            }).then(r => r.json()).then(d => {
                if (d.ok) { showToast('Изменено', 'success'); loadMessages(); }
                else showToast(d.error || 'Не удалось изменить', 'error');
            }).catch(() => showToast('Ошибка сети', 'error'));
        }
        function forwardMsg(msgId) {
            const target = prompt('Куда переслать (@username, ID или t.me/...)?');
            if (!target) return;
            fetch('/api/tg/forward', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ from_chat_id: _currentChat.id, msg_id: msgId, to: target.trim() })
            }).then(r => r.json()).then(d => {
                if (d.ok) showToast('Переслано', 'success');
                else showToast(d.error || 'Не удалось переслать', 'error');
            }).catch(() => showToast('Ошибка сети', 'error'));
        }

        // === File attach ===
        function attachFile() {
            document.getElementById('file-picker').click();
        }
        function onFilePicked(e) {
            const file = e.target.files[0];
            if (!file || !_currentChat) return;
            const fd = new FormData();
            fd.append('file', file);
            fd.append('chat_id', _currentChat.id);
            const caption = document.getElementById('msg-input').value.trim();
            if (caption) fd.append('caption', caption);
            showToast('Отправляю файл…', 'info');
            fetch('/api/tg/send_file', { method: 'POST', body: fd }).then(r => r.json()).then(d => {
                if (d.ok) {
                    document.getElementById('msg-input').value = '';
                    autoResize(document.getElementById('msg-input'));
                    showToast('Отправлено', 'success');
                    loadMessages();
                } else {
                    showToast(d.error || 'Ошибка отправки', 'error');
                }
            }).catch(() => showToast('Ошибка сети', 'error'));
            e.target.value = '';
        }

        function autoResize(el) {
            el.style.height = 'auto';
            el.style.height = Math.min(200, el.scrollHeight) + 'px';
        }
        function onInputKey(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        }
        function sendMessage() {
            if (!_currentChat) return;
            const input = document.getElementById('msg-input');
            const text = input.value.trim();
            if (!text) return;
            const btn = document.getElementById('send-btn');
            btn.disabled = true;
            fetch('/api/tg/send', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ chat_id: _currentChat.id, text: text })
            }).then(r => r.json()).then(d => {
                btn.disabled = false;
                if (d.ok) {
                    input.value = '';
                    autoResize(input);
                    loadMessages();
                } else {
                    showToast(d.error || 'Ошибка отправки', 'error');
                }
            }).catch(() => {
                btn.disabled = false;
                showToast('Ошибка сети', 'error');
            });
        }

        function toggleInfo() {
            const layout = document.getElementById('root-layout');
            const panel = document.getElementById('chat-info-panel');
            if (layout.classList.contains('with-info')) {
                layout.classList.remove('with-info');
                return;
            }
            if (!_currentChat) return;
            panel.innerHTML = '<div style="text-align:center;color:var(--text-muted);padding:60px 20px;"><i class="bi bi-arrow-repeat spin" style="font-size:18px;"></i></div>';
            layout.classList.add('with-info');
            fetch('/api/tg/user_info?chat_id=' + _currentChat.id).then(r => r.json()).then(d => {
                if (d.error) {
                    panel.innerHTML = '<div style="color:#f87171;padding:20px;text-align:center;">' + escHtml(d.error) + '</div>';
                    return;
                }
                let html = '';
                let title = '';
                let sub = '';
                if (d.type === 'user') {
                    title = ((d.first_name || '') + ' ' + (d.last_name || '')).trim() || 'Без имени';
                    sub = d.username ? '@' + d.username : (d.phone ? '+' + d.phone : 'был(а) недавно');
                } else {
                    title = d.title || '';
                    sub = (d.type === 'channel' ? 'канал' : 'группа') + (d.participants_count ? ' • ' + d.participants_count + ' участ.' : '');
                }
                const ini = (title || '?').charAt(0).toUpperCase();
                html += '<div class="info-header">' +
                    '<div class="info-avatar" style="background:' + avatarGradient(_currentChat.id) + ';">' +
                        '<img src="/api/tg/avatar?chat_id=' + _currentChat.id + '" onerror="this.style.display=\'none\'">' +
                        escHtml(ini) +
                    '</div>' +
                    '<div class="info-name">' + escHtml(title) + '</div>' +
                    '<div class="info-status">' + escHtml(sub) + '</div>' +
                    '</div>';
                html += '<div class="info-section">';
                if (d.about) {
                    html += '<div class="info-row"><i class="bi bi-info-circle"></i><div class="row-content"><div class="row-value" style="white-space:pre-wrap;">' + escHtml(d.about) + '</div><div class="row-label">' + (d.type === 'user' ? 'О себе' : 'Описание') + '</div></div></div>';
                }
                if (d.username) {
                    html += '<div class="info-row" onclick="navigator.clipboard.writeText(\'@' + escHtml(d.username) + '\');showToast(\'Скопировано\',\'success\')"><i class="bi bi-at"></i><div class="row-content"><div class="row-value">@' + escHtml(d.username) + '</div><div class="row-label">Имя пользователя</div></div></div>';
                }
                if (d.phone) {
                    html += '<div class="info-row"><i class="bi bi-telephone"></i><div class="row-content"><div class="row-value">+' + escHtml(d.phone) + '</div><div class="row-label">Телефон</div></div></div>';
                }
                html += '<div class="info-row"><i class="bi bi-hash"></i><div class="row-content"><div class="row-value">' + d.id + '</div><div class="row-label">ID</div></div></div>';
                if (d.is_premium) {
                    html += '<div class="info-row"><i class="bi bi-star-fill" style="color:#fbbf24;"></i><div class="row-content"><div class="row-value">Premium-аккаунт</div></div></div>';
                }
                if (d.is_bot) {
                    html += '<div class="info-row"><i class="bi bi-robot"></i><div class="row-content"><div class="row-value">Бот</div></div></div>';
                }
                if (d.is_scam || d.is_fake) {
                    html += '<div class="info-row"><i class="bi bi-exclamation-triangle-fill" style="color:#e74c3c;"></i><div class="row-content"><div class="row-value">' + (d.is_scam ? 'Scam' : 'Fake') + '</div><div class="row-label">Помечен Telegram</div></div></div>';
                }
                html += '</div>';
                panel.innerHTML = html;
            });
        }

        function startRefresh() {
            if (_refreshTimer) clearInterval(_refreshTimer);
            _refreshTimer = setInterval(() => {
                loadDialogs();
                if (_currentChat) loadMessages();
            }, 8000);
        }

        // === Emoji picker ===
        const EMOJI_LIST = ['👍','❤️','🔥','😁','😢','🎉','😱','😡','💯','👏','🙏','😍','😘','🤔','😎','🤯','🥰','😭','😤','😴','🤣','😅','🙄','😏','😬','🤝','💪','🤙','✌️','👌','🙌','💔','❤‍🔥','🤬','💋','🥺','😇','🤡','💀','👻','🎂','🎁','⭐','✨','🌹','💐','☕','🍕','🍺','🍾','🤩','🥳','🤪','😋','🤤','🤓'];
        function toggleEmojiPanel() {
            const panel = document.getElementById('emoji-panel');
            if (!panel.children.length) {
                EMOJI_LIST.forEach(e => {
                    const b = document.createElement('button');
                    b.textContent = e;
                    b.onclick = () => insertEmoji(e);
                    panel.appendChild(b);
                });
            }
            panel.classList.toggle('show');
        }
        function insertEmoji(e) {
            const inp = document.getElementById('msg-input');
            const start = inp.selectionStart || 0;
            const end = inp.selectionEnd || 0;
            inp.value = inp.value.slice(0, start) + e + inp.value.slice(end);
            inp.focus();
            inp.selectionStart = inp.selectionEnd = start + e.length;
            autoResize(inp);
        }
        document.addEventListener('click', function(e) {
            const panel = document.getElementById('emoji-panel');
            if (!panel || !panel.classList.contains('show')) return;
            if (panel.contains(e.target)) return;
            if (e.target.closest('.input-attach')) return;
            panel.classList.remove('show');
        });

        // === Drag & drop файлов в окно ===
        const dndOverlay = document.getElementById('dnd-overlay');
        let _dndCounter = 0;
        document.addEventListener('dragenter', function(e) {
            e.preventDefault();
            if (!_currentChat) return;
            if (e.dataTransfer && Array.from(e.dataTransfer.types || []).includes('Files')) {
                _dndCounter++;
                dndOverlay.classList.add('active');
            }
        });
        document.addEventListener('dragover', function(e) { e.preventDefault(); });
        document.addEventListener('dragleave', function(e) {
            _dndCounter = Math.max(0, _dndCounter - 1);
            if (_dndCounter === 0) dndOverlay.classList.remove('active');
        });
        document.addEventListener('drop', function(e) {
            e.preventDefault();
            _dndCounter = 0;
            dndOverlay.classList.remove('active');
            if (!_currentChat) return;
            const files = e.dataTransfer && e.dataTransfer.files;
            if (!files || !files.length) return;
            sendFiles(Array.from(files));
        });
        function sendFiles(files) {
            if (!_currentChat || !files || !files.length) return;
            const caption = document.getElementById('msg-input').value.trim();
            let sent = 0;
            const total = files.length;
            files.forEach((file, idx) => {
                const fd = new FormData();
                fd.append('file', file);
                fd.append('chat_id', _currentChat.id);
                if (idx === 0 && caption) fd.append('caption', caption);
                showToast('Отправляю ' + (idx + 1) + '/' + total + '…', 'info');
                fetch('/api/tg/send_file', { method: 'POST', body: fd }).then(r => r.json()).then(d => {
                    if (d.ok) {
                        sent++;
                        if (sent === total) {
                            document.getElementById('msg-input').value = '';
                            autoResize(document.getElementById('msg-input'));
                            showToast('Отправлено: ' + sent + '/' + total, 'success');
                            loadMessages();
                        }
                    } else {
                        showToast(d.error || ('Ошибка ' + file.name), 'error');
                    }
                }).catch(() => showToast('Ошибка сети при отправке ' + file.name, 'error'));
            });
        }
        // Перенаправляем onFilePicked на sendFiles (поддержка multiple)
        window.onFilePicked = function(e) {
            const files = e.target.files;
            if (files && files.length) sendFiles(Array.from(files));
            e.target.value = '';
        };

        // === Search в чате ===
        function toggleSearch() {
            const bar = document.getElementById('search-bar');
            if (bar.style.display === 'none') {
                bar.style.display = 'block';
                document.getElementById('search-msg-input').focus();
            } else {
                bar.style.display = 'none';
                document.getElementById('search-results').innerHTML = '';
                document.getElementById('search-msg-input').value = '';
            }
        }
        function onSearchKey(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                doSearch();
            }
            if (e.key === 'Escape') toggleSearch();
        }
        function doSearch() {
            const q = document.getElementById('search-msg-input').value.trim();
            const out = document.getElementById('search-results');
            if (!q || !_currentChat) { out.innerHTML = ''; return; }
            out.innerHTML = '<div style="text-align:center;color:var(--text-muted);padding:12px;"><i class="bi bi-arrow-repeat spin"></i></div>';
            fetch('/api/tg/search_messages?chat_id=' + _currentChat.id + '&q=' + encodeURIComponent(q))
                .then(r => r.json()).then(d => {
                    if (!d.messages || !d.messages.length) {
                        out.innerHTML = '<div style="color:var(--text-muted);padding:8px;text-align:center;">Ничего не найдено</div>';
                        return;
                    }
                    out.innerHTML = d.messages.map(m => {
                        const who = m.sender_name ? '<b style="color:var(--accent-light);">' + escHtml(m.sender_name) + '</b> ' : '';
                        return '<div style="padding:6px 10px;border-radius:6px;cursor:pointer;border-bottom:1px solid var(--divider);" onmouseover="this.style.background=\'var(--bg-side-hover)\'" onmouseout="this.style.background=\'\'" onclick="scrollToMsg(' + m.id + ')">' +
                            '<div style="font-size:11px;color:var(--text-muted);margin-bottom:2px;">' + escHtml(timeStr(m.date)) + ' ' + fullTimeStr(m.date) + '</div>' +
                            '<div>' + who + escHtml(m.text || '(без текста)') + '</div>' +
                        '</div>';
                    }).join('');
                });
        }
        function scrollToMsg(msgId) {
            const row = document.querySelector('.msg-row[data-msg-id="' + msgId + '"]');
            if (row) {
                row.scrollIntoView({ behavior: 'smooth', block: 'center' });
                row.style.background = 'rgba(106,178,242,0.2)';
                setTimeout(() => { row.style.background = ''; }, 1500);
            } else {
                showToast('Сообщение не загружено в текущей странице', 'info');
            }
        }

        // === Reactions ===
        const QUICK_REACTIONS = ['👍','❤️','🔥','😁','😢','🎉'];
        function showReactionsPopup(ev, msgId) {
            ev.stopPropagation();
            // удалить старый
            const old = document.querySelector('.reactions-popup');
            if (old) old.remove();
            const row = document.querySelector('.msg-row[data-msg-id="' + msgId + '"]');
            if (!row) return;
            const bubble = row.querySelector('.bubble');
            if (!bubble) return;
            const popup = document.createElement('div');
            popup.className = 'reactions-popup';
            popup.innerHTML = QUICK_REACTIONS.map(e =>
                '<button class="react-btn" onclick="sendReaction(' + msgId + ',\'' + e + '\')">' + e + '</button>'
            ).join('');
            bubble.style.position = 'relative';
            bubble.appendChild(popup);
            setTimeout(() => {
                document.addEventListener('click', function rm() {
                    if (popup) popup.remove();
                    document.removeEventListener('click', rm);
                });
            }, 100);
        }
        function sendReaction(msgId, emoji) {
            if (!_currentChat) return;
            const old = document.querySelector('.reactions-popup');
            if (old) old.remove();
            fetch('/api/tg/react', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ chat_id: _currentChat.id, msg_id: msgId, emoji: emoji })
            }).then(r => r.json()).then(d => {
                if (d.ok) showToast('Реакция ' + emoji, 'success');
                else showToast(d.error || 'Не удалось поставить', 'error');
            }).catch(() => showToast('Ошибка сети', 'error'));
        }

        // === Stories ===
        let _storiesUsers = [];
        let _storiesCurUser = -1;
        let _storiesCurStory = 0;
        function openStories() {
            const bar = document.getElementById('stories-bar');
            if (bar.style.display === 'none') {
                fetch('/api/tg/stories').then(r => r.json()).then(d => {
                    if (d.error) { showToast(d.error, 'error'); return; }
                    _storiesUsers = d.users || [];
                    if (!_storiesUsers.length) { showToast('Нет активных историй у контактов', 'info'); return; }
                    const list = document.getElementById('stories-list');
                    list.innerHTML = _storiesUsers.map((u, i) => {
                        const ini = (u.name || '?').charAt(0).toUpperCase();
                        return '<div onclick="playStories(' + i + ')" style="display:inline-flex;flex-direction:column;align-items:center;gap:4px;cursor:pointer;width:62px;">' +
                            '<div style="width:54px;height:54px;border-radius:50%;padding:2px;background:linear-gradient(135deg,#ff885e,#a855f7);">' +
                                '<div class="avatar" style="width:50px;height:50px;font-size:18px;border:2px solid var(--bg-side);background:' + avatarGradient(u.id) + ';">' +
                                    '<img src="/api/tg/avatar?chat_id=' + u.id + '" onerror="this.style.display=\'none\'">' +
                                    '<span>' + escHtml(ini) + '</span>' +
                                '</div>' +
                            '</div>' +
                            '<div style="font-size:11px;text-align:center;color:var(--text);max-width:60px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' + escHtml(u.name) + '</div>' +
                        '</div>';
                    }).join('');
                    bar.style.display = 'block';
                });
            } else {
                bar.style.display = 'none';
            }
        }
        function playStories(userIdx) {
            _storiesCurUser = userIdx;
            _storiesCurStory = 0;
            document.getElementById('stories-viewer').style.display = 'flex';
            renderCurStory();
        }
        function renderCurStory() {
            const u = _storiesUsers[_storiesCurUser];
            if (!u) { closeStories(); return; }
            const s = u.stories[_storiesCurStory];
            if (!s) {
                // переходим к следующему юзеру
                if (_storiesCurUser < _storiesUsers.length - 1) {
                    _storiesCurUser++;
                    _storiesCurStory = 0;
                    renderCurStory();
                } else {
                    closeStories();
                }
                return;
            }
            // имя + аватар
            document.getElementById('stories-name').textContent = u.name;
            const av = document.getElementById('stories-avatar');
            av.style.background = avatarGradient(u.id);
            av.innerHTML = '<img src="/api/tg/avatar?chat_id=' + u.id + '" onerror="this.style.display=\'none\'"><span>' + escHtml((u.name||'?').charAt(0).toUpperCase()) + '</span>';
            // прогресс-бар (полоски сверху)
            const prog = document.getElementById('stories-progress');
            prog.innerHTML = u.stories.map((_, i) =>
                '<div style="flex:1;height:3px;background:rgba(255,255,255,' + (i < _storiesCurStory ? '0.9' : (i === _storiesCurStory ? '0.4' : '0.2')) + ');border-radius:2px;"></div>'
            ).join('');
            // медиа
            const url = '/api/tg/story_media?peer=' + u.id + '&story=' + s.id;
            const img = document.getElementById('stories-img');
            const vid = document.getElementById('stories-video');
            if (s.media_type === 'video') {
                img.style.display = 'none';
                vid.style.display = '';
                vid.src = url;
            } else {
                vid.style.display = 'none';
                vid.pause();
                img.style.display = '';
                img.src = url;
            }
            // подпись
            const cap = document.getElementById('stories-caption');
            if (s.caption) { cap.textContent = s.caption; cap.style.display = ''; }
            else cap.style.display = 'none';
        }
        function storyNext() {
            const u = _storiesUsers[_storiesCurUser];
            if (!u) return;
            if (_storiesCurStory < u.stories.length - 1) {
                _storiesCurStory++;
            } else if (_storiesCurUser < _storiesUsers.length - 1) {
                _storiesCurUser++;
                _storiesCurStory = 0;
            } else {
                closeStories();
                return;
            }
            renderCurStory();
        }
        function storyPrev() {
            if (_storiesCurStory > 0) {
                _storiesCurStory--;
            } else if (_storiesCurUser > 0) {
                _storiesCurUser--;
                _storiesCurStory = _storiesUsers[_storiesCurUser].stories.length - 1;
            } else {
                return;
            }
            renderCurStory();
        }
        function closeStories() {
            document.getElementById('stories-viewer').style.display = 'none';
            const vid = document.getElementById('stories-video');
            try { vid.pause(); } catch(e) {}
            vid.src = '';
            document.getElementById('stories-img').src = '';
        }
        document.addEventListener('keydown', function(e) {
            if (document.getElementById('stories-viewer').style.display !== 'flex') return;
            if (e.key === 'ArrowLeft') storyPrev();
            if (e.key === 'ArrowRight') storyNext();
            if (e.key === 'Escape') closeStories();
        });

        // Init
        loadAccountInfo();
        loadDialogs();
        startRefresh();
    </script>
</body>
</html>
