diff --git a/docs/plans/email-celular-lista-liderancas.md b/docs/plans/email-celular-lista-liderancas.md
index 51210ee0..f4657a48 100644
--- a/docs/plans/email-celular-lista-liderancas.md
+++ b/docs/plans/email-celular-lista-liderancas.md
@@ -9,6 +9,8 @@ Responsável: —
**Nota de revisão (2026-07-26):** entregue como especificado — `CampaignCopyableCell` nasceu compartilhado (`shared/`) já no 2º call site (`AdvisorsTable.tsx` migrado no mesmo PR), `whatsAppHrefForPhone` promovido a `lib/phone.ts`, `LeadershipRowViewModel.email` populado sem query nova, e `loadLeadershipDetail` deduplicado (reusa `row.email` de `toLeadershipRows` em vez de reparsear `doc.contact`). Ordem de colunas final: Nome → E-mail → Celular → Status → Municípios → Organizações → Acesso ao app → Ações (WhatsApp), exatamente como travado abaixo. Gate completo (tsc/lint/format/knip/cycles/test/build) verde; `pnpm exec knip` mantém o erro pré-existente ao carregar `payload.config.ts` (P3, não relacionado); `pnpm test:e2e` reproduziu apenas o flake pré-existente já documentado em `campaignMunicipalities.e2e.spec.ts` (checkbox de consentimento do `LeaderContactsPanel` antes da hidratação) — nenhuma falha nas rotas tocadas por este item.
+**Hotfix produção (2026-07-26 noite):** `/campanha/liderancas` 500 em prod — RSC não pode passar `formatDisplay` (função) para o Client Component `CampaignCopyableCell`. API trocada para `displayValue?: string` (formatação no caller); Vercel runtime error: "Functions cannot be passed directly to Client Components". Assessores (`AdvisorsTable`, já `'use client'`) não quebrava, mas foi alinhado.
+
## Design (Impeccable)
Âncoras: `PRODUCT.md` (princípios 2 clareza sob pressão, 8 Feel the action; anti spreadsheet) / `DESIGN.md` (register `product`; Field Desk) · tema `data-theme='campaign'` · precedente de interação [`AdvisorsTable.tsx`](../../src/components/campaign/advisor/AdvisorsTable.tsx) (B19 ✓) · shells `CampaignTable` / `CampaignPageShell`.
diff --git a/src/app/(campaign)/campanha/(app)/liderancas/page.tsx b/src/app/(campaign)/campanha/(app)/liderancas/page.tsx
index b4036dd0..55e0083f 100644
--- a/src/app/(campaign)/campanha/(app)/liderancas/page.tsx
+++ b/src/app/(campaign)/campanha/(app)/liderancas/page.tsx
@@ -71,7 +71,7 @@ const leadershipColumns = (
),
diff --git a/src/components/campaign/advisor/AdvisorsTable.tsx b/src/components/campaign/advisor/AdvisorsTable.tsx
index f532cfbb..154a185c 100644
--- a/src/components/campaign/advisor/AdvisorsTable.tsx
+++ b/src/components/campaign/advisor/AdvisorsTable.tsx
@@ -357,7 +357,9 @@ export const AdvisorsTable = ({
)}
diff --git a/src/components/campaign/shared/CampaignCopyableCell.tsx b/src/components/campaign/shared/CampaignCopyableCell.tsx
index 9553f787..70d7b3df 100644
--- a/src/components/campaign/shared/CampaignCopyableCell.tsx
+++ b/src/components/campaign/shared/CampaignCopyableCell.tsx
@@ -22,8 +22,12 @@ type CampaignCopyableCellProps = {
value: string | null
/** Used in the toast ("`label` copiado.") and the button's `aria-label`. */
label: string
- /** Transforms `value` for display only — the clipboard still gets the raw value (e.g. phone masking). */
- formatDisplay?: (value: string) => string
+ /**
+ * Preformatted label (e.g. masked phone). Clipboard still gets raw `value`.
+ * String, not a formatter — Client Component; RSC cannot pass functions
+ * (broke `/campanha/liderancas` after B28).
+ */
+ displayValue?: string
emptyDisplay?: string
className?: string
}
@@ -37,7 +41,7 @@ type CampaignCopyableCellProps = {
export const CampaignCopyableCell = ({
value,
label,
- formatDisplay,
+ displayValue,
emptyDisplay = '—',
className,
}: CampaignCopyableCellProps) => {
@@ -49,8 +53,6 @@ export const CampaignCopyableCell = ({
)
}
- const displayValue = formatDisplay ? formatDisplay(value) : value
-
return (
)
}