  // Project context picker: populated from /api/status (which already returns
  // the configured project list). Single-project: rendered as a static label
  // so it's still visible but not clickable. Multi-project: <select> dropdown.
  // Zero-project: a hint to add one. Selection persists per-browser in
  // localStorage and is included in every /api/command-center/stream call.
  // Build the "+ Add" button as a real DOM node (was an HTML string + innerHTML
  // injection — SEC-03 ratchet prefers we avoid that pattern, see
  // test/unit.test.js DYNAMIC_INNERHTML_BASELINE).
  function makeContextAddBtn() {
    var btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'context-add';
    btn.id = 'chat-context-add';
    btn.title = 'Link a new project';
    btn.textContent = '+ Add';
    return btn;
  }
  // Strip variant: empty-projects message.
  function makeContextEmptyNode() {
    var empty = document.createElement('span');
    empty.className = 'context-empty';
    empty.textContent = 'No projects linked yet.';
    return empty;
  }
  // Strip variant: single-project static label (no picker, just the name).
  function makeContextStaticNode(name) {
    var staticSpan = document.createElement('span');
    staticSpan.className = 'context-static';
    staticSpan.textContent = name;
    return staticSpan;
  }
  // Strip variant: multi-project <select>. Returns the select so the caller
  // can attach a change listener.
  function makeContextSelect(projects, selected) {
    var sel = document.createElement('select');
    sel.id = 'chat-context-select';
    sel.setAttribute('aria-label', 'Working in project');
    for (var i = 0; i < projects.length; i++) {
      var p = projects[i];
      var opt = document.createElement('option');
      opt.value = p;
      opt.textContent = p;
      if (p === selected) opt.selected = true;
      sel.appendChild(opt);
    }
    return sel;
  }
  async function loadProjectsAndRenderContext(opts) {
    var stripEl = document.getElementById('chat-context-strip');
    var controlsEl = document.getElementById('chat-context-controls');
    if (!stripEl || !controlsEl) return;
    var preferProject = (opts && opts.preferProject) || null;
    try {
      var res = await fetch('/api/status');
      if (!res.ok) throw new Error('HTTP ' + res.status);
      var data = await res.json();
      var projects = (data && Array.isArray(data.projects) ? data.projects : [])
        .map(function(p) { return p && p.name ? String(p.name) : null; })
        .filter(Boolean);
      if (projects.length === 0) {
        stripEl.style.display = '';
        controlsEl.replaceChildren(makeContextEmptyNode(), makeContextAddBtn());
        currentProject = null;
      } else {
        if (preferProject && projects.indexOf(preferProject) !== -1) {
          currentProject = preferProject;
          try { localStorage.setItem(SLIM_PROJECT_KEY, currentProject); } catch (_e) {}
        } else if (currentProject && projects.indexOf(currentProject) === -1) {
          currentProject = null;
          try { localStorage.removeItem(SLIM_PROJECT_KEY); } catch (_e) {}
        }
        if (!currentProject) {
          currentProject = projects[0];
          try { localStorage.setItem(SLIM_PROJECT_KEY, currentProject); } catch (_e) {}
        }
        if (projects.length === 1) {
          stripEl.style.display = '';
          controlsEl.replaceChildren(makeContextStaticNode(currentProject), makeContextAddBtn());
        } else {
          var sel = makeContextSelect(projects, currentProject);
          stripEl.style.display = '';
          controlsEl.replaceChildren(sel, makeContextAddBtn());
          sel.addEventListener('change', function(ev) {
            currentProject = ev.target.value || null;
            try { localStorage.setItem(SLIM_PROJECT_KEY, currentProject); } catch (_e) {}
          });
        }
      }
      var addBtn = document.getElementById('chat-context-add');
      if (addBtn) addBtn.addEventListener('click', openAddProjectModal);
    } catch (_e) {
      stripEl.style.display = 'none';
    }
  }

  // ── Add-project modal ────────────────────────────────────────
  function openAddProjectModal() {
    var modal = document.getElementById('slim-add-project-modal');
    var input = document.getElementById('slim-add-project-path');
    var msg = document.getElementById('slim-add-project-msg');
    if (!modal) return;
    if (input) { input.value = ''; input.disabled = false; }
    if (msg) { msg.textContent = ''; msg.style.color = ''; }
    modal.classList.add('open');
    if (input) setTimeout(function() { input.focus(); }, 0);
  }
  // Reset both modal fields here so cancel / close-after-success / Esc /
  // backdrop-click all behave the same way: open the modal next time and
  // start fresh, no stale path or status text leaking across openings.
  function closeAddProjectModal() {
    var modal = document.getElementById('slim-add-project-modal');
    var input = document.getElementById('slim-add-project-path');
    var msg = document.getElementById('slim-add-project-msg');
    if (modal) modal.classList.remove('open');
    if (input) { input.value = ''; input.disabled = false; }
    if (msg) { msg.textContent = ''; msg.style.color = ''; }
  }
  async function browseProjectPath() {
    var input = document.getElementById('slim-add-project-path');
    var msg = document.getElementById('slim-add-project-msg');
    if (!input) return;
    if (msg) { msg.textContent = 'Opening folder picker…'; msg.style.color = 'var(--muted)'; }
    // Pre-seed the picker with whatever is in the text box so users who've
    // typed a partial path don't have to re-navigate to it from their home
    // dir. Server validates this strictly (walks up to nearest existing dir).
    // modernPicker: true opts into the slim-UX Explorer-style picker
    // (Microsoft.Win32.OpenFolderDialog with native path bar + InitialDirectory
    // support). The classic dashboard doesn't send this flag and gets the
    // unchanged WinForms FolderBrowserDialog for its Scan Projects flow.
    var initialPath = (input.value || '').trim();
    try {
      var res = await fetch('/api/projects/browse', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ initialPath: initialPath || undefined, modernPicker: true }),
      });
      if (!res.ok) throw new Error('HTTP ' + res.status);
      var data = await res.json();
      if (data && data.path) {
        input.value = data.path;
        if (msg) msg.textContent = '';
      } else if (msg) {
        msg.textContent = 'No folder selected.';
      }
    } catch (e) {
      if (msg) { msg.textContent = 'Browse failed: ' + (e && e.message ? e.message : 'unknown error'); msg.style.color = 'var(--red)'; }
    }
  }
  async function submitAddProject() {
    var input = document.getElementById('slim-add-project-path');
    var msg = document.getElementById('slim-add-project-msg');
    var submitBtn = document.getElementById('slim-add-project-submit');
    if (!input || !msg) return;
    var p = (input.value || '').trim();
    if (!p) { msg.textContent = 'Enter a path or click Browse.'; msg.style.color = 'var(--red)'; return; }
    msg.textContent = 'Linking…';
    msg.style.color = 'var(--muted)';
    if (submitBtn) submitBtn.disabled = true;
    if (input) input.disabled = true;
    try {
      var res = await fetch('/api/projects/add', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ path: p }),
      });
      var data = await res.json().catch(function() { return {}; });
      if (!res.ok) {
        var hint = data && data.needsConfirmation
          ? ' (path is not a git repo — use Settings → Scan Projects to confirm a non-repo path)'
          : '';
        throw new Error((data && data.error) ? data.error + hint : ('HTTP ' + res.status + hint));
      }
      var newName = data && data.name ? data.name : null;
      msg.textContent = 'Linked ' + (newName || p) + '. Refreshing…';
      msg.style.color = 'var(--green)';
      await loadProjectsAndRenderContext({ preferProject: newName });
      setTimeout(closeAddProjectModal, 600);
    } catch (e) {
      msg.textContent = 'Failed: ' + (e && e.message ? e.message : 'unknown error');
      msg.style.color = 'var(--red)';
    } finally {
      if (submitBtn) submitBtn.disabled = false;
      if (input) input.disabled = false;
    }
  }

  loadProjectsAndRenderContext();
  // Wire add-project modal once at startup; the trigger button gets a click
  // listener re-bound on every render of the context strip.
  (function wireAddProjectModal() {
    var modal = document.getElementById('slim-add-project-modal');
    if (!modal) return;
    var closeBtn = document.getElementById('slim-add-project-close');
    var cancelBtn = document.getElementById('slim-add-project-cancel');
    var browseBtn = document.getElementById('slim-add-project-browse');
    var submitBtn = document.getElementById('slim-add-project-submit');
    var input = document.getElementById('slim-add-project-path');
    if (closeBtn) closeBtn.addEventListener('click', closeAddProjectModal);
    if (cancelBtn) cancelBtn.addEventListener('click', closeAddProjectModal);
    if (browseBtn) browseBtn.addEventListener('click', browseProjectPath);
    if (submitBtn) submitBtn.addEventListener('click', submitAddProject);
    if (input) input.addEventListener('keydown', function(ev) {
      if (ev.key === 'Enter') { ev.preventDefault(); submitAddProject(); }
    });
    modal.addEventListener('click', function(ev) {
      if (ev.target === modal) closeAddProjectModal();
    });
  })();

