{% comment %} The thread's identity line and its two conversation controls. Its own partial with its own endpoint because it holds *state*, and state goes stale: "Mark done" posts and gets a 204 back, so without a refresh the button kept its old label and its old hidden value, and the only transition an agent could make was the one they had just made. inboxThreadChanged already told the body and the panel; this listens to the same event. Not folded into the polled body instead, which would have been one fewer request: the assignee dressed as the design's quiet "Unassigned ▾" button, so the keyboard and screen readers get a native control. {% endcomment %}
{% csrf_token %}
{% csrf_token %} {% if conversation.state == "done" %} {% else %} {% endif %}
{% else %} Read only {% endif %} {% comment %} Shows and hides the contact panel. `info` and `toggleInfo` live on the page's own x-data (inbox/list.html), so the choice survives this header being re-fetched and a different conversation being opened. {% endcomment %}