  // ── Team member cards (status panel, top sub-section) ──────────
  // Maps an agent status to one of the four card classes.
  function memberStatusClass(s) {
    return (s === 'working' || s === 'done' || s === 'error') ? s : 'idle';
  }

  // Build the colored status pill shared by the member card and the detail
  // modal. DOM-built (no innerHTML) to keep the SEC-03 baseline clean.
  function createStatusChip(status) {
    var chip = document.createElement('span');
    chip.className = 'member-status ' + memberStatusClass(status);
    chip.textContent = status || 'idle';
    return chip;
  }

  // Last-rendered agents payload — skip the full grid rebuild when it's
  // unchanged between polls (avoids 5s DOM churn and preserves card focus).
  var _lastAgentsJson = null;

  // Render the square member-card grid from the /api/status `agents` array.
  // Name, role and emoji are config-sourced, so everything goes through
  // textContent rather than innerHTML.
  function renderMembers(agents) {
    var grid = document.getElementById('member-grid');
    if (!grid) return;
    var json = JSON.stringify(agents);
    if (json === _lastAgentsJson) return;
    _lastAgentsJson = json;
    grid.textContent = '';
    if (!agents.length) {
      var empty = document.createElement('div');
      empty.className = 'member-empty';
      empty.textContent = 'No team members';
      grid.appendChild(empty);
      return;
    }
    var frag = document.createDocumentFragment();
    agents.forEach(function(a) {
      if (!a || !a.id) return;
      var card = document.createElement('div');
      card.className = 'member-card ' + memberStatusClass(a.status);
      card.setAttribute('role', 'button');
      card.setAttribute('tabindex', '0');
      card.title = (a.name || a.id) + (a.role ? ' — ' + a.role : '');
      // The clicked agent object is captured directly — no id->lookup round-trip.
      card.addEventListener('click', function() { openAgentDetail(a); });
      card.addEventListener('keydown', function(ev) {
        if (ev.key === 'Enter' || ev.key === ' ') { ev.preventDefault(); openAgentDetail(a); }
      });

      var emoji = document.createElement('div');
      emoji.className = 'member-emoji';
      emoji.textContent = a.emoji || '🤖';
      card.appendChild(emoji);

      var name = document.createElement('div');
      name.className = 'member-name';
      name.textContent = a.name || a.id;
      card.appendChild(name);

      var role = document.createElement('div');
      role.className = 'member-role';
      role.textContent = a.role || '';
      card.appendChild(role);

      card.appendChild(createStatusChip(a.status));
      frag.appendChild(card);
    });
    grid.appendChild(frag);
  }

  // Append a labelled key/value row to the agent detail modal body.
  function appendAgentRow(body, key, value, muted) {
    var row = document.createElement('div');
    row.className = 'agent-detail-row';
    var k = document.createElement('div');
    k.className = 'agent-detail-key';
    k.textContent = key;
    var v = document.createElement('div');
    v.className = 'agent-detail-val' + (muted ? ' muted' : '');
    v.textContent = value;
    row.appendChild(k);
    row.appendChild(v);
    body.appendChild(row);
  }

  // Populate + open the agent detail modal for the given agent object (passed
  // straight from the clicked card).
  function openAgentDetail(a) {
    var modal = document.getElementById('slim-agent-modal');
    var body = document.getElementById('slim-agent-body');
    var titleEl = document.getElementById('slim-agent-title');
    if (!a || !modal || !body) return;
    if (titleEl) titleEl.textContent = a.name || a.id;
    body.textContent = '';

    // Header: emoji + name + role.
    var head = document.createElement('div');
    head.className = 'agent-detail-head';
    var hEmoji = document.createElement('div');
    hEmoji.className = 'agent-detail-emoji';
    hEmoji.textContent = a.emoji || '🤖';
    head.appendChild(hEmoji);
    var hText = document.createElement('div');
    var hName = document.createElement('div');
    hName.className = 'agent-detail-name';
    hName.textContent = a.name || a.id;
    var hRole = document.createElement('div');
    hRole.className = 'agent-detail-role';
    hRole.textContent = a.role || '';
    hText.appendChild(hName);
    hText.appendChild(hRole);
    head.appendChild(hText);
    body.appendChild(head);

    // Status row — reuse the colored member-status chip.
    var statusRow = document.createElement('div');
    statusRow.className = 'agent-detail-row';
    var sk = document.createElement('div');
    sk.className = 'agent-detail-key';
    sk.textContent = 'Status';
    statusRow.appendChild(sk);
    statusRow.appendChild(createStatusChip(a.status));
    body.appendChild(statusRow);

    var runtime = [a.runtime, a.model].filter(Boolean).join(' · ');
    appendAgentRow(body, 'Runtime', runtime || '—', !runtime);

    var task = a.currentTask || a.lastAction || '';
    appendAgentRow(body, 'Current', task || 'Idle — nothing in flight', !task);

    appendAgentRow(body, 'Last result', a.resultSummary || 'No recent output', !a.resultSummary);

    modal.classList.add('open');
  }

  // Shared modal close-binding: close button + backdrop click + Escape.
  // Used by the agent modal and the completions modal below.
