(function () {
  const SERVER_URL = window.LIVECHAT_SERVER_URL || 'https://livechat.zonawd78.shop/demo.html';

  // ---- styles ----
  const ACCENT = '#2f6feb';

  const style = document.createElement('style');
  style.textContent = `
    #lc-bubble {
      position: fixed; bottom: 20px; right: 20px; width: 56px; height: 56px;
      border-radius: 50%; background: ${ACCENT}; color: white; display: flex;
      align-items: center; justify-content: center; cursor: pointer; font-size: 26px;
      box-shadow: 0 4px 14px rgba(0,0,0,.25); z-index: 999999;
    }
    #lc-window {
      position: fixed; bottom: 88px; right: 20px; width: 320px; height: 420px;
      background: #f4f5f7; border-radius: 12px; display: none; flex-direction: column;
      overflow: hidden; box-shadow: 0 8px 24px rgba(0,0,0,.35); z-index: 999999;
      font-family: -apple-system, Roboto, Arial, sans-serif;
    }
    #lc-topbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; background: #f4f5f7; }
    #lc-topbar-left { display: flex; align-items: center; gap: 8px; }
    #lc-topbar button { border: none; background: #fff; color: #333; width: 32px; height: 32px; border-radius: 50%;
      box-shadow: 0 1px 3px rgba(0,0,0,.15); cursor: pointer; font-size: 15px; line-height: 1; }
    #lc-agentcard { display: flex; align-items: center; gap: 10px; background: #fff;
      padding: 8px 14px 8px 8px; border-radius: 999px; box-shadow: 0 2px 8px rgba(0,0,0,.12); margin-bottom: 12px; }
    #lc-agent-avatar { width: 38px; height: 38px; border-radius: 50%; background: ${ACCENT}; color: #fff;
      display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
    #lc-agent-name { font-weight: 700; font-size: 14px; color: #1a1a1a; }
    #lc-agent-role { font-size: 12px; color: #8a8f98; }
    #lc-messages { flex: 1; padding: 10px 12px; overflow-y: auto; background: #f4f5f7; }
    .lc-msg-row { display: flex; align-items: flex-end; gap: 8px; margin: 6px 0; }
    .lc-row-admin { justify-content: flex-start; }
    .lc-row-user { justify-content: flex-end; }
    .lc-avatar { width: 26px; height: 26px; border-radius: 50%; background: ${ACCENT}; color: #fff;
      font-size: 12px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
    #lc-messages .lc-msg { max-width: 78%; padding: 8px 12px; border-radius: 14px; font-size: 13px; line-height: 1.4; }
    #lc-messages .lc-user { background: ${ACCENT}; color: #fff; border-bottom-right-radius: 4px; }
    #lc-messages .lc-admin { background: #fff; color: #1a1a1a; box-shadow: 0 1px 2px rgba(0,0,0,.08); border-bottom-left-radius: 4px; }
    #lc-messages .lc-msg img { max-width: 100%; max-height: 180px; border-radius: 8px; display: block; cursor: pointer; }
    #lc-messages .lc-msg .lc-file-link { display: flex; align-items: center; gap: 6px; color: inherit; text-decoration: none; }
    #lc-messages .lc-msg .lc-file-link .lc-file-icon { font-size: 16px; }
    #lc-messages .lc-msg .lc-file-caption { margin-top: 4px; }
    #lc-messages .lc-system { max-width: 100%; margin: 10px 0; text-align: center; font-size: 12px; color: #8a8f98; background: transparent; padding: 4px 8px; }
    #lc-inputbar { display: flex; align-items: center; gap: 6px; margin: 10px 12px; padding: 6px 6px 6px 16px;
      background: #fff; border-radius: 999px; box-shadow: 0 1px 4px rgba(0,0,0,.12); border-top: none; }
    #lc-attach { border: none; background: transparent; color: #8a8f98; font-size: 22px; font-weight: 600;
      width: 28px; height: 28px; padding: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; line-height: 1; flex-shrink: 0; }
    #lc-attach:hover { color: #333; }
    #lc-input { flex: 1; border: none; padding: 8px 4px; background: transparent; color: #1a1a1a; font-size: 13px; outline: none; min-width: 0; }
    #lc-send { border: none; background: ${ACCENT}; color: #fff; width: 34px; height: 34px; border-radius: 50%;
      display: flex; align-items: center; justify-content: center; font-size: 16px; cursor: pointer; flex-shrink: 0; }
    #lc-file-input { display: none; }
    #lc-upload-preview { display: none; align-items: center; gap: 8px; padding: 6px 16px; background: transparent; font-size: 12px; color: #444; }
    #lc-upload-preview .lc-upload-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    #lc-upload-cancel { border: none; background: transparent; color: #e0464f; cursor: pointer; font-size: 14px; }
    #lc-prechat { flex: 1; padding: 16px; background: #f4f5f7; overflow-y: auto; display: flex;
      flex-direction: column; justify-content: center; align-items: center; }
    #lc-prechat-inner { width: 100%; max-width: 380px; }
    #lc-prechat-card { background: #fff; border-radius: 14px; padding: 18px 16px; box-shadow: 0 2px 8px rgba(0,0,0,.08); display: flex; flex-direction: column; }
    #lc-prechat p { color: #444; font-size: 13px; line-height: 1.5; margin: 0 0 16px; }
    #lc-prechat label { color: #666; font-size: 12px; margin-bottom: 4px; display: block; }
    #lc-prechat .lc-field { margin-bottom: 14px; }
    #lc-prechat input { width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: 8px; border: 1px solid #e4e6ea; background: #f0f1f3; color: #1a1a1a; font-size: 13px; outline: none; }
    #lc-prechat input:focus { border-color: ${ACCENT}; }
    #lc-prechat-start { margin-top: 4px; border: none; background: ${ACCENT}; color: #fff; padding: 12px; border-radius: 999px; font-size: 14px; font-weight: 600; cursor: pointer; }
    #lc-prechat-start:hover { filter: brightness(1.08); }
    #lc-prechat-error { color: #e0464f; font-size: 12px; margin-top: -6px; margin-bottom: 10px; display: none; }
    #lc-powered { text-align: center; font-size: 11px; color: #9aa0a8; margin-top: 14px; }
    #lc-powered b { color: #666; }

    .lc-reopen-card { background: #fff; border-radius: 14px; padding: 16px 14px; margin: 14px 0 6px; box-shadow: 0 2px 8px rgba(0,0,0,.08); }
    .lc-reopen-card p { color: #444; font-size: 13px; line-height: 1.5; margin: 0 0 14px; }
    .lc-reopen-card label { color: #666; font-size: 12px; margin-bottom: 4px; display: block; }
    .lc-reopen-card .lc-field { margin-bottom: 12px; }
    .lc-reopen-card input { width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: 8px; border: 1px solid #e4e6ea; background: #f0f1f3; color: #1a1a1a; font-size: 13px; outline: none; }
    .lc-reopen-card input:focus { border-color: ${ACCENT}; }
    .lc-reopen-start { width: 100%; margin-top: 2px; border: none; background: ${ACCENT}; color: #fff; padding: 11px; border-radius: 999px; font-size: 14px; font-weight: 600; cursor: pointer; }
    .lc-reopen-start:hover { filter: brightness(1.08); }
    .lc-reopen-error { color: #e0464f; font-size: 12px; margin-top: -6px; margin-bottom: 10px; display: none; }
    .lc-reopen-powered { text-align: center; font-size: 11px; color: #9aa0a8; margin-top: 12px; }
    .lc-reopen-powered b { color: #666; }

    /* -------- tampilan mobile: perbesar semuanya biar gak keliatan kekecilan -------- */
    @media (max-width: 480px) {
      #lc-topbar button { width: 38px; height: 38px; font-size: 17px; }
      #lc-agentcard { padding: 12px 18px 12px 10px; border-radius: 20px; }
      #lc-agent-avatar { width: 48px; height: 48px; font-size: 22px; }
      #lc-agent-name { font-size: 17px; }
      #lc-agent-role { font-size: 14px; }
      #lc-prechat-inner { max-width: 460px; }
      #lc-prechat-card { padding: 26px 22px; border-radius: 18px; }
      #lc-prechat p { font-size: 15px; margin-bottom: 20px; }
      #lc-prechat label { font-size: 13.5px; margin-bottom: 6px; }
      #lc-prechat .lc-field { margin-bottom: 18px; }
      #lc-prechat input { padding: 13px 14px; font-size: 15px; border-radius: 10px; }
      #lc-prechat-start { padding: 15px; font-size: 16px; border-radius: 999px; }
      #lc-prechat-error { font-size: 13px; }
      #lc-powered { font-size: 12.5px; margin-top: 18px; }

      #lc-messages { padding: 14px 16px; }
      #lc-messages .lc-msg { max-width: 85%; font-size: 15px; padding: 11px 15px; border-radius: 16px; }
      .lc-msg-row { margin: 8px 0; gap: 10px; }
      .lc-avatar { width: 30px; height: 30px; font-size: 13px; }
      #lc-messages .lc-system { font-size: 13px; }
      #lc-inputbar { padding: 6px 6px 6px 18px; margin: 12px; }
      #lc-attach { font-size: 24px; width: 32px; height: 32px; }
      #lc-input { font-size: 15px; padding: 10px 6px; }
      #lc-send { width: 40px; height: 40px; font-size: 18px; }
      #lc-upload-preview { font-size: 13px; padding: 8px 16px; }

      .lc-reopen-card { padding: 20px 18px; border-radius: 16px; }
      .lc-reopen-card p { font-size: 14px; margin-bottom: 16px; }
      .lc-reopen-card label { font-size: 13px; margin-bottom: 5px; }
      .lc-reopen-card .lc-field { margin-bottom: 14px; }
      .lc-reopen-card input { padding: 12px 13px; font-size: 14px; border-radius: 9px; }
      .lc-reopen-start { padding: 13px; font-size: 15px; }
      .lc-reopen-error { font-size: 12.5px; }
      .lc-reopen-powered { font-size: 12px; margin-top: 14px; }
    }
  `;
  document.head.appendChild(style);

  // ---- markup ----
  const bubble = document.createElement('div');
  bubble.id = 'lc-bubble';
  bubble.innerHTML = '💬';

  const win = document.createElement('div');
  win.id = 'lc-window';
  win.innerHTML = `
    <div id="lc-topbar">
      <div id="lc-topbar-left">
        <button id="lc-back" title="Tutup">←</button>
        <button id="lc-menu" title="Menu">⋯</button>
      </div>
      <button id="lc-close" title="Tutup">✕</button>
    </div>
    <div id="lc-prechat">
      <div id="lc-prechat-inner">
        <div id="lc-agentcard">
          <div id="lc-agent-avatar">💬</div>
          <div>
            <div id="lc-agent-name">Admin</div>
            <div id="lc-agent-role">Customer Support</div>
          </div>
        </div>
        <div id="lc-prechat-card">
          <p>Selamat datang di Live Chat kami! Silakan isi data di bawah ini sebelum memulai obrolan.</p>
          <div class="lc-field">
            <label for="lc-prechat-name">Nama</label>
            <input id="lc-prechat-name" placeholder="Nama kamu" autocomplete="name" />
          </div>
          <div class="lc-field">
            <label for="lc-prechat-email">Email</label>
            <input id="lc-prechat-email" placeholder="Email kamu" autocomplete="email" />
          </div>
          <div id="lc-prechat-error">Nama wajib diisi ya.</div>
          <button id="lc-prechat-start">Mulai Obrolan</button>
        </div>
        <div id="lc-powered">Powered by <b>LiveChat</b></div>
      </div>
    </div>
    <div id="lc-chat-area" style="display:none; flex-direction:column; flex:1; min-height:0;">
      <div id="lc-messages"></div>
      <div id="lc-upload-preview">
        <span class="lc-upload-name"></span>
        <button id="lc-upload-cancel" title="Batal">✕</button>
      </div>
      <div id="lc-inputbar">
        <button id="lc-attach" title="Kirim gambar/file">+</button>
        <input id="lc-file-input" type="file" accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.zip,.txt" />
        <input id="lc-input" placeholder="Tulis pesan..." />
        <button id="lc-send" title="Kirim">↑</button>
      </div>
    </div>
  `;

  document.body.appendChild(bubble);
  document.body.appendChild(win);

  const prechatEl = win.querySelector('#lc-prechat');
  const chatAreaEl = win.querySelector('#lc-chat-area');
  const prechatNameEl = win.querySelector('#lc-prechat-name');
  const prechatEmailEl = win.querySelector('#lc-prechat-email');
  const prechatErrorEl = win.querySelector('#lc-prechat-error');
  const prechatStartBtn = win.querySelector('#lc-prechat-start');

  const messagesEl = win.querySelector('#lc-messages');
  const inputEl = win.querySelector('#lc-input');
  const sendBtn = win.querySelector('#lc-send');
  const attachBtn = win.querySelector('#lc-attach');
  const fileInputEl = win.querySelector('#lc-file-input');
  const uploadPreviewEl = win.querySelector('#lc-upload-preview');
  const uploadNameEl = uploadPreviewEl.querySelector('.lc-upload-name');
  const uploadCancelBtn = win.querySelector('#lc-upload-cancel');

  let pendingFile = null;

  let roomId = localStorage.getItem('lc_room_id');
  let visitorName = localStorage.getItem('lc_visitor_name') || '';
  let visitorEmail = localStorage.getItem('lc_visitor_email') || '';
  let socket = null;
  let chatClosed = false; // true kalau room ini sudah ditutup, dipakai buat munculin form mulai obrolan baru
  let reopenCardEl = null; // kartu inline "mulai obrolan baru" yang muncul di dalam histori chat

  function escapeHtml(str) {
    const div = document.createElement('div');
    div.textContent = str;
    return div.innerHTML;
  }

  const AGENT_NAME = (win.querySelector('#lc-agent-name').textContent || 'A').trim();

  function appendMsg(msg, from) {
    // dukung pemanggilan lama appendMsg(text, from) dan baru appendMsg(msgObj)
    let m = msg;
    if (typeof msg === 'string') m = { text: msg, type: 'text' };
    from = from || m.from;
    const isAdmin = from === 'admin';

    const row = document.createElement('div');
    row.className = 'lc-msg-row ' + (isAdmin ? 'lc-row-admin' : 'lc-row-user');

    if (isAdmin) {
      const av = document.createElement('div');
      av.className = 'lc-avatar';
      av.textContent = AGENT_NAME.charAt(0).toUpperCase() || 'A';
      row.appendChild(av);
    }

    const div = document.createElement('div');
    div.className = 'lc-msg ' + (isAdmin ? 'lc-admin' : 'lc-user');

    const fileUrl = m.url ? (/^(https?:|blob:|data:)/.test(m.url) ? m.url : SERVER_URL + m.url) : null;

    if (m.type === 'image' && fileUrl) {
      const img = document.createElement('img');
      img.src = fileUrl;
      img.alt = m.filename || 'gambar';
      img.addEventListener('click', () => window.open(fileUrl, '_blank'));
      div.appendChild(img);
      if (m.text && m.text !== m.filename) {
        const cap = document.createElement('div');
        cap.className = 'lc-file-caption';
        cap.textContent = m.text;
        div.appendChild(cap);
      }
    } else if (m.type === 'file' && fileUrl) {
      const link = document.createElement('a');
      link.className = 'lc-file-link';
      link.href = fileUrl;
      link.target = '_blank';
      link.rel = 'noopener';
      link.innerHTML =
        '<span class="lc-file-icon">📄</span><span>' + escapeHtml(m.filename || 'File') + '</span>';
      div.appendChild(link);
      if (m.text && m.text !== m.filename) {
        const cap = document.createElement('div');
        cap.className = 'lc-file-caption';
        cap.textContent = m.text;
        div.appendChild(cap);
      }
    } else {
      div.textContent = m.text;
    }

    row.appendChild(div);
    messagesEl.appendChild(row);
    messagesEl.scrollTop = messagesEl.scrollHeight;
  }

  function appendSystemMsg(text) {
    const div = document.createElement('div');
    div.className = 'lc-msg lc-system';
    div.textContent = text;
    messagesEl.appendChild(div);
    messagesEl.scrollTop = messagesEl.scrollHeight;
  }

  // kartu inline "isi nama & email lagi buat mulai obrolan baru", muncul di histori chat setelah chat ditutup
  function buildReopenCard() {
    const card = document.createElement('div');
    card.className = 'lc-reopen-card';
    card.innerHTML = `
      <p>Selamat datang di Live Chat kami! Silakan isi data di bawah ini sebelum memulai obrolan.</p>
      <div class="lc-field">
        <label>Nama</label>
        <input class="lc-reopen-name" placeholder="Nama kamu" autocomplete="name" />
      </div>
      <div class="lc-field">
        <label>Email</label>
        <input class="lc-reopen-email" placeholder="Email kamu" autocomplete="email" />
      </div>
      <div class="lc-reopen-error">Nama wajib diisi ya.</div>
      <button class="lc-reopen-start">Mulai Obrolan</button>
      <div class="lc-reopen-powered">Powered by <b>LiveChat</b></div>
    `;

    const nameInput = card.querySelector('.lc-reopen-name');
    const emailInput = card.querySelector('.lc-reopen-email');
    const errorEl = card.querySelector('.lc-reopen-error');
    const startBtn = card.querySelector('.lc-reopen-start');

    nameInput.value = visitorName || '';
    emailInput.value = visitorEmail || '';

    async function startNewChat() {
      const name = nameInput.value.trim();
      const email = emailInput.value.trim();

      if (!name) {
        errorEl.style.display = 'block';
        nameInput.focus();
        return;
      }
      errorEl.style.display = 'none';
      startBtn.disabled = true;

      if (socket) {
        socket.disconnect();
        socket = null;
      }
      roomId = null;
      localStorage.removeItem('lc_room_id');
      visitorName = name;
      visitorEmail = email;
      localStorage.setItem('lc_visitor_name', name);
      localStorage.setItem('lc_visitor_email', email);
      chatClosed = false;

      removeReopenCard();
      setInputEnabled(true);
      await initSocket();
    }

    startBtn.addEventListener('click', startNewChat);
    [nameInput, emailInput].forEach((el) => {
      el.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') startNewChat();
      });
    });

    return card;
  }

  function showReopenForm() {
    if (reopenCardEl) return; // udah ada, jangan dobel
    reopenCardEl = buildReopenCard();
    messagesEl.appendChild(reopenCardEl);
    messagesEl.scrollTop = messagesEl.scrollHeight;
  }

  function removeReopenCard() {
    if (reopenCardEl) {
      reopenCardEl.remove();
      reopenCardEl = null;
    }
  }

  function setInputEnabled(enabled) {
    inputEl.disabled = !enabled;
    sendBtn.disabled = !enabled;
    attachBtn.disabled = !enabled;
    inputEl.placeholder = enabled ? 'Tulis pesan...' : 'Chat ini telah diblokir';
  }

  function loadSocketIoScript(cb) {
    if (window.io) return cb();
    const s = document.createElement('script');
    s.src = SERVER_URL + '/socket.io/socket.io.js';
    s.onload = cb;
    document.head.appendChild(s);
  }

  async function ensureRoom() {
    if (roomId) return roomId;
    const res = await fetch(SERVER_URL + '/api/chat/start', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ user: visitorName, email: visitorEmail, site: location.hostname }),
    });
    const data = await res.json();
    roomId = data.room.id;
    localStorage.setItem('lc_room_id', roomId);
    return roomId;
  }

  async function initSocket() {
    await ensureRoom();
    loadSocketIoScript(() => {
      socket = window.io(SERVER_URL);
      socket.emit('join_room', roomId);
      socket.on('admin_reply', (payload) => {
        if (Number(payload.room_id) === Number(roomId)) {
          appendMsg({ ...payload, from: 'admin' });
        }
      });
      socket.on('room_blocked', (payload) => {
        if (Number(payload.room_id) === Number(roomId)) {
          setInputEnabled(false);
          appendSystemMsg('🚫 Chat ini telah diblokir oleh admin.');
        }
      });
      socket.on('room_unblocked', (payload) => {
        if (Number(payload.room_id) === Number(roomId)) {
          setInputEnabled(true);
          appendSystemMsg('✅ Chat ini sudah dibuka kembali oleh admin.');
        }
      });
      socket.on('room_closed', (payload) => {
        if (Number(payload.room_id) === Number(roomId)) {
          chatClosed = true;
          setInputEnabled(false);
          appendSystemMsg('Anda telah menutup obrolan.');
          showReopenForm();
        }
      });
    });

    // load history kalau room lama
    try {
      const res = await fetch(SERVER_URL + '/api/chat/history/' + roomId);
      const data = await res.json();
      data.messages.forEach((m) => appendMsg(m));
      if (data.room && data.room.blocked) {
        setInputEnabled(false);
        appendSystemMsg('🚫 Chat ini telah diblokir oleh admin.');
      } else if (data.room && data.room.status === 'closed') {
        chatClosed = true;
        setInputEnabled(false);
        appendSystemMsg('Anda telah menutup obrolan.');
        showReopenForm();
      }
    } catch (e) {}
  }

  function showChatArea() {
    prechatEl.style.display = 'none';
    chatAreaEl.style.display = 'flex';
  }

  function openWidget() {
    const hasIdentity = roomId || visitorName; // pernah isi form / punya room sebelumnya
    if (hasIdentity) {
      showChatArea();
      if (!socket) initSocket();
    } else {
      prechatEl.style.display = 'flex';
      chatAreaEl.style.display = 'none';
    }
  }

  bubble.addEventListener('click', () => {
    const isOpen = win.style.display === 'flex';
    win.style.display = isOpen ? 'none' : 'flex';
    if (!isOpen) openWidget();
  });

  const backBtn = win.querySelector('#lc-back');
  if (backBtn) {
    backBtn.addEventListener('click', () => {
      win.style.display = 'none';
    });
  }

  const closeBtn = win.querySelector('#lc-close');
  if (closeBtn) {
    closeBtn.addEventListener('click', () => {
      win.style.display = 'none';
    });
  }

  prechatStartBtn.addEventListener('click', () => {
    const name = prechatNameEl.value.trim();
    const email = prechatEmailEl.value.trim();

    if (!name) {
      prechatErrorEl.style.display = 'block';
      prechatNameEl.focus();
      return;
    }
    prechatErrorEl.style.display = 'none';

    visitorName = name;
    visitorEmail = email;
    localStorage.setItem('lc_visitor_name', name);
    localStorage.setItem('lc_visitor_email', email);

    showChatArea();
    if (!socket) initSocket();
  });

  [prechatNameEl, prechatEmailEl].forEach((el) => {
    el.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') prechatStartBtn.click();
    });
  });

  async function sendMessage() {
    const text = inputEl.value.trim();

    if (pendingFile) {
      await sendFile(pendingFile, text);
      clearPendingFile();
      inputEl.value = '';
      return;
    }

    if (!text) return;
    inputEl.value = '';
    appendMsg({ text, type: 'text' }, 'user');

    await ensureRoom();
    const res = await fetch(SERVER_URL + '/api/chat/message', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ room_id: roomId, text }),
    });

    if (res.status === 403) {
      const data = await res.json().catch(() => ({}));
      setInputEnabled(false);
      appendSystemMsg(data.message || '🚫 Chat ini telah diblokir oleh admin.');
    }
  }

  async function sendFile(file, caption) {
    await ensureRoom();

    const isImage = file.type.startsWith('image/');
    const localUrl = URL.createObjectURL(file);
    appendMsg(
      { text: caption || file.name, type: isImage ? 'image' : 'file', url: localUrl, filename: file.name },
      'user'
    );

    const formData = new FormData();
    formData.append('room_id', roomId);
    formData.append('file', file);
    if (caption) formData.append('caption', caption);

    try {
      const res = await fetch(SERVER_URL + '/api/chat/upload', { method: 'POST', body: formData });
      if (res.status === 403) {
        const data = await res.json().catch(() => ({}));
        setInputEnabled(false);
        appendSystemMsg(data.message || '🚫 Chat ini telah diblokir oleh admin.');
      } else if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        appendSystemMsg('⚠️ ' + (data.message || 'Gagal mengirim file, coba lagi.'));
      }
    } catch (e) {
      console.error('[livechat] gagal upload file', e);
      appendSystemMsg('⚠️ Gagal mengirim file, cek koneksi kamu dan coba lagi.');
    }
  }

  function setPendingFile(file) {
    pendingFile = file;
    uploadNameEl.textContent = file.name;
    uploadPreviewEl.style.display = 'flex';
  }

  function clearPendingFile() {
    pendingFile = null;
    fileInputEl.value = '';
    uploadPreviewEl.style.display = 'none';
  }

  attachBtn.addEventListener('click', () => fileInputEl.click());

  fileInputEl.addEventListener('change', () => {
    const file = fileInputEl.files[0];
    if (file) setPendingFile(file);
  });

  uploadCancelBtn.addEventListener('click', clearPendingFile);

  sendBtn.addEventListener('click', sendMessage);
  inputEl.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') sendMessage();
  });
})();