<!DOCTYPE html>
<html lang="es">
<head>
  <script>/*pos_theme_early*/(function(){var t=localStorage.getItem("pos_theme")||"industrial";document.documentElement.setAttribute("data-theme",t);})()</script>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Marketplace B2B — Nexus Autoparts POS</title>
  <link rel="stylesheet" href="/pos/static/css/chat.css" />
  <link rel="stylesheet" href="/pos/static/css/tokens.css" />
  <link rel="stylesheet" href="/pos/static/css/common.css" />
  <link rel="stylesheet" href="/pos/static/css/pos-ui.css?v=33" />
  <link rel="stylesheet" href="/pos/static/css/sidebar.css" />
  <link rel="stylesheet" href="/pos/static/css/pos-glass.css" />
  <link rel="manifest" href="/pos/static/pwa/manifest.json" />
  <meta name="theme-color" content="#F5A623" />
  <link rel="shortcut icon" type="image/png" href="/pos/static/pwa/icon-192.png" />

  <link rel="stylesheet" href="/pos/static/css/marketplace.css"></head>
<body>

  <header class="page-header">
    <div class="page-title">Marketplace B2B</div>
    <div style="display:flex;gap:var(--space-3);align-items:center;">
      <span class="user-role" id="userRoleTag">cargando...</span>
      <a href="/pos/catalog" style="color:var(--color-text-secondary);">← POS</a>
    </div>
  </header>

  <!-- Tab bar — rendered dynamically based on role -->
  <nav class="tab-bar" id="tabBar">
    <!-- buttons injected by JS -->
  </nav>

  <!-- ══════════ TAB: Browse (buyer) ══════════ -->
  <section class="tab-panel" id="panel-browse">
    <div class="search-row">
      <input type="text" id="browseQuery" placeholder="Buscar parte, marca, numero OEM..." autocomplete="off">
      <input type="text" id="browseCity" placeholder="Ciudad (opcional)" style="max-width:200px;">
      <button onclick="runBrowseSearch()">Buscar</button>
    </div>
    <div id="browseResults" class="results-grid"></div>
  </section>

  <!-- ══════════ TAB: Mis POs (buyer) ══════════ -->
  <section class="tab-panel" id="panel-mine">
    <h2 style="margin-bottom:var(--space-4);font-family:var(--font-heading);">Mis Pedidos</h2>
    <div id="minePOList"></div>
  </section>

  <!-- ══════════ TAB: Inbox (seller) ══════════ -->
  <section class="tab-panel" id="panel-inbox">
    <h2 style="margin-bottom:var(--space-4);font-family:var(--font-heading);">Pedidos Recibidos</h2>
    <div id="inboxPOList"></div>
  </section>

  <!-- ══════════ TAB: Mi Inventario (seller) ══════════ -->
  <section class="tab-panel" id="panel-inventory">
    <h2 style="margin-bottom:var(--space-4);font-family:var(--font-heading);">Mi Inventario</h2>
    <div class="upload-box">
      <label>Cargar inventario via CSV</label>
      <textarea id="csvText" placeholder="part_number,stock,price,name&#10;AB-123,5,150.50,Filtro de aceite&#10;CD-456,12,89.00,Balata delantera"></textarea>
      <div class="hint">
        Columnas requeridas: <code>part_number, stock, price</code>.
        Opcionales: <code>name, min_order, warehouse_location, currency</code>.
        <br>Si la parte no existe en el catálogo, se crea automáticamente como <em>seller listing</em>.
      </div>
      <button style="margin-top:var(--space-3);padding:var(--space-3) var(--space-6);background:var(--gradient-accent);color:var(--btn-primary-text);border:none;border-radius:var(--radius-md);font-weight:bold;cursor:pointer;" onclick="uploadCSV()">Subir CSV</button>
      <div id="uploadResult" style="margin-top:var(--space-3);font-size:var(--text-body-sm);"></div>
    </div>
  </section>

  <!-- ══════════ PO Detail Modal ══════════ -->
  <div class="modal-overlay" id="poModal">
    <div class="modal-content">
      <button class="modal-close" onclick="closeModal('poModal')">✕</button>
      <div class="modal-title" id="poModalTitle">Pedido</div>
      <div id="poModalBody">cargando...</div>
    </div>
  </div>

  <!-- ══════════ Part Detail / Create PO Modal ══════════ -->
  <div class="modal-overlay" id="partModal">
    <div class="modal-content">
      <button class="modal-close" onclick="closeModal('partModal')">✕</button>
      <div class="modal-title" id="partModalTitle">Detalle de parte</div>
      <div id="partModalBody">cargando...</div>
    </div>
  </div>

  <script>
  (function () {
    'use strict';
    var API = '/pos/api/marketplace';
    var TOKEN = localStorage.getItem('pos_token') || '';

    // ── Auth headers helper ──
    function headers() {
      return {
        'Authorization': 'Bearer ' + TOKEN,
        'Content-Type': 'application/json',
        'X-Device-Id': localStorage.getItem('pos_device_id') || 'web',
      };
    }

    function apiFetch(path, opts) {
      opts = opts || {};
      opts.headers = headers();
      return fetch(API + path, opts).then(function (r) {
        if (r.status === 401) {
          window.location.href = '/pos/login';
          return null;
        }
        return r.json();
      });
    }

    // ── HTML escape ──
    function esc(s) {
      var d = document.createElement('div');
      d.textContent = s || '';
      return d.innerHTML;
    }

    function fmt(n) {
      return (n || 0).toLocaleString('es-MX', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    }

    // ── Role detection (reads from JWT payload) ──
    // Since we don't expose a /whoami endpoint, try to derive role from
    // the orders/inbox endpoint — if it returns 403, the user is a buyer.
    // Admin users can see everything so default to 'admin' view.
    var userRole = 'buyer';  // default
    function detectRole() {
      // Use the /whoami endpoint to reliably detect the marketplace role.
      return apiFetch('/whoami').then(function (data) {
        if (data && data.marketplace_role) {
          userRole = data.marketplace_role;
        } else {
          userRole = 'buyer';
        }
        document.getElementById('userRoleTag').textContent =
          userRole + (data && data.bodega_id ? ' · bodega #' + data.bodega_id : '');
        renderTabs();
      });
    }

    // ── Render tab bar based on role ──
    function renderTabs() {
      var tabs;
      if (userRole === 'seller' || userRole === 'admin') {
        tabs = [
          { id: 'inbox',     label: 'Pedidos Recibidos' },
          { id: 'inventory', label: 'Mi Inventario' },
          { id: 'browse',    label: 'Explorar' },
        ];
      } else {
        tabs = [
          { id: 'browse', label: 'Explorar' },
          { id: 'mine',   label: 'Mis Pedidos' },
        ];
      }

      var bar = document.getElementById('tabBar');
      bar.innerHTML = tabs.map(function (t) {
        return '<button class="tab-btn" data-tab="' + t.id + '" onclick="switchTab(\'' + t.id + '\')">' + t.label + '</button>';
      }).join('');

      // Open the first tab by default
      switchTab(tabs[0].id);
    }

    window.switchTab = function (id) {
      document.querySelectorAll('.tab-btn').forEach(function (b) {
        b.classList.toggle('active', b.dataset.tab === id);
      });
      document.querySelectorAll('.tab-panel').forEach(function (p) {
        p.classList.toggle('active', p.id === 'panel-' + id);
      });
      // Lazy-load content per tab
      if (id === 'browse') runBrowseSearch();
      if (id === 'mine') loadMyPOs();
      if (id === 'inbox') loadInbox();
    };

    // ═══════════════════════════════════════════════════════════════════
    // BROWSE
    // ═══════════════════════════════════════════════════════════════════

    window.runBrowseSearch = function () {
      var q = document.getElementById('browseQuery').value.trim();
      var city = document.getElementById('browseCity').value.trim();
      var params = [];
      if (q) params.push('q=' + encodeURIComponent(q));
      if (city) params.push('city=' + encodeURIComponent(city));
      var url = '/inventory/search' + (params.length ? '?' + params.join('&') : '');

      var grid = document.getElementById('browseResults');
      grid.innerHTML = '<div class="empty-state">Buscando...</div>';

      apiFetch(url).then(function (resp) {
        if (!resp || !resp.data) { grid.innerHTML = '<div class="empty-state"><h3>Error</h3></div>'; return; }
        if (resp.data.length === 0) {
          grid.innerHTML = '<div class="empty-state"><h3>Sin resultados</h3><p>Ninguna bodega tiene esta parte en stock.</p></div>';
          return;
        }
        grid.innerHTML = resp.data.map(function (p) {
          var priceStr = p.min_price === p.max_price
            ? '$' + fmt(p.min_price)
            : '$' + fmt(p.min_price) + ' – $' + fmt(p.max_price);
          var isOem = p.listing_type === 'oem';
          var badge = isOem
            ? '<span style="background:#3FB95020;color:#3FB950;padding:2px 6px;border-radius:4px;font-size:var(--text-caption);">Catálogo</span>'
            : '<span style="background:#F5A62320;color:#F5A623;padding:2px 6px;border-radius:4px;font-size:var(--text-caption);">Listing</span>';
          var onclick = isOem
            ? 'openPartDetail(' + p.id + ')'
            : 'openListingDetail(' + p.id + ')';
          return '<div class="part-card" onclick="' + onclick + '">' +
            '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--space-1);">' +
              '<div class="part-card__oem">' + esc(p.part_number) + '</div>' +
              badge +
            '</div>' +
            '<div class="part-card__name">' + esc(p.name) + '</div>' +
            '<div class="part-card__meta">' +
              '<span class="price-range">' + priceStr + '</span>' +
              '<span class="stock-pill">' + esc(p.total_stock_hint) + '</span>' +
            '</div>' +
            '<div style="font-size:var(--text-caption);color:var(--color-text-muted);margin-top:var(--space-2);">' +
              p.bodega_count + ' bodega' + (p.bodega_count !== 1 ? 's' : '') +
            '</div>' +
          '</div>';
        }).join('');
      });
    };

    // ═══════════════════════════════════════════════════════════════════
    // PART DETAIL + CREATE PO
    // ═══════════════════════════════════════════════════════════════════

    var cart = [];  // {part_id, bodega_id, part_name, oem, quantity, unit_price}

    window.openPartDetail = function (partId) {
      var modal = document.getElementById('partModal');
      modal.classList.add('open');
      document.getElementById('partModalBody').innerHTML = 'Cargando bodegas...';

      apiFetch('/inventory/part/' + partId).then(function (resp) {
        if (!resp || !resp.data) return;
        var bodegas = resp.data;
        if (bodegas.length === 0) {
          document.getElementById('partModalBody').innerHTML = '<div class="empty-state">Ninguna bodega tiene esta parte en stock.</div>';
          return;
        }
        var html = '<p style="color:var(--color-text-muted);margin-bottom:var(--space-3);">Elige una bodega para ordenar:</p>';
        html += '<div style="display:flex;flex-direction:column;gap:var(--space-2);">';
        bodegas.forEach(function (b) {
          html += '<div style="padding:var(--space-3);border:1px solid var(--glass-border);border-radius:var(--radius-md);display:flex;justify-content:space-between;align-items:center;">' +
            '<div>' +
              '<strong>' + esc(b.name) + '</strong>' +
              '<div style="color:var(--color-text-muted);font-size:var(--text-caption);">' + esc(b.city || '') + ' · ' + esc(b.stock_hint) + '</div>' +
            '</div>' +
            '<div style="text-align:right;">' +
              '<div class="price-range">$' + fmt(b.price) + '</div>' +
              '<button style="margin-top:var(--space-1);padding:var(--space-1) var(--space-3);background:var(--gradient-accent);color:var(--btn-primary-text);border:none;border-radius:var(--radius-sm);font-size:var(--text-caption);cursor:pointer;" onclick="createOrderFor(' + partId + ', null, ' + b.id_bodega + ', \'' + esc(b.name).replace(/\'/g, '\\\'') + '\', ' + (b.price || 0) + ')">Ordenar</button>' +
            '</div>' +
          '</div>';
        });
        html += '</div>';
        document.getElementById('partModalBody').innerHTML = html;
      });
    };

    window.openListingDetail = function (wiId) {
      var modal = document.getElementById('partModal');
      modal.classList.add('open');
      document.getElementById('partModalBody').innerHTML = 'Cargando bodegas...';

      apiFetch('/inventory/listing/' + wiId).then(function (resp) {
        if (!resp || !resp.data) return;
        var bodegas = resp.data;
        if (bodegas.length === 0) {
          document.getElementById('partModalBody').innerHTML = '<div class="empty-state">Ninguna bodega tiene esta parte en stock.</div>';
          return;
        }
        var html = '<p style="color:var(--color-text-muted);margin-bottom:var(--space-3);">Elige una bodega para ordenar:</p>';
        html += '<div style="display:flex;flex-direction:column;gap:var(--space-2);">';
        bodegas.forEach(function (b) {
          html += '<div style="padding:var(--space-3);border:1px solid var(--glass-border);border-radius:var(--radius-md);display:flex;justify-content:space-between;align-items:center;">' +
            '<div>' +
              '<strong>' + esc(b.name) + '</strong>' +
              '<div style="color:var(--color-text-muted);font-size:var(--text-caption);">' + esc(b.city || '') + ' · ' + esc(b.stock_hint) + '</div>' +
            '</div>' +
            '<div style="text-align:right;">' +
              '<div class="price-range">$' + fmt(b.price) + '</div>' +
              '<button style="margin-top:var(--space-1);padding:var(--space-1) var(--space-3);background:var(--gradient-accent);color:var(--btn-primary-text);border:none;border-radius:var(--radius-sm);font-size:var(--text-caption);cursor:pointer;" onclick="createOrderFor(null, ' + wiId + ', ' + b.id_bodega + ', \'' + esc(b.name).replace(/\'/g, '\\\'') + '\', ' + (b.price || 0) + ')">Ordenar</button>' +
            '</div>' +
          '</div>';
        });
        html += '</div>';
        document.getElementById('partModalBody').innerHTML = html;
      });
    };

    window.createOrderFor = function (partId, wiId, bodegaId, bodegaName, price) {
      var qty = prompt('Cantidad a ordenar para "' + bodegaName + '":', '1');
      if (!qty) return;
      qty = parseInt(qty);
      if (qty < 1) return;

      var notes = prompt('Notas para la bodega (opcional):', '') || '';

      var item = { quantity: qty, unit_price: price };
      if (partId) {
        item.part_id = partId;
      } else if (wiId) {
        item.wi_id = wiId;
      } else {
        alert('Error: se requiere part_id o wi_id');
        return;
      }

      // Create PO draft
      apiFetch('/orders', {
        method: 'POST',
        body: JSON.stringify({
          bodega_id: bodegaId,
          items: [item],
          delivery_method: 'pickup',
          buyer_notes: notes,
        }),
      }).then(function (resp) {
        if (!resp || resp.error) {
          alert('Error creando pedido: ' + (resp && resp.error || 'desconocido'));
          return;
        }
        // Auto-submit immediately for now
        apiFetch('/orders/' + resp.po_id + '/transition', {
          method: 'POST',
          body: JSON.stringify({ new_status: 'submitted' }),
        }).then(function (tr) {
          if (tr && tr.ok) {
            alert('✓ Pedido #' + resp.po_id + ' enviado a ' + bodegaName);
            closeModal('partModal');
            if (userRole === 'buyer') switchTab('mine');
          } else {
            alert('Pedido creado #' + resp.po_id + ' pero no se pudo enviar: ' + (tr && tr.error || ''));
          }
        });
      });
    };

    // ═══════════════════════════════════════════════════════════════════
    // MIS POS (buyer)
    // ═══════════════════════════════════════════════════════════════════

    window.loadMyPOs = function () {
      var container = document.getElementById('minePOList');
      container.innerHTML = 'Cargando...';
      apiFetch('/orders/mine?only_mine=false').then(function (resp) {
        renderPOList(container, resp, 'Aun no has creado pedidos.');
      });
    };

    // ═══════════════════════════════════════════════════════════════════
    // INBOX (seller)
    // ═══════════════════════════════════════════════════════════════════

    window.loadInbox = function () {
      var container = document.getElementById('inboxPOList');
      container.innerHTML = 'Cargando...';
      apiFetch('/orders/inbox').then(function (resp) {
        renderPOList(container, resp, 'Aun no hay pedidos recibidos.');
      });
    };

    function renderPOList(container, resp, emptyMsg) {
      if (!resp || resp.error || !resp.data) {
        container.innerHTML = '<div class="empty-state"><h3>Error</h3><p>' + esc(resp && resp.error || 'unknown') + '</p></div>';
        return;
      }
      if (resp.data.length === 0) {
        container.innerHTML = '<div class="empty-state"><h3>Sin pedidos</h3><p>' + emptyMsg + '</p></div>';
        return;
      }
      var html = '<table class="po-table"><thead><tr>' +
        '<th>#</th>' +
        '<th>Estado</th>' +
        (userRole === 'seller' ? '<th>Comprador</th>' : '<th>Bodega</th>') +
        '<th>Items</th>' +
        '<th>Total</th>' +
        '<th>Creado</th>' +
      '</tr></thead><tbody>';
      resp.data.forEach(function (po) {
        var when = po.submitted_at ? new Date(po.submitted_at).toLocaleDateString('es-MX') : '—';
        html += '<tr onclick="openPODetail(' + po.id_po + ')">' +
          '<td><strong>#' + po.id_po + '</strong></td>' +
          '<td><span class="status-badge status-' + po.status + '">' + po.status + '</span></td>' +
          '<td>' + esc(po.bodega_name || po.buyer_display_name || '—') + '</td>' +
          '<td>' + po.item_count + '</td>' +
          '<td>$' + fmt(po.total_amount) + '</td>' +
          '<td>' + when + '</td>' +
        '</tr>';
      });
      html += '</tbody></table>';
      container.innerHTML = html;
    }

    // ═══════════════════════════════════════════════════════════════════
    // PO DETAIL MODAL
    // ═══════════════════════════════════════════════════════════════════

    window.openPODetail = function (poId) {
      var modal = document.getElementById('poModal');
      modal.classList.add('open');
      document.getElementById('poModalTitle').textContent = 'Pedido #' + poId;
      document.getElementById('poModalBody').innerHTML = 'Cargando...';

      apiFetch('/orders/' + poId).then(function (po) {
        if (!po || po.error) {
          document.getElementById('poModalBody').innerHTML = '<div>Error: ' + esc(po && po.error || '') + '</div>';
          return;
        }
        var html = '<div style="display:flex;justify-content:space-between;margin-bottom:var(--space-3);">' +
          '<div>' +
            '<div style="font-size:var(--text-caption);color:var(--color-text-muted);">COMPRADOR</div>' +
            '<div>' + esc(po.buyer_display_name) + '</div>' +
          '</div>' +
          '<div>' +
            '<div style="font-size:var(--text-caption);color:var(--color-text-muted);">BODEGA</div>' +
            '<div>' + esc(po.bodega_name) + '</div>' +
          '</div>' +
          '<div>' +
            '<div style="font-size:var(--text-caption);color:var(--color-text-muted);">ESTADO</div>' +
            '<span class="status-badge status-' + po.status + '">' + po.status + '</span>' +
          '</div>' +
        '</div>';

        html += '<h4 style="margin:var(--space-4) 0 var(--space-2);">Items</h4>';
        html += '<table class="po-table"><thead><tr><th>OEM</th><th>Nombre</th><th>Cant</th><th>Precio</th><th>Subtotal</th></tr></thead><tbody>';
        po.items.forEach(function (it) {
          html += '<tr>' +
            '<td style="font-family:var(--font-mono);">' + esc(it.oem_part_number) + '</td>' +
            '<td>' + esc(it.part_name) + '</td>' +
            '<td>' + it.quantity + '</td>' +
            '<td>$' + fmt(it.unit_price) + '</td>' +
            '<td>$' + fmt(it.subtotal) + '</td>' +
          '</tr>';
        });
        html += '</tbody></table>';

        html += '<div style="text-align:right;font-size:var(--text-h5);margin-top:var(--space-3);"><strong>Total: $' + fmt(po.total_amount) + ' ' + po.currency + '</strong></div>';

        // Transition buttons based on current status + role
        var actions = getActionsForStatus(po.status, userRole);
        if (actions.length) {
          html += '<div style="margin-top:var(--space-4);padding-top:var(--space-4);border-top:1px solid var(--glass-border);display:flex;gap:var(--space-2);">';
          actions.forEach(function (a) {
            html += '<button onclick="transitionPO(' + po.id_po + ', \'' + a.status + '\')" ' +
                    'style="padding:var(--space-2) var(--space-4);background:' + a.color + ';color:#fff;border:none;border-radius:var(--radius-md);font-weight:bold;cursor:pointer;">' +
                    a.label + '</button>';
          });
          html += '</div>';
        }

        // Status history
        if (po.history && po.history.length) {
          html += '<h4 style="margin:var(--space-4) 0 var(--space-2);">Historial</h4>';
          html += '<div style="font-size:var(--text-caption);color:var(--color-text-muted);">';
          po.history.forEach(function (h) {
            html += '<div>' + new Date(h.at).toLocaleString('es-MX') + ' — ' +
                    (h.from_status ? h.from_status + ' → ' : '') + h.to_status +
                    ' (' + h.actor_kind + ')' +
                    (h.note ? ' · ' + esc(h.note) : '') +
                    '</div>';
          });
          html += '</div>';
        }

        document.getElementById('poModalBody').innerHTML = html;
      });
    };

    function getActionsForStatus(status, role) {
      // Map: {role: {status: [{status, label, color}]}}
      var actionMap = {
        buyer: {
          ready:     [{ status: 'delivered', label: 'Marcar recibido', color: '#3FB950' }],
          delivered: [{ status: 'closed',    label: 'Cerrar pedido',   color: '#888' }],
        },
        seller: {
          submitted: [
            { status: 'confirmed', label: 'Confirmar', color: '#00D4FF' },
            { status: 'rejected',  label: 'Rechazar',  color: '#F85149' },
          ],
          confirmed: [{ status: 'ready', label: 'Marcar listo', color: '#A78BFA' }],
          ready:     [{ status: 'delivered', label: 'Marcar entregado', color: '#3FB950' }],
        },
      };
      return (actionMap[role] || {})[status] || [];
    }

    window.transitionPO = function (poId, newStatus) {
      var note = prompt('Nota opcional:', '') || '';
      apiFetch('/orders/' + poId + '/transition', {
        method: 'POST',
        body: JSON.stringify({ new_status: newStatus, note: note }),
      }).then(function (r) {
        if (r && r.ok) {
          openPODetail(poId);
        } else {
          alert('Error: ' + (r && r.error || 'unknown'));
        }
      });
    };

    // ═══════════════════════════════════════════════════════════════════
    // CSV UPLOAD (seller)
    // ═══════════════════════════════════════════════════════════════════

    window.uploadCSV = function () {
      var csv = document.getElementById('csvText').value;
      if (!csv.trim()) { alert('Pega un CSV primero'); return; }

      var resultDiv = document.getElementById('uploadResult');
      resultDiv.innerHTML = 'Subiendo...';

      apiFetch('/inventory/upload', {
        method: 'POST',
        body: JSON.stringify({ csv: csv }),
      }).then(function (r) {
        if (!r || r.error) {
          resultDiv.innerHTML = '<span style="color:#F85149;">Error: ' + esc(r && r.error || 'unknown') + '</span>';
          return;
        }
        var msg = '<span style="color:#3FB950;">✓ ' + r.inserted + ' nuevos, ' +
                  r.updated + ' actualizados';
        if (r.skipped > 0) msg += ', ' + r.skipped + ' omitidos';
        msg += '</span>';
        if (r.oem_count !== undefined || r.seller_count !== undefined) {
          msg += '<div style="margin-top:var(--space-2);font-size:var(--text-caption);color:var(--color-text-muted);">' +
                 (r.oem_count || 0) + ' catálogo OEM · ' + (r.seller_count || 0) + ' seller listings</div>';
        }
        if (r.errors && r.errors.length) {
          msg += '<div style="margin-top:var(--space-2);color:var(--color-text-muted);font-size:var(--text-caption);">';
          r.errors.slice(0, 5).forEach(function (e) {
            msg += '<div>• ' + esc(e) + '</div>';
          });
          if (r.total_errors > 5) msg += '<div>(' + (r.total_errors - 5) + ' errores mas)</div>';
          msg += '</div>';
        }
        resultDiv.innerHTML = msg;
      });
    };

    // ── Generic modal close ──
    window.closeModal = function (id) {
      document.getElementById(id).classList.remove('open');
    };
    // Close modal on outside click
    document.querySelectorAll('.modal-overlay').forEach(function (m) {
      m.addEventListener('click', function (e) {
        if (e.target === m) m.classList.remove('open');
      });
    });

    // ── Boot ──
    if (!TOKEN) {
      window.location.href = '/pos/login';
    } else {
      detectRole();
    }
  })();
  </script>
  <script src="/pos/static/js/chat.js" defer></script>
</body>
</html>
