{% load common_extras %} {% comment %} Step 2 — the audience (SPEC §13.1). The rule builder is templates/contacts/_filter_bar.html, included unchanged, and its Alpine component is the CRM's (defined once in compose.html's alpine_components block, so it exists before Alpine initialises anything this partial swaps in). That is the point of contract 8: a broadcast audience and a saved segment are the same document evaluated by the same engine, so a second builder here would be a second list of sources and operators that could disagree with the one the segment page uses. `can_manage_crm` is deliberately absent from this context, which is what keeps the filter bar's save/update/delete-segment controls out of the composer — managing segments is the CRM's job, not a side effect of drafting a broadcast. Two forms, one Alpine scope, because forms cannot nest and these do different things: the top one GETs a preview on every edit, the bottom one POSTs the document that gets stored. Both read the same `serialised`, so the count an operator agrees to is computed from the rules they are looking at. {% endcomment %}

Who receives this?

Pick a saved segment or build the rules. The count updates as you go, and nobody is messaged until the last step.

{% comment %} Option cards rather than a select (HANDOFF §3): the choice between a saved audience and your own rules is the whole of this step, so it is laid out rather than folded away. Real radios bound to `segment`, so the preview form above and the save form below read the same value. {% endcomment %}
Audience {% for option in filter_config.segments %} {% endfor %}
{% include "contacts/_filter_bar.html" %}
{% include "broadcasts/_audience_preview.html" %}

Opted-out contacts, and anyone the channel will not let you message, are left out automatically.

{% csrf_token %} {% include "broadcasts/_step_back.html" %}