diff --git a/docs/plans/listas-sem-subtitulo-prosa-impl.md b/docs/plans/listas-sem-subtitulo-prosa-impl.md
new file mode 100644
index 00000000..057daa15
--- /dev/null
+++ b/docs/plans/listas-sem-subtitulo-prosa-impl.md
@@ -0,0 +1,67 @@
+# Impl: Listas `/campanha` — subtítulos curtos (sem prosa; filtro salvo em Municípios)
+
+Status: aprovado
+Atualizado em: 2026-08-02
+Issue: #283
+Intenção: docs/plans/listas-sem-subtitulo-prosa.md
+Appetite restante: ~0,5 dia eng (herdado)
+
+## Leitura da intenção
+
+- **Outcome:** Header das listas citadas, Quadro e create/edit estáticos mostram só o título — sem parágrafo de prosa. Em `/campanha/municipios`, quando a URL casa com um filtro salvo (B18), o subtítulo do header passa a ser o **nome** do filtro; a label de resumo duplicada some da barra.
+- **O que NÃO negociar:** Organizações, Conceitos, Perfil, Contatos mantêm subtítulos atuais; chips/omnibox como editor de filtro ficam; leader lockdown intocado; não puxar serializador pesado de URL para o layout `(app)`.
+- **O que reavaliar:** A label de resumo (`formatMunicipalityActiveFiltersSummary`) ao lado da busca **já foi removida** no B127 (omnibox). O aceite de “sumir a label duplicada” está satisfeito — só garantir que não reintroduzimos resumo visível na barra.
+
+## Abordagem recomendada
+
+```mermaid
+flowchart LR
+ A[campaignPageChrome pathRules] -->|sectionOnly| B[Header título só]
+ C[MunicipalityListPageChrome] -->|SetCampaignPageChrome| D[Subtítulo = nome filtro salvo]
+ E[Edit pages] -->|remove subtitle override| B
+```
+
+**Opções consideradas:**
+- A) Apagar `subtitle` no catálogo e manter `pathRules` com `resolveCatalogEntry` — catálogo ainda carrega prosa morta.
+- B) **`pathRules` → `sectionOnly(title)`** para rotas no escopo; catálogo limpo nas entradas afetadas; metadata já usa só `title`.
+- C) `SetCampaignPageChrome` em cada rota create/edit — duplica o catálogo.
+
+**Recomendação:** B — o dono (`campaignPageChrome.ts`) já resolve chrome por pathname; overrides pontuais só onde o estado é client-side (filtro salvo) ou dinâmico (editar com nome da entidade).
+
+**Rejeitadas:** C (twins); A (prosa morta no catálogo).
+
+### Componentes / mudanças
+
+- **`campaignPageChrome.ts`**: `sectionOnly` nas listas citadas, Quadro, create/edit estáticos; remove prosa das entradas de catálogo afetadas; mantém subtítulos em org/conceitos/perfil/contatos.
+- **`MunicipalityListPageChrome.tsx`** (novo): client; `useMunicipalitySavedFilters` + `isSameListHref` (mesmo contrato da sidebar B18); `SetCampaignPageChrome` só quando há match.
+- **Edit pages** (`municipios/.../editar`, `atividades/.../editar`): chrome/metadata sem `subtitle`.
+- **Migration:** sem migration.
+- **Access / Consent:** nenhum.
+- **UI:** B — encaixe no chrome B123; sem redesign.
+
+### Dados → forma
+
+- Não há dados novos — só orientação espacial no header.
+
+## Fases verificáveis
+
+1. **Chrome catálogo + edit** — `campaignPageChrome.ts`, edit pages, testes unitários.
+2. **Filtro salvo** — `MunicipalityListPageChrome` na página de lista; teste unitário do match.
+3. **Gates** — `pnpm gate:fast`; push via `pnpm push`.
+
+## Rabbit holes / Não escopo (engenharia)
+
+- Reescrever subtítulos de Organizações/Conceitos/Perfil/Contatos.
+- Subtítulo para URL filtrada ad hoc (só filtro salvo casado).
+- Reintroduzir `formatMunicipalityActiveFiltersSummary` visível na barra.
+
+## Riscos e mitigação
+
+- **Acoplamento layout ↔ URL municípios:** `isSameListHref` já é client-safe e usado na sidebar — reusar, não importar `buildMunicipalityListHref` no layout.
+- **Regressão E2E filtros salvos:** sidebar + Renomear intactos; só chrome do header muda.
+
+## Aceite de engenharia
+
+- [x] Aceite de produto da intenção ainda coberto
+- [x] Invariantes AGENTS/engineering-standards
+- [x] Testes de domínio previstos (unit chrome + saved-filter match)
diff --git a/src/app/(campaign)/campanha/(app)/atividades/[slug]/editar/page.tsx b/src/app/(campaign)/campanha/(app)/atividades/[slug]/editar/page.tsx
index 447dea5a..2ce65db2 100644
--- a/src/app/(campaign)/campanha/(app)/atividades/[slug]/editar/page.tsx
+++ b/src/app/(campaign)/campanha/(app)/atividades/[slug]/editar/page.tsx
@@ -22,12 +22,9 @@ type EditActivityPageProps = {
params: Promise<{ slug: string }>
}
-const activityEditSubtitle = 'Atualize os detalhes da atividade sem alterar o título original.'
-
export async function generateMetadata({ params }: EditActivityPageProps) {
const { slug } = await params
- if (!slug)
- return campaignPageMetadata({ title: 'Editar atividade', subtitle: activityEditSubtitle })
+ if (!slug) return campaignPageMetadata({ title: 'Editar atividade' })
const [user, payload] = await Promise.all([
requireCampaignPageActor({ gate: 'staff', redirectTo: '/campanha/atividades' }),
@@ -36,9 +33,9 @@ export async function generateMetadata({ params }: EditActivityPageProps) {
try {
const view = await getActivityEditPageData(payload, user, slug)
- return campaignPageMetadata({ title: `Editar ${view.title}`, subtitle: activityEditSubtitle })
+ return campaignPageMetadata({ title: `Editar ${view.title}` })
} catch {
- return campaignPageMetadata({ title: 'Editar atividade', subtitle: activityEditSubtitle })
+ return campaignPageMetadata({ title: 'Editar atividade' })
}
}
@@ -63,9 +60,7 @@ export default async function EditActivityPage({ params }: EditActivityPageProps
return (
-
+
}
-const municipalityEditSubtitle =
- 'A geografia do município é pré-definida e não pode ser alterada. Aqui você edita metas, votos estimados, inteligência e tendência política.'
-
export async function generateMetadata({ params }: MunicipalityEditPageProps) {
const { slug } = await params
const payload = await getPayload({ config })
@@ -43,12 +40,9 @@ export async function generateMetadata({ params }: MunicipalityEditPageProps) {
try {
const context = await resolveAccessibleMunicipalityContext(payload, user, slug)
const view = await getMunicipalityDetailViewModel(payload, context, user)
- return campaignPageMetadata({
- title: `Editar ${view.name}`,
- subtitle: municipalityEditSubtitle,
- })
+ return campaignPageMetadata({ title: `Editar ${view.name}` })
} catch {
- return campaignPageMetadata({ title: 'Editar município', subtitle: municipalityEditSubtitle })
+ return campaignPageMetadata({ title: 'Editar município' })
}
}
@@ -76,9 +70,7 @@ export default async function MunicipalityEditPage({ params }: MunicipalityEditP
return (
-
+