{% comment %} The refreshable half of the tags page. The list page renders this inline; every mutation's toast_response carries a `tagsChanged` HX-Trigger, and this container answers it by re-fetching itself from `contacts:tag_rows` — a view that renders this template alone. Fetching the full page and picking one div out of it with hx-select also works, and costs a whole shell render (sidebar, workspace switcher, every context-processor query) per keystroke-sized edit. The root element's id, hx-get, hx-trigger and hx-swap="outerHTML" are that seam and must stay on it: this file is what replaces itself, so moving any of the four onto a child breaks every refresh silently — the toast still fires and the list simply never updates. Three forms per row became one named action and a "…". Renaming is what people come here for. Merging is the repair for two tags that mean the same thing — a data-quality problem the case-insensitive unique index cannot catch, because "VIP" and "Priority" are distinct strings and one idea — and it belongs behind the menu with the other twice-a-year action. {% endcomment %}
{% if tags %}
{% for tag in tags %}
{% include "partials/_nav_icon.html" with name="tag" icon_size=19 %}
{{ tag.name }}
On {{ tag.contact_count }} contact{{ tag.contact_count|pluralize }}
{% comment %} Full-width and ordered last, so an open editor drops onto its own line under the row rather than colliding with the action buttons. {% endcomment %}
{% endfor %}
{% else %} {% comment %} .btn-pill-secondary, not primary: the header already holds this screen's one primary action. It opens the same modal as the header's, by id. {% endcomment %}

No tags yet

A tag is how a flow says "this person asked about pricing", so a filter can find them again later.

{% endif %}