(function() {
  var template = document.getElementById('board-card-template');
  var addCardButtons = document.querySelectorAll('.board-column-add-card');

  var ICONS_BASE = '/static/icons/';
  var ICON_LIST = ['cloud.svg', 'cloud-filled.svg', 'cloud-storm.svg', 'cloud-down.svg', 'cloud-up.svg', 'cloud-exclamation.svg'];
  var boardMarkdownConverter = null;
  var boardRefManifest = null;

  function refreshBoardRefManifest() {
    var ctx = getBoardContext();
    if (!ctx.project || !window.BoardRefs) return Promise.resolve(null);
    return BoardRefs.loadManifest(ctx.project, ctx.board)
      .then(function (manifest) {
        boardRefManifest = manifest;
        return manifest;
      })
      .catch(function () {
        boardRefManifest = { commits: [], refs: [] };
        return boardRefManifest;
      });
  }

  function linkifyMarkdownElement(el) {
    if (!el || !window.BoardRefs || !boardRefManifest) return;
    var ctx = getBoardContext();
    if (!ctx.project) return;
    BoardRefs.linkifyElement(el, boardRefManifest, ctx.project);
  }

  function attachBoardRefAutocomplete(textarea) {
    if (!textarea || !window.BoardRefs || !boardRefManifest) return;
    BoardRefs.attachAutocomplete(textarea, boardRefManifest);
  }

  function whenShowdownReady(cb) {
    if (typeof showdown !== 'undefined') {
      cb();
      return;
    }
    var script = document.getElementById('Showdown-script');
    if (!script) return;
    function run() {
      if (typeof showdown !== 'undefined') cb();
    }
    script.addEventListener('load', run);
    if (script.getAttribute('data-loaded')) run();
  }

  function getBoardMarkdownConverter() {
    if (!boardMarkdownConverter && typeof showdown !== 'undefined') {
      boardMarkdownConverter = new showdown.Converter({ ghCompatibleHeaderId: true });
    }
    return boardMarkdownConverter;
  }

  function markdownToHtml(source) {
    var conv = getBoardMarkdownConverter();
    if (!conv) return null;
    return conv.makeHtml(source || '');
  }

  function htmlToPlainPreview(html) {
    var tmp = document.createElement('div');
    tmp.innerHTML = html;
    return (tmp.textContent || '').replace(/\s+/g, ' ').trim();
  }

  function markdownPlainPreview(source, maxLen) {
    var md = source || '';
    var html = markdownToHtml(md);
    var text = html !== null ? htmlToPlainPreview(html) : md.replace(/\s+/g, ' ').trim();
    if (maxLen && text.length > maxLen) return text.slice(0, maxLen) + '\u2026';
    return text;
  }

  function getMarkdownFromElement(el) {
    if (!el) return '';
    if (Object.prototype.hasOwnProperty.call(el.dataset, 'boardMarkdown')) {
      return el.dataset.boardMarkdown;
    }
    return (el.textContent || '').trim();
  }

  function setMarkdownElement(el, source) {
    if (!el) return;
    var md = source || '';
    el.dataset.boardMarkdown = md;
    el.classList.add('markdown-body', 'board-card-markdown');
    function apply() {
      var html = markdownToHtml(md);
      if (html !== null) {
        el.innerHTML = html;
        linkifyMarkdownElement(el);
      } else {
        el.textContent = md;
      }
    }
    if (typeof showdown !== 'undefined') {
      apply();
    } else {
      el.textContent = md;
      whenShowdownReady(apply);
    }
  }

  function syncCompactDescription(card, source) {
    var preview = card.querySelector('.board-card-description-preview');
    var full = card.querySelector('.board-card-description-full');
    var md = source !== undefined ? source : getMarkdownFromElement(full);
    if (preview) {
      preview.textContent = md ? markdownPlainPreview(md, 120) : '';
      preview.dataset.boardMarkdown = md;
    }
  }

  function preloadIcons() {
    ICON_LIST.forEach(function(name) {
      var img = new Image();
      img.src = ICONS_BASE + name;
    });
  }

  function setCardIcon(card, iconName) {
    var icon = card && card.querySelector && card.querySelector('.board-card-icon');
    if (icon) icon.setAttribute('data-icon', iconName);
  }

  function assignCloudIconToCard(card) {
    setCardIcon(card, 'cloud');
  }

  function assignCloudIconToAllCards() {
    document.querySelectorAll('.board-card').forEach(assignCloudIconToCard);
  }

  preloadIcons();
  function initBoard() {
    assignCloudIconToAllCards();
    refreshBoardRefManifest().then(function () {
      loadTasksForBoard();
      openTaskFromQueryString();
    });
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initBoard);
  } else {
    initBoard();
  }

  function taskDisplayId(ref) {
    if (!ref) return '';
    var slug = ref.replace(/^refs\/tags\/tasks\//, '');
    if (slug.indexOf('task_') === 0) return slug.slice(5);
    return slug;
  }

  function taskDisplayIdShort(fullId) {
    if (!fullId) return '';
    return fullId.length <= 4 ? fullId : fullId.slice(-4);
  }

  function syncCardTitleLineTooltip(card) {
    var titleLine = card.querySelector('.board-card-title-line');
    if (!titleLine) return;
    var titleEl = card.querySelector('.board-card-title');
    var titleText = ((titleEl && titleEl.textContent) || '').trim() || 'Untitled';
    var fullId = card.dataset.taskRef ? taskDisplayId(card.dataset.taskRef) : '';
    titleLine.title = fullId ? (fullId + ': ' + titleText) : titleText;
  }

  function setCardTaskRefDisplay(card, ref, id) {
    var fullId = id || taskDisplayId(ref);
    var idEl = card.querySelector('.board-card-task-id');
    if (idEl) idEl.textContent = taskDisplayIdShort(fullId);
    var refEl = card.querySelector('.board-card-task-ref');
    if (refEl) refEl.textContent = ref || '';
    syncCardTitleLineTooltip(card);
  }

  function getBoardContext() {
    var boardColumns = document.querySelector('.board-columns');
    var project = boardColumns && boardColumns.dataset.project;
    var board = boardColumns && boardColumns.dataset.board;
    if (!project && location.pathname) {
      var m = location.pathname.match(/^\/project\/(.+?)\/board\/?$/);
      if (m) project = m[1];
    }
    if (!board) board = (new URLSearchParams(location.search)).get('b') || 'Tasks';
    return { project: project || '', board: board || 'Tasks' };
  }

  function createCardFromTask(task) {
    if (!template || !template.content) return null;
    var clone = template.content.cloneNode(true);
    var card = clone.querySelector && clone.querySelector('.board-card');
    if (!card) return null;
    var status = task.status || 'TODO';
    card.dataset.taskRef = task.ref || '';
    card.dataset.taskStatus = status;
    setCardTaskRefDisplay(card, task.ref || '', task.id);
    var titleEl = card.querySelector('.board-card-title');
    if (titleEl) titleEl.textContent = task.title || 'Untitled';
    syncCardTitleLineTooltip(card);
    var descFull = card.querySelector('.board-card-description-full');
    if (descFull) setMarkdownElement(descFull, task.description || '');
    syncCompactDescription(card, task.description || '');
    setCardIcon(card, 'cloud-filled');
    var meta = card.querySelector('.board-card-meta');
    if (meta) {
      var badge = meta.querySelector('.badge');
      var assigneeSpan = meta.querySelectorAll('.text-truncate')[0];
      var commentsSpan = meta.querySelector('.board-card-comments-count-meta') || meta.querySelector('.ms-auto');
      if (badge) {
        badge.textContent = task.priority || 'LOW';
        badge.className = 'badge badge-outline text-' + (task.priority === 'CRITICAL' ? 'danger' : task.priority === 'HIGH' ? 'warning' : 'secondary');
      }
      if (assigneeSpan) assigneeSpan.textContent = task.assignee || 'None';
      if (commentsSpan) commentsSpan.textContent = commentCountLabel(task.comments_count || 0);
    }
    var details = card.querySelector('.board-card-details');
    if (details) {
      var dueDate = details.querySelector('.board-card-due-date');
      var updatedAt = details.querySelector('.board-card-updated-at');
      var statusEl = details.querySelector('.board-card-status');
      var priorityEl = details.querySelector('.board-card-priority');
      var assigneeEl = details.querySelector('.board-card-assignee');
      if (dueDate) dueDate.textContent = task.due_date || 'None';
      if (updatedAt) updatedAt.textContent = task.updated_at || 'None';
      if (statusEl) statusEl.textContent = status;
      if (priorityEl) priorityEl.textContent = task.priority || 'LOW';
      if (assigneeEl) assigneeEl.textContent = task.assignee || 'None';
      updateCardCommentCount(card, task.comments_count || 0);
    }
    return clone;
  }

  function groupTasksByStatus(tasks) {
    var byStatus = {};
    if (!Array.isArray(tasks)) return byStatus;
    tasks.forEach(function(task) {
      var s = task.status || 'TODO';
      if (!byStatus[s]) byStatus[s] = [];
      byStatus[s].push(task);
    });
    return byStatus;
  }

  function loadTasksForBoard() {
    var ctx = getBoardContext();
    if (!ctx.project) return;
    var listUrl = '/tasks/list?' + new URLSearchParams({ project: ctx.project, board: ctx.board }).toString();
    fetch(listUrl).then(function(res) {
      if (!res.ok) return;
      return res.json();
    }).then(function(tasks) {
      if (!Array.isArray(tasks)) return;
      var byStatus = groupTasksByStatus(tasks);
      var columns = document.querySelectorAll('.board-column.dropzone');
      columns.forEach(function(column) {
        var status = column.dataset.status || 'TODO';
        var cardsContainer = column.querySelector('.board-column-cards');
        if (!cardsContainer) return;
        cardsContainer.innerHTML = '';
        (byStatus[status] || []).forEach(function(task) {
          var frag = createCardFromTask(task);
          if (frag) cardsContainer.appendChild(frag);
        });
        updateColumnBadge(column);
      });
      refreshBoardRefManifest();
    }).catch(function() {});
  }

  function openTaskFromQueryString() {
    var taskRef = (new URLSearchParams(location.search)).get("task");
    if (!taskRef) return;
    window.setTimeout(function () {
      var card = findBoardCardByTaskRef(taskRef);
      if (card && !card.classList.contains("board-card-popout")) {
        showCardPopout(card);
      }
    }, 0);
  }

  function fetchBoardTasksJson() {
    var ctx = getBoardContext();
    if (!ctx.project) return Promise.resolve(null);
    var listUrl = '/tasks/list?' + new URLSearchParams({ project: ctx.project, board: ctx.board }).toString();
    return fetch(listUrl).then(function(res) {
      return res.ok ? res.json() : null;
    });
  }

  function reorderBoardDomToTaskList(tasks) {
    if (!Array.isArray(tasks)) return;
    var byStatus = groupTasksByStatus(tasks);
    document.querySelectorAll('.board-column.dropzone').forEach(function(column) {
      var status = column.dataset.status || 'TODO';
      var cardsContainer = column.querySelector('.board-column-cards');
      if (!cardsContainer) return;
      var ordered = byStatus[status] || [];
      ordered.forEach(function(task) {
        if (!task.ref) return;
        var card = findBoardCardByTaskRef(task.ref);
        if (card) cardsContainer.appendChild(card);
      });
      updateColumnBadge(column);
    });
  }

  function addDefaultCard(ev) {
    if (!template || !template.content) return;
    var column = ev.currentTarget.closest('.board-column');
    var cardsContainer = column && column.querySelector('.board-column-cards');
    var boardColumns = document.querySelector('.board-columns');
    if (!cardsContainer || !boardColumns) return;
    var ctx = getBoardContext();
    var project = ctx.project;
    var board = ctx.board;
    if (!project) return;
    var clone = template.content.cloneNode(true);
    var card = clone.querySelector && clone.querySelector('.board-card');
    if (!card) return;
    var titleEl = card.querySelector('.board-card-title');
    if (titleEl) titleEl.textContent = 'New task';
    syncCardTitleLineTooltip(card);
    assignCloudIconToCard(card);
    cardsContainer.appendChild(clone);
    var badge = column.querySelector('.board-column-add-card');
    if (badge) {
      badge.textContent = cardsContainer.querySelectorAll('.board-card').length;
    }
    var status = column.dataset.status || 'TODO';
    setCardIcon(card, 'cloud-up');
    var createUrl = '/tasks/create?' + new URLSearchParams({
      project: project,
      board: board,
      title: 'New task',
      description: '',
      status: status,
      priority: 'LOW',
      assignee: '',
      due_date: ''
    }).toString();
    fetch(createUrl, { method: 'POST' }).then(function(res) {
      if (res.ok) {
        return res.json().then(function(body) {
          setCardIcon(card, 'cloud-filled');
          if (body.ref) {
            card.dataset.taskRef = body.ref;
            setCardTaskRefDisplay(card, body.ref);
          }
        });
      }
      if (res.status >= 400 && res.status < 600) {
        setCardIcon(card, 'cloud-exclamation');
      }
    }).catch(function() {
      setCardIcon(card, 'cloud-exclamation');
    });
  }

  addCardButtons.forEach(function(btn) {
    btn.addEventListener('click', addDefaultCard);
  });

  var boardColumns = document.querySelector('.board-columns');
  var draggedCard = null;
  var didDrag = false;
  var boardAuth = { auth_enabled: false, username: null };

  function loadBoardAuthStatus() {
    return fetch('/auth/status', { credentials: 'same-origin' })
      .then(function(res) { return res.ok ? res.json() : null; })
      .then(function(s) {
        if (!s) return;
        boardAuth.auth_enabled = !!s.auth_enabled;
        boardAuth.username = s.username || null;
      })
      .catch(function() {});
  }
  loadBoardAuthStatus();

  function canAddComment() {
    return !boardAuth.auth_enabled || !!boardAuth.username;
  }

  function commentCountLabel(n) {
    return n + ' comment' + (n !== 1 ? 's' : '');
  }

  function updateCardCommentCount(card, count) {
    var n = count || 0;
    var meta = card.querySelector('.board-card-meta');
    if (meta) {
      var commentsSpan = meta.querySelector('.board-card-comments-count-meta') || meta.querySelector('.ms-auto');
      if (commentsSpan) commentsSpan.textContent = commentCountLabel(n);
    }
  }

  function commentAuthorInitials(author) {
    var parts = (author || '').trim().split(/\s+/).filter(Boolean);
    if (!parts.length) return '?';
    if (parts.length === 1) return parts[0].charAt(0).toUpperCase();
    return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
  }

  function commentAvatarHtml(comment) {
    var wrap = document.createElement('span');
    wrap.className = 'board-card-comment-avatar';
    if (comment.gravatar_url) {
      var img = document.createElement('img');
      img.src = comment.gravatar_url;
      img.alt = '';
      img.width = 32;
      img.height = 32;
      img.onerror = function() {
        wrap.replaceChildren();
        var fb = document.createElement('span');
        fb.className = 'board-card-comment-avatar-fallback';
        fb.textContent = commentAuthorInitials(comment.author);
        wrap.appendChild(fb);
      };
      wrap.appendChild(img);
    } else {
      var fb = document.createElement('span');
      fb.className = 'board-card-comment-avatar-fallback';
      fb.textContent = commentAuthorInitials(comment.author);
      wrap.appendChild(fb);
    }
    return wrap;
  }

  function renderCommentsList(card, comments) {
    var list = card.querySelector('.board-card-comments-list');
    if (!list) return;
    list.innerHTML = '';
    if (!Array.isArray(comments) || !comments.length) return;
    comments.forEach(function(comment) {
      var row = document.createElement('div');
      row.className = 'board-card-comment-item';
      row.appendChild(commentAvatarHtml(comment));
      var body = document.createElement('div');
      body.className = 'board-card-comment-body';
      var authorEl = document.createElement('div');
      authorEl.className = 'board-card-comment-author';
      authorEl.textContent = comment.author || 'Unknown';
      var contentEl = document.createElement('div');
      contentEl.className = 'board-card-comment-content';
      setMarkdownElement(contentEl, comment.content || '');
      body.appendChild(authorEl);
      body.appendChild(contentEl);
      row.appendChild(body);
      list.appendChild(row);
    });
  }

  function syncCommentFormVisibility(card) {
    var form = card.querySelector('.board-card-comment-form');
    var hint = card.querySelector('.board-card-comment-signin-hint');
    if (!form || !hint) return;
    if (canAddComment()) {
      form.classList.remove('d-none');
      hint.classList.add('d-none');
    } else {
      form.classList.add('d-none');
      hint.classList.remove('d-none');
    }
  }

  function loadCommentsForCard(card) {
    var taskRef = card.dataset.taskRef;
    if (!taskRef) return Promise.resolve();
    var ctx = getBoardContext();
    if (!ctx.project) return Promise.resolve();
    var listUrl = '/comments/list?' + new URLSearchParams({
      project: ctx.project,
      board: ctx.board,
      task: taskRef
    }).toString();
    return fetch(listUrl, { credentials: 'same-origin' })
      .then(function(res) { return res.ok ? res.json() : []; })
      .then(function(comments) {
        if (!Array.isArray(comments)) comments = [];
        renderCommentsList(card, comments);
        updateCardCommentCount(card, comments.length);
        return comments;
      })
      .catch(function() { return []; });
  }

  function setupCommentForm(popoutCard) {
    var form = popoutCard.querySelector('.board-card-comment-form');
    if (!form || form.dataset.bound === '1') return;
    form.dataset.bound = '1';
    syncCommentFormVisibility(popoutCard);
    var commentInput = form.querySelector('.board-card-comment-input');
    attachBoardRefAutocomplete(commentInput);
    form.addEventListener('submit', function(e) {
      e.preventDefault();
      if (!canAddComment()) return;
      var taskRef = popoutCard.dataset.taskRef;
      if (!taskRef) return;
      var input = form.querySelector('.board-card-comment-input');
      var content = (input && input.value) ? input.value.trim() : '';
      if (!content) return;
      var ctx = getBoardContext();
      if (!ctx.project) return;
      var createUrl = '/comments/create?' + new URLSearchParams({
        project: ctx.project,
        board: ctx.board,
        task: taskRef,
        content: content
      }).toString();
      fetch(createUrl, { method: 'POST', credentials: 'same-origin' })
        .then(function(res) {
          if (!res.ok) {
            var msg = (res.status === 401 || res.status === 403)
              ? 'Not authorized to add comments (sign in again if needed).'
              : 'Could not post comment.';
            showBoardError(msg);
            return null;
          }
          if (input) input.value = '';
          return loadCommentsForCard(popoutCard);
        })
        .catch(function() {
          showBoardError('Could not post comment.');
        });
    });
  }

  function findBoardCardByTaskRef(taskRef) {
    if (!taskRef) return null;
    var cards = document.querySelectorAll('.board-card');
    for (var i = 0; i < cards.length; i++) {
      if (cards[i].dataset.taskRef === taskRef) return cards[i];
    }
    return null;
  }

  function clearColumnDropHighlight() {
    document.querySelectorAll('.board-column.dropzone.border-primary').forEach(function(el) {
      el.classList.remove('border-primary');
    });
  }

  function dragTransferLooksLikeTask(e) {
    if (draggedCard) return true;
    var types = e.dataTransfer && e.dataTransfer.types;
    if (!types || !types.length) return false;
    for (var i = 0; i < types.length; i++) {
      if (types[i] === 'text/plain' || types[i] === 'Text') return true;
    }
    return false;
  }

  function showBoardError(message) {
    var anchor = boardColumns && boardColumns.parentNode;
    if (!anchor) return;
    var existing = document.querySelector('.board-task-error-hint');
    if (existing) existing.remove();
    var el = document.createElement('div');
    el.className = 'alert board-task-error-hint py-2 px-3 mb-2';
    el.setAttribute('role', 'alert');
    el.textContent = message;
    anchor.insertBefore(el, boardColumns);
    window.setTimeout(function() {
      if (el.parentNode) el.remove();
    }, 8000);
  }

  function updateColumnBadge(column) {
    var cardsContainer = column && column.querySelector('.board-column-cards');
    var badge = column && column.querySelector('.board-column-add-card');
    if (badge && cardsContainer) {
      badge.textContent = cardsContainer.querySelectorAll('.board-card').length;
    }
  }

  function handleDragStart(e) {
    var card = e.target.closest && e.target.closest('.board-card');
    if (!card) return;
    didDrag = true;
    draggedCard = card;
    e.dataTransfer.effectAllowed = 'move';
    try {
      e.dataTransfer.setData('text/plain', card.dataset.taskRef || '');
    } catch (err) {
      /* ignore setData failures in restricted environments */
    }
    card.classList.add('opacity-50');
  }
  function handleDragEnd(e) {
    var card = (draggedCard && draggedCard.classList.contains('opacity-50') ? draggedCard : null) ||
      (e.target.closest && e.target.closest('.board-card'));
    if (card) card.classList.remove('opacity-50');
    clearColumnDropHighlight();
    window.setTimeout(function() {
      draggedCard = null;
      didDrag = false;
    }, 0);
  }

  /** Parse display date text to YYYY-MM-DD for input[type=date]. Returns '' if none. */
  function parseDateForInput(text) {
    if (!text || text.trim() === 'None') return '';
    var s = text.trim();
    var m = s.match(/^(\d{4})-(\d{2})-(\d{2})/);
    return m ? m[0] : '';
  }

  function setupPopoutEditables(popoutCard) {
    var titleEl = popoutCard.querySelector('.board-card-title');
    var descEl = popoutCard.querySelector('.board-card-description-full');
    var dueEl = popoutCard.querySelector('.board-card-due-date');
    var statusEl = popoutCard.querySelector('.board-card-status');
    var priorityEl = popoutCard.querySelector('.board-card-priority');

    function pushTaskUpdate() {
      var taskRef = popoutCard.dataset.taskRef;
      if (!taskRef) return;
      var ctx = getBoardContext();
      if (!ctx.project) return;
      var tEl = popoutCard.querySelector('.board-card-title');
      var dEl = popoutCard.querySelector('.board-card-description-full');
      var dueEl_ = popoutCard.querySelector('.board-card-due-date');
      var sEl = popoutCard.querySelector('.board-card-status');
      var pEl = popoutCard.querySelector('.board-card-priority');
      var aEl = popoutCard.querySelector('.board-card-assignee');
      var dueVal = (dueEl_ && dueEl_.textContent) ? dueEl_.textContent.trim() : '';
      var statusDisplay = (sEl && sEl.textContent) ? sEl.textContent.trim() : 'TODO';
      var priorityDisplay = (pEl && pEl.textContent) ? pEl.textContent.trim() : 'LOW';
      var body = {
        title: (tEl && tEl.textContent) ? tEl.textContent.trim() || 'Untitled' : 'Untitled',
        description: getMarkdownFromElement(dEl),
        status: statusDisplay ? statusDisplay.replace(/\s+/g, '_').toUpperCase() : 'TODO',
        priority: priorityDisplay ? priorityDisplay.replace(/\s+/g, '_').toUpperCase() : 'LOW',
        assignee: (aEl && aEl.textContent && aEl.textContent.trim() !== 'None') ? aEl.textContent.trim() : null,
        due_date: (dueVal && dueVal !== 'None') ? dueVal : null
      };
      fetch('/tasks/update?' + new URLSearchParams({ project: ctx.project, board: ctx.board, task: taskRef }).toString(), {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      }).catch(function() {});
    }

    if (titleEl) titleEl.classList.add('board-card-editable');
    function commitTitle() {
      var input = popoutCard.querySelector('.board-card-title-edit');
      if (!input) return;
      var val = (input.value || '').trim() || 'Untitled';
      titleEl.textContent = val;
      titleEl.classList.remove('d-none');
      input.remove();
      syncCardTitleLineTooltip(popoutCard);
      pushTaskUpdate();
    }
    if (titleEl) {
      titleEl.addEventListener('click', function () {
        if (popoutCard.querySelector('.board-card-title-edit')) return;
        var val = (titleEl.textContent || '').trim();
        var input = document.createElement('input');
        input.type = 'text';
        input.className = 'form-control form-control-sm board-card-title-edit';
        input.value = val;
        titleEl.classList.add('d-none');
        titleEl.parentNode.insertBefore(input, titleEl);
        input.focus();
        input.addEventListener('blur', commitTitle);
        input.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); input.blur(); } });
      });
    }

    function commitDescription() {
      var textarea = popoutCard.querySelector('.board-card-description-edit');
      if (!textarea) return;
      var val = (textarea.value || '').trim();
      setMarkdownElement(descEl, val);
      syncCompactDescription(popoutCard, val);
      descEl.classList.remove('d-none');
      textarea.remove();
      pushTaskUpdate();
    }
    if (descEl) {
      descEl.addEventListener('click', function () {
        if (popoutCard.querySelector('.board-card-description-edit')) return;
        var val = getMarkdownFromElement(descEl);
        var textarea = document.createElement('textarea');
        textarea.className = 'form-control form-control-sm board-card-description-edit mt-1';
        textarea.rows = 3;
        textarea.value = val;
        descEl.classList.add('d-none');
        descEl.parentNode.insertBefore(textarea, descEl);
        attachBoardRefAutocomplete(textarea);
        textarea.focus();
        textarea.addEventListener('blur', commitDescription);
      });
    }

    function commitDueDate() {
      var input = popoutCard.querySelector('.board-card-due-date-edit');
      if (!input) return;
      var val = (input.value || '').trim();
      dueEl.textContent = val || 'None';
      dueEl.classList.remove('d-none');
      input.remove();
      pushTaskUpdate();
    }
    if (dueEl) {
      dueEl.addEventListener('click', function () {
        if (popoutCard.querySelector('.board-card-due-date-edit')) return;
        var val = parseDateForInput(dueEl.textContent);
        var input = document.createElement('input');
        input.type = 'date';
        input.className = 'form-control form-control-sm board-card-due-date-edit mt-1';
        input.value = val;
        dueEl.classList.add('d-none');
        dueEl.parentNode.insertBefore(input, dueEl);
        input.focus();
        input.addEventListener('blur', commitDueDate);
      });
    }

    function commitStatus() {
      var sel = popoutCard.querySelector('.board-card-status-edit');
      if (!sel) return;
      var display = (sel.options[sel.selectedIndex] && sel.options[sel.selectedIndex].text) ? sel.options[sel.selectedIndex].text : (sel.value || 'TODO');
      statusEl.textContent = display || 'TODO';
      statusEl.classList.remove('d-none');
      sel.remove();
      var statusValue = display ? display.replace(/\s+/g, '_').toUpperCase() : 'TODO';
      popoutCard.dataset.taskStatus = statusValue;
      pushTaskUpdate();
    }
    if (statusEl) {
      statusEl.addEventListener('click', function () {
        if (popoutCard.querySelector('.board-card-status-edit')) return;
        var current = (statusEl.textContent || '').trim() || 'TODO';
        var sel = document.createElement('select');
        sel.className = 'form-select form-select-sm board-card-status-edit mt-1';
        sel.innerHTML = '';
        var opt = document.createElement('option');
        opt.value = current;
        opt.textContent = current;
        opt.selected = true;
        sel.appendChild(opt);
        statusEl.classList.add('d-none');
        statusEl.parentNode.insertBefore(sel, statusEl);
        sel.focus();
        sel.addEventListener('blur', commitStatus);
        sel.addEventListener('change', commitStatus);
      });
    }

    function commitPriority() {
      var sel = popoutCard.querySelector('.board-card-priority-edit');
      if (!sel) return;
      var display = (sel.options[sel.selectedIndex] && sel.options[sel.selectedIndex].text) ? sel.options[sel.selectedIndex].text : (sel.value || 'LOW');
      priorityEl.textContent = display || 'LOW';
      priorityEl.classList.remove('d-none');
      sel.remove();
      pushTaskUpdate();
    }
    if (priorityEl) {
      priorityEl.addEventListener('click', function () {
        if (popoutCard.querySelector('.board-card-priority-edit')) return;
        var current = (priorityEl.textContent || '').trim() || 'LOW';
        var sel = document.createElement('select');
        sel.className = 'form-select form-select-sm board-card-priority-edit mt-1';
        sel.innerHTML = '';
        var opt = document.createElement('option');
        opt.value = current;
        opt.textContent = current;
        opt.selected = true;
        sel.appendChild(opt);
        priorityEl.classList.add('d-none');
        priorityEl.parentNode.insertBefore(sel, priorityEl);
        sel.focus();
        sel.addEventListener('blur', commitPriority);
        sel.addEventListener('change', commitPriority);
      });
    }
  }

  function showCardPopout(card) {
    var cardsContainer = card.parentNode;
    var nextSibling = card.nextSibling;
    card.classList.add('board-card-popout');
    card.draggable = false;
    card.removeAttribute('draggable');
    var details = card.querySelector('.board-card-details');
    if (details) details.classList.remove('d-none');
    setupPopoutEditables(card);
    setupCommentForm(card);
    var descFull = card.querySelector('.board-card-description-full');
    if (descFull && !Object.prototype.hasOwnProperty.call(descFull.dataset, 'boardMarkdown')) {
      setMarkdownElement(descFull, getMarkdownFromElement(descFull));
      syncCompactDescription(card);
    } else if (descFull) {
      linkifyMarkdownElement(descFull);
    }
    document.querySelectorAll('.board-card-comment-content.board-card-markdown').forEach(function (el) {
      if (card.contains(el)) linkifyMarkdownElement(el);
    });
    loadCommentsForCard(card);
    var overlay = document.createElement('div');
    overlay.className = 'board-card-popout-overlay';
    overlay.appendChild(card);
    function close() {
      overlay.removeEventListener('click', closeOnBackdrop);
      document.body.removeChild(overlay);
      card.classList.remove('board-card-popout');
      card.setAttribute('draggable', 'true');
      card.draggable = true;
      if (details) details.classList.add('d-none');
      if (nextSibling) {
        cardsContainer.insertBefore(card, nextSibling);
      } else {
        cardsContainer.appendChild(card);
      }
      updateColumnBadge(cardsContainer.closest('.board-column'));
    }
    function closeOnBackdrop(e) {
      if (e.target === overlay) close();
    }
    overlay.addEventListener('click', closeOnBackdrop);
    document.body.appendChild(overlay);
    updateColumnBadge(cardsContainer.closest('.board-column'));
  }

  function handleCardClick(e) {
    if (didDrag) return;
    var card = e.target.closest && e.target.closest('.board-card');
    if (!card || card.classList.contains('board-card-popout')) return;
    e.preventDefault();
    showCardPopout(card);
  }

  function handleBoardDragOver(e) {
    if (!boardColumns || !boardColumns.contains(e.target)) return;
    var col = e.target.closest && e.target.closest('.board-column.dropzone');
    if (!col || !dragTransferLooksLikeTask(e)) return;
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    clearColumnDropHighlight();
    col.classList.add('border-primary');
  }

  function pushTaskStatusUpdate(card, newStatus) {
    var taskRef = card && card.dataset.taskRef;
    if (!taskRef) return Promise.resolve({ ok: false, status: 0 });
    var ctx = getBoardContext();
    if (!ctx.project) return Promise.resolve({ ok: false, status: 0 });
    return fetch('/tasks/update?' + new URLSearchParams({ project: ctx.project, board: ctx.board, task: taskRef }).toString(), {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ status: newStatus || 'TODO' })
    }).then(function(res) {
      return { ok: res.ok, status: res.status };
    }).catch(function() {
      return { ok: false, status: 0 };
    });
  }

  function handleBoardDrop(e) {
    var col = e.target.closest && e.target.closest('.board-column.dropzone');
    if (!col || !boardColumns || !boardColumns.contains(e.target)) return;
    e.preventDefault();
    e.stopPropagation();
    clearColumnDropHighlight();
    var taskRef = '';
    try {
      taskRef = e.dataTransfer.getData('text/plain') || '';
    } catch (err2) {
      taskRef = '';
    }
    var card = draggedCard || findBoardCardByTaskRef(taskRef);
    if (!card) return;
    var targetColumn = col;
    var targetCards = targetColumn.querySelector('.board-column-cards');
    if (!targetCards) return;
    var sourceColumn = card.closest && card.closest('.board-column');
    if (sourceColumn === targetColumn) return;
    var newStatus = targetColumn.dataset.status || 'TODO';
    var prevStatus = card.dataset.taskStatus || 'TODO';
    var sourceCards = sourceColumn && sourceColumn.querySelector('.board-column-cards');
    var nextSibling = card.nextSibling;
    card.dataset.taskStatus = newStatus;
    targetCards.appendChild(card);
    updateColumnBadge(sourceColumn);
    updateColumnBadge(targetColumn);
    pushTaskStatusUpdate(card, newStatus).then(function(result) {
      if (result.ok) {
        fetchBoardTasksJson().then(function(tasks) {
          if (tasks) reorderBoardDomToTaskList(tasks);
        });
        return;
      }
      card.dataset.taskStatus = prevStatus;
      if (sourceCards) {
        if (nextSibling && nextSibling.parentNode === sourceCards) {
          sourceCards.insertBefore(card, nextSibling);
        } else {
          sourceCards.appendChild(card);
        }
      }
      updateColumnBadge(sourceColumn);
      updateColumnBadge(targetColumn);
      var st = result.status;
      var msg = (st === 401 || st === 403)
        ? 'Not authorized to update tasks (sign in again if needed). The card was moved back.'
        : 'Could not save the task move. The card was moved back.';
      showBoardError(msg);
    });
  }

  if (boardColumns) {
    boardColumns.addEventListener('dragstart', handleDragStart);
    boardColumns.addEventListener('dragend', handleDragEnd);
    boardColumns.addEventListener('click', handleCardClick);
    boardColumns.addEventListener('dragover', handleBoardDragOver, true);
    boardColumns.addEventListener('drop', handleBoardDrop, true);
  }
})();