mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
docs(S36,C220,S37,S38,S39): planos + designs hi-fi — Central de Conteúdos (logo, link do Instagram, lideranças, cards e seção na home)
This commit is contained in:
parent
d0823043ed
commit
d976aa8530
10 changed files with 929 additions and 0 deletions
|
|
@ -0,0 +1,94 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR" data-theme="campaign-site">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<title>Design — S35 · Cards misturados ao catálogo</title>
|
||||
<style type="text/tailwindcss">
|
||||
@theme { --font-sans: Arimo, Arial, sans-serif; }
|
||||
:root { --red:#a21c1c;--kit:#e4102f;--blue:#184e92;--yellow:#ffe607;--cream:#fff8f2;--muted:#6c615e;--line:rgb(0 0 0/.12);--display:'Exo 2','Arial Black',sans-serif; }
|
||||
*{box-sizing:border-box}.display{font-family:var(--display)}
|
||||
.board{background:#e7e3e0;background-image:radial-gradient(rgb(24 78 146/.09) .7px,transparent .7px);background-size:18px 18px}
|
||||
.frame{box-shadow:0 22px 60px rgb(39 25 22/.13)}.desktop{width:1280px}.phone{width:390px;border-radius:28px}.scene:after{content:'';height:1px;flex:1;background:#cfc9c5}
|
||||
.field{min-height:44px;border:1px solid rgb(0 0 0/.18);border-radius:10px;background:#fff;padding:10px 13px;font-size:15px}
|
||||
.chip{display:inline-flex;min-height:36px;align-items:center;gap:6px;border:1px solid var(--line);border-radius:999px;background:#fff;padding:6px 11px;font-size:12px;font-weight:700}.active{border-color:rgb(24 78 146/.35);background:#eef4fb;color:#184e92}
|
||||
.card{overflow:hidden;border:1px solid var(--line);border-radius:14px;background:#fff;box-shadow:0 8px 24px rgb(71 19 14/.07)}
|
||||
.tag{display:inline-flex;min-height:23px;align-items:center;border-radius:999px;background:#eef4fb;padding:4px 8px;color:#184e92;font-size:11px;font-weight:800}
|
||||
.alias{display:inline-flex;border:1px solid rgb(0 0 0/.1);border-radius:999px;background:#fff;padding:3px 7px;color:#6c615e;font-size:10px;font-weight:700}
|
||||
.btn{display:inline-flex;min-height:44px;align-items:center;justify-content:center;border-radius:10px;border:1.5px solid rgb(162 28 28/.28);background:#fff;padding:9px 13px;color:#a21c1c;font-size:13px;font-weight:800}
|
||||
.art{position:relative;display:grid;place-items:center;overflow:hidden;background:linear-gradient(145deg,#184e92,#0876ac);color:#fff}.art:before{content:'1313';position:absolute;font-family:var(--display);font-size:66px;font-weight:900;color:rgb(255 255 255/.08);transform:rotate(-8deg)}.art-red{background:linear-gradient(145deg,#e4102f,#a21c1c)}.art-light{background:linear-gradient(145deg,#eee9e5,#fff)}
|
||||
.piece-art{display:grid;place-items:center;background:linear-gradient(135deg,#e5e2df,#f7f5f3);color:#6c615e;text-align:center;font-size:10px;font-weight:800;letter-spacing:.04em}
|
||||
</style>
|
||||
</head>
|
||||
<body class="board min-h-screen text-black antialiased">
|
||||
<main class="mx-auto max-w-[1480px] space-y-14 px-4 py-12 md:px-8">
|
||||
<header class="max-w-3xl">
|
||||
<span class="rounded-full bg-[#e4102f] px-3 py-1 text-xs font-bold text-white">S35 · revisão do gate</span>
|
||||
<h1 class="display mt-4 text-4xl font-black">Cards e peças vivem no mesmo board.</h1>
|
||||
<p class="mt-2 text-sm leading-6 text-[#6c615e]">Cada modelo é um item individual na ordem normal do catálogo. Não existe faixa, cabeçalho ou agrupamento próprio para cards.</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 01</span><h2>Board padrão · desktop 1280 · peças e modelos misturados</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white">
|
||||
<header class="flex h-16 items-center justify-between bg-[#ae1603] px-10"><div class="h-9 w-44 rounded bg-white/20"></div><b class="text-sm text-white">Central de Conteúdos</b></header>
|
||||
<div class="mx-auto max-w-6xl px-10 py-10">
|
||||
<div class="rounded-xl bg-[#fff8f2] p-4"><div class="field text-[#6c615e]">Encontre uma peça por assunto, cidade ou tema…</div><div class="mt-3 flex gap-2"><span class="chip">Tipo⌄</span><span class="chip">Cidade⌄</span><span class="chip">Região⌄</span><span class="chip">Tema⌄</span><span class="chip">Instituição⌄</span></div></div>
|
||||
<div class="mt-8"><h2 class="display text-2xl font-black">Escolha, compartilhe e peça voto</h2><p class="mt-1 text-sm text-[#6c615e]">Uma lista só: peças oficiais e convites para criar seu card.</p></div>
|
||||
<div class="mt-5 grid grid-cols-3 gap-6">
|
||||
<article class="card"><div class="piece-art relative aspect-video"><span>NEEDS ASSET · POSTER REAL</span><span class="absolute grid size-12 place-items-center rounded-full bg-[#ffe607] text-xl text-black shadow">▶</span></div><div class="p-4"><span class="tag">Vídeo</span><h3 class="mt-2 font-extrabold">Título da peça publicada</h3><p class="mt-1 text-xs text-[#6c615e]">Tema · Cidade</p><div class="mt-4 grid grid-cols-2 gap-2"><span class="btn">Baixar</span><span class="btn">Compartilhar</span></div></div></article>
|
||||
<article class="card"><div class="art aspect-video"><b class="relative display text-2xl">#SOU ____</b></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Card com seu nome</h3><p class="mt-1 text-xs leading-5 text-[#6c615e]">Coloque seu nome no card oficial.</p><div class="mt-2 flex gap-1"><span class="alias">nome</span></div><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card"><div class="piece-art aspect-video">NEEDS ASSET · FOTO REAL</div><div class="p-4"><span class="tag">Foto</span><h3 class="mt-2 font-extrabold">Outra peça publicada</h3><p class="mt-1 text-xs text-[#6c615e]">Tema da peça</p><div class="mt-4 grid grid-cols-2 gap-2"><span class="btn">Baixar</span><span class="btn">Compartilhar</span></div></div></article>
|
||||
<article class="card"><div class="art aspect-video"><div class="relative text-center"><b class="display block bg-[#e4102f] px-4 py-1 text-lg text-[#ffeb00]">TIME DE</b><b class="display mt-1 block bg-[#0061a5] px-4 py-1 text-2xl">VOCÊ</b></div><span class="absolute right-2 bottom-2 text-[9px] font-black">PLACEHOLDER · ARTE EXISTENTE</span></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Time de você</h3><p class="mt-1 text-xs text-[#6c615e]">Entre para o time com sua foto.</p><div class="mt-2 flex gap-1"><span class="alias">santinho</span></div><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card"><div class="piece-art relative aspect-video"><span>NEEDS ASSET · CAPA REAL</span><span class="absolute grid size-12 place-items-center rounded-full bg-[#ffe607] text-xl text-black shadow">▶</span></div><div class="p-4"><span class="tag">Áudio</span><h3 class="mt-2 font-extrabold">Mensagem para compartilhar</h3><p class="mt-1 text-xs text-[#6c615e]">Campanha</p><div class="mt-4 grid grid-cols-2 gap-2"><span class="btn">Baixar</span><span class="btn">Compartilhar</span></div></div></article>
|
||||
<article class="card border-2 border-[#e4102f]"><div class="art art-red aspect-video"><span class="absolute top-2 right-2 rounded-full bg-white px-2 py-1 text-[9px] font-black text-[#184e92]">NOVO</span><b class="relative display text-xl text-[#ffeb00]">MINHA COLINHA</b><span class="absolute right-2 bottom-2 text-[9px] font-black">PLACEHOLDER · ARTE EXISTENTE</span></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Minha colinha</h3><p class="mt-1 text-xs text-[#6c615e]">Monte sua cola de votação.</p><div class="mt-2 flex gap-1"><span class="alias">santinho</span><span class="alias">colinha</span></div><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
</div>
|
||||
<div class="mt-7 rounded-xl border border-[#184e92]/20 bg-[#eef4fb] p-4 text-sm leading-6 text-[#184e92]"><b>Regra do gate:</b> a ordem acima mistura itens por relevância/ordem do catálogo. “Card” é apenas o tipo do item — nunca um cabeçalho ou uma seção dentro do board.</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 02</span><h2>Mobile 390 · board misto e Tipo “Card” ativo</h2></div>
|
||||
<div class="flex flex-wrap justify-center gap-8"><div class="phone frame min-h-[960px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between bg-[#ae1603] px-4"><div class="h-7 w-32 rounded bg-white/20"></div><span class="text-white">☰</span></header><div class="p-4"><div class="field text-sm text-[#6c615e]">Busque uma peça ou card…</div><div class="mt-3 flex gap-2 overflow-hidden"><span class="chip shrink-0">Tipo⌄</span><span class="chip shrink-0">Cidade⌄</span><span class="chip shrink-0">Tema⌄</span></div><h2 class="display mt-6 text-2xl font-black">Escolha, compartilhe e peça voto</h2><div class="mt-4 space-y-4">
|
||||
<article class="card grid grid-cols-[128px_1fr]"><div class="piece-art min-h-40">NEEDS ASSET<br/>POSTER REAL</div><div class="p-4"><span class="tag">Vídeo</span><h3 class="mt-2 text-sm font-extrabold">Título da peça publicada</h3><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article>
|
||||
<article class="card grid grid-cols-[128px_1fr]"><div class="art min-h-40"><b class="relative display text-xl">#SOU</b></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 text-sm font-extrabold">Card com seu nome</h3><span class="alias mt-2">nome</span><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Escolher →</a></div></article>
|
||||
<article class="card grid grid-cols-[128px_1fr]"><div class="piece-art min-h-40">NEEDS ASSET<br/>FOTO REAL</div><div class="p-4"><span class="tag">Foto</span><h3 class="mt-2 text-sm font-extrabold">Outra peça publicada</h3><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article>
|
||||
<article class="card grid grid-cols-[128px_1fr]"><div class="art art-red min-h-40"><b class="relative display text-center text-lg text-[#ffeb00]">MINHA<br/>COLINHA</b></div><div class="p-4"><span class="tag">Card · NOVO</span><h3 class="mt-2 text-sm font-extrabold">Minha colinha</h3><div class="mt-2 flex gap-1"><span class="alias">santinho</span><span class="alias">colinha</span></div><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Escolher →</a></div></article>
|
||||
</div><p class="mt-5 text-center text-[11px] leading-4 text-[#6c615e]">Sem divisor “Cards”. A alternância peça → card → peça é intencional.</p></div></div>
|
||||
<div class="phone frame min-h-[960px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between bg-[#ae1603] px-4"><div class="h-7 w-32 rounded bg-white/20"></div><span class="text-white">☰</span></header><div class="p-4"><div class="field text-sm text-[#6c615e]">Busque um card…</div><div class="mt-3 flex gap-2 overflow-hidden"><span class="chip active shrink-0">Tipo · Card ×</span><span class="chip shrink-0">Tema⌄</span></div><h2 class="display mt-6 text-2xl font-black">Escolha, compartilhe e peça voto</h2><p class="mt-1 text-xs text-[#6c615e]">6 itens com o filtro aplicado.</p><div class="mt-4 space-y-3">
|
||||
<article class="card grid grid-cols-[96px_1fr]"><div class="art min-h-28"><b class="relative display">#SOU</b></div><div class="p-3"><span class="tag">Card</span><h3 class="mt-1 text-sm font-extrabold">Card com seu nome</h3><span class="alias mt-1">nome</span></div></article>
|
||||
<article class="card grid grid-cols-[96px_1fr]"><div class="art art-light min-h-28"><span class="relative text-2xl text-[#a21c1c]">◎</span></div><div class="p-3"><span class="tag">Card</span><h3 class="mt-1 text-sm font-extrabold">Moldura quadrada</h3><span class="alias mt-1">foto de perfil</span></div></article>
|
||||
<article class="card grid grid-cols-[96px_1fr]"><div class="art art-light min-h-28"><span class="relative text-2xl text-[#a21c1c]">▯</span></div><div class="p-3"><span class="tag">Card</span><h3 class="mt-1 text-sm font-extrabold">Moldura vertical</h3><span class="alias mt-1">foto de perfil</span></div></article>
|
||||
<article class="card grid grid-cols-[96px_1fr]"><div class="art min-h-28"><b class="relative display text-center text-xs">TIME DE<br/>VOCÊ</b></div><div class="p-3"><span class="tag">Card</span><h3 class="mt-1 text-sm font-extrabold">Time de você</h3><span class="alias mt-1">santinho</span></div></article>
|
||||
<article class="card grid grid-cols-[96px_1fr]"><div class="art art-red min-h-28"><b class="relative display text-center text-xs text-[#ffeb00]">TIME DO<br/>ESTADUAL</b></div><div class="p-3"><span class="tag">Card</span><h3 class="mt-1 text-sm font-extrabold">Time do estadual</h3><span class="alias mt-1">estadual</span></div></article>
|
||||
<article class="card grid grid-cols-[96px_1fr] border-2 border-[#e4102f]"><div class="art art-red min-h-28"><b class="relative display text-center text-xs text-[#ffeb00]">MINHA<br/>COLINHA</b></div><div class="p-3"><span class="tag">Card · NOVO</span><h3 class="mt-1 text-sm font-extrabold">Minha colinha</h3><div class="mt-1 flex gap-1"><span class="alias">santinho</span><span class="alias">colinha</span></div></div></article>
|
||||
</div></div></div></div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 03</span><h2>Tipo “Card” ativo · os 6 modelos, sem cabeçalho próprio</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white"><header class="flex h-16 items-center justify-between bg-[#ae1603] px-10"><div class="h-9 w-44 rounded bg-white/20"></div><b class="text-sm text-white">Central de Conteúdos</b></header><div class="mx-auto max-w-6xl px-10 py-10"><div class="rounded-xl bg-[#fff8f2] p-4"><div class="field text-[#6c615e]">Encontre uma peça por assunto, cidade ou tema…</div><div class="mt-3 flex gap-2"><span class="chip active">Tipo · Card ×</span><span class="chip">Cidade⌄</span><span class="chip">Região⌄</span><span class="chip">Tema⌄</span><span class="chip">Instituição⌄</span></div></div><div class="mt-8 flex items-end justify-between"><div><h2 class="display text-2xl font-black">Escolha, compartilhe e peça voto</h2><p class="mt-1 text-sm text-[#6c615e]">Resultados do filtro aplicado.</p></div><span class="text-xs text-[#6c615e]">6 itens</span></div>
|
||||
<div class="mt-5 grid grid-cols-3 gap-6">
|
||||
<article class="card"><div class="art aspect-video"><b class="relative display text-2xl">#SOU ____</b></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Card com seu nome</h3><p class="mt-1 text-xs text-[#6c615e]">Coloque seu nome no card oficial.</p><span class="alias mt-2">nome</span><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card"><div class="art art-light aspect-video"><div class="relative grid size-20 place-items-center rounded-full border-2 border-dashed border-[#a21c1c]/40 text-3xl text-[#a21c1c]">◎</div></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Moldura quadrada</h3><p class="mt-1 text-xs text-[#6c615e]">Foto de perfil quadrada.</p><span class="alias mt-2">foto de perfil</span><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card"><div class="art art-light aspect-video"><div class="relative grid h-24 w-16 place-items-center rounded-lg border-2 border-dashed border-[#a21c1c]/40 text-3xl text-[#a21c1c]">◎</div></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Moldura vertical</h3><p class="mt-1 text-xs text-[#6c615e]">Foto vertical para stories.</p><span class="alias mt-2">foto de perfil</span><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card"><div class="art aspect-video"><b class="relative display text-xl">TIME DE VOCÊ</b></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Time de você</h3><p class="mt-1 text-xs text-[#6c615e]">Entre para o time com sua foto.</p><span class="alias mt-2">santinho</span><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card"><div class="art art-red aspect-video"><b class="relative display text-xl text-[#ffeb00]">TIME DO ESTADUAL</b></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Time do estadual</h3><p class="mt-1 text-xs text-[#6c615e]">Escolha o estadual e personalize.</p><span class="alias mt-2">estadual</span><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
<article class="card border-2 border-[#e4102f]"><div class="art art-red aspect-video"><span class="absolute top-2 right-2 rounded-full bg-white px-2 py-1 text-[9px] font-black text-[#184e92]">NOVO</span><b class="relative display text-xl text-[#ffeb00]">MINHA COLINHA</b></div><div class="p-4"><span class="tag">Card</span><h3 class="mt-2 font-extrabold">Minha colinha</h3><p class="mt-1 text-xs text-[#6c615e]">Monte sua cola de votação.</p><div class="mt-2 flex gap-1"><span class="alias">santinho</span><span class="alias">colinha</span></div><a class="btn mt-4 w-full">Escolher este modelo →</a></div></article>
|
||||
</div>
|
||||
</div></div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENAS 04–05</span><h2>Busca por apelido · “santinho” e “foto de perfil”</h2></div>
|
||||
<div class="grid gap-8 lg:grid-cols-2">
|
||||
<div class="frame rounded-xl bg-white p-7"><div class="field flex justify-between"><span>santinho</span><b class="text-[#6c615e]">×</b></div><div class="mt-3"><span class="chip active">Busca · “santinho” ×</span></div><h3 class="display mt-7 text-xl font-black">2 itens encontrados</h3><div class="mt-4 grid grid-cols-2 gap-4"><article class="card"><div class="art aspect-video"><b class="relative display text-xl">TIME DE VOCÊ</b></div><div class="p-4"><span class="tag">Card</span><h4 class="mt-2 font-extrabold">Time de você</h4><span class="alias mt-2">santinho</span></div></article><article class="card"><div class="art art-red aspect-video"><b class="relative display text-xl text-[#ffeb00]">MINHA COLINHA</b></div><div class="p-4"><span class="tag">Card</span><h4 class="mt-2 font-extrabold">Minha colinha</h4><div class="mt-2 flex gap-1"><span class="alias">santinho</span><span class="alias">colinha</span></div></div></article></div></div>
|
||||
<div class="frame rounded-xl bg-white p-7"><div class="field flex justify-between"><span>foto de perfil</span><b class="text-[#6c615e]">×</b></div><div class="mt-3"><span class="chip active">Busca · “foto de perfil” ×</span></div><h3 class="display mt-7 text-xl font-black">2 itens encontrados</h3><div class="mt-4 grid grid-cols-2 gap-4"><article class="card"><div class="art art-light aspect-video"><div class="relative grid size-16 place-items-center rounded-full border-2 border-dashed border-[#a21c1c]/40 text-[#a21c1c]">◎</div></div><div class="p-4"><span class="tag">Card</span><h4 class="mt-2 font-extrabold">Moldura quadrada</h4><span class="alias mt-2">foto de perfil</span></div></article><article class="card"><div class="art art-light aspect-video"><div class="relative grid h-20 w-12 place-items-center rounded border-2 border-dashed border-[#a21c1c]/40 text-[#a21c1c]">◎</div></div><div class="p-4"><span class="tag">Card</span><h4 class="mt-2 font-extrabold">Moldura vertical</h4><span class="alias mt-2">foto de perfil</span></div></article></div></div>
|
||||
</div>
|
||||
<div class="mt-7 grid gap-4 md:grid-cols-2"><div class="rounded-xl border border-[#184e92]/20 bg-[#eef4fb] p-4 text-sm leading-6 text-[#184e92]"><b>Faceta geográfica ativa:</b> os seis modelos somem, pois não são territoriais. Uma peça publicada de tipo Card continua seguindo a regra normal das peças.</div><div class="rounded-xl border border-dashed bg-white p-4 text-sm leading-6 text-[#6c615e]"><b class="text-black">Sem convite duplicado:</b> o antigo tile “Card personalizado” foi removido. O estúdio segue acessível por cada modelo e pelo estado vazio já existente.</div></div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
116
docs/plans/central-conteudos-cards-no-catalogo.md
Normal file
116
docs/plans/central-conteudos-cards-no-catalogo.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# S35 — Central de Conteúdos — cards personalizáveis como itens do catálogo
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-23
|
||||
Issue: #1304
|
||||
Priority: P1
|
||||
Impeccable: B — encaixe no catálogo existente (novos itens + busca/filtros), sem rota nova
|
||||
Design UI: docs/plans/central-conteudos-cards-no-catalogo-ui-design.html
|
||||
Appetite: ~1–1,5 dia eng; um outcome verificável (cada card encontrável por nome, busca e filtro no catálogo)
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
Hoje os cards personalizáveis aparecem em `/conteudos` como **um único convite genérico** ("Faça seu card com Solla 1313"), que só é exibido quando nenhum filtro está ativo e não revela quais modelos existem. Quem procura um card pelo nome popular não acha nada, e quem não conhece a galeria nem sabe que há seis opções. O dono pediu literalmente: buscar **"santinho"** deve trazer os cards **"Time de você"** e **"colinha"**; buscar **"foto de perfil"** deve trazer os cards de foto de perfil. Cada modelo deve ser um item próprio do catálogo — **junto dos demais itens, sem seção separada** —, encontrável pelo próprio nome, por apelido e pelo filtro Tipo "Card", levando ao estúdio já com o modelo escolhido.
|
||||
|
||||
Isso revoga explicitamente a decisão D6 do S27 (`docs/plans/central-conteudos-publica-impl.md:81-85`), que rejeitou a entrada catalogada e fixou o tile único — o tile morre, substituído pelos itens individuais. Card continua **não sendo peça**: sem linha no banco, sem arquivo, sem publicação/kill switch próprio; o estúdio `/cards` segue o único lugar que gera o card, no aparelho do visitante.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** eleitor/simpatizante no celular, chegando por busca ou link do WhatsApp; conhece os cards pelos apelidos ("santinho", "foto de perfil", "colinha"), não pelos nomes oficiais dos modelos.
|
||||
- **Job principal:** achar o card que ele quer pelo nome que ele usa e cair no estúdio com o modelo já escolhido, sem varrer a galeria inteira.
|
||||
- **Fluxo desejado:** abre `/conteudos` → busca "santinho" (ou "foto de perfil") ou filtra Tipo "Card" → vê cada modelo como item próprio, com nome, explicação curta e arte → toca no item → chega em `/cards?model=<id>` com o modelo selecionado → faz e baixa o card no aparelho → o catálogo segue igual (nada do card fica lá).
|
||||
- **Anti-goals de produto:** não transforma card em peça (arquivo, publicação, kill switch); não cria rota, galeria ou segundo estúdio; não move a geração para o servidor/catálogo; não captura dado novo (a foto continua 100% no aparelho); não vira SEO de palavras-chave nem página própria por card.
|
||||
|
||||
### Esboço de fluxo (B)
|
||||
|
||||
```text
|
||||
[eleitor no celular] → /conteudos
|
||||
→ busca "santinho" · "foto de perfil" · "colinha" · "estadual" ou Tipo "Card"
|
||||
→ cada modelo de card aparece como item próprio, misturado às peças (sem seção separada)
|
||||
→ toca no item → /cards?model=<id> (modelo já escolhido no estúdio)
|
||||
→ faz/baixa o card no aparelho (nada do card fica no catálogo)
|
||||
→ volta ao catálogo: peças e cards juntos, sem convite duplicado
|
||||
[filtro geográfico ativo (Cidade/Região/Instituição)] → cards somem (não são territoriais)
|
||||
[sem JS] → a busca por querystring continua achando os itens do mesmo jeito
|
||||
```
|
||||
|
||||
### Design UI (B)
|
||||
|
||||
- Design UI (gate): `docs/plans/central-conteudos-cards-no-catalogo-ui-design.html` (+ assets em `central-conteudos-cards-no-catalogo-ui-design-assets/`) — itens de card **misturados ao board existente, sem seção/agrupamento próprio** (arte, nome, mini-descrição/apelido, caminho para o estúdio), o estado do filtro Tipo "Card" e o resultado das buscas por apelido. (Revisão do gate: a primeira versão agrupava os cards numa seção própria; o gate cortou a seção.)
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- Cada um dos 6 modelos é um item próprio do catálogo, **na mesma lista dos outros conteúdos, sem seção separada**, encontrável pelo nome do modelo e pelos apelidos: "santinho" traz "Time de você" e "Minha colinha"; "foto de perfil" traz "Moldura quadrada" e "Moldura vertical"; "colinha" traz "Minha colinha"; "estadual" traz "Time do estadual".
|
||||
- O filtro Tipo "Card" traz os itens de card; a busca por termo e os filtros funcionam sem JS (querystring), como no catálogo atual.
|
||||
- Cada item leva ao estúdio com o modelo já escolhido (`/cards?model=<id>`); o estúdio segue alcançável pelo estado vazio.
|
||||
- Guardrail — card não é peça: sem linha no banco, sem mídia, sem publicação/kill switch próprio; o item é um convite ao estúdio, nunca um arquivo para baixar/compartilhar.
|
||||
- Guardrail — o tile único ("Card personalizado") deixa de existir; nada de convite duplicado.
|
||||
- Guardrail — **sem seção/agrupamento separado de cards**: eles aparecem misturados aos demais itens do catálogo, sob a mesma busca e os mesmos filtros; nenhum cabeçalho/faixa própria de cards.
|
||||
- Guardrail — cards não respondem a faceta geográfica (Cidade/Região/Instituição): com faceta ativa, somem do resultado (não são territoriais).
|
||||
- Guardrail — catálogo sem peça publicada mantém o estado honesto atual (com o caminho para o estúdio), sem inventar um board vazio de cards.
|
||||
- Guardrail — nada muda no estúdio: foto/recorte 100% no aparelho, sem PII e sem `Consent` novo; o clique no item pode alimentar o mecanismo anônimo do C213/S32 como abertura de card, nunca como peça.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — o item não exibe número/contador; só roteia o visitante ao estúdio. A contagem de uso continua no mecanismo anônimo do C213/S32 (assunto card), sem métrica nova.
|
||||
- **Decisões desbloqueadas:** o eleitor escolhe o modelo sem varrer a galeria; a comunicação passa a poder ler quais modelos são procurados no catálogo, se a questão (c) for aceita (leitura pelo mecanismo existente).
|
||||
- **Forma:** *adiada ao plano de implementação* — nenhuma tabela/gráfico; quando muito, o evento anônimo já existente.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- Modelos (id → rótulo atual, fonte única `src/lib/cardModels.ts:65-135`): `eu-sou-solla` → "Card com seu nome"; `perfil-quadrado` → "Moldura quadrada"; `perfil-retangular` → "Moldura vertical"; `time-de-voce` → "Time de você"; `time-do-estadual` → "Time do estadual" (S30, escolha entre 53 estaduais); `minha-colinha` → "Minha colinha" (S31, selo `NOVO`, escolha de estadual).
|
||||
- Apelidos de busca por modelo (proposta verbatim): "santinho" → `time-de-voce` + `minha-colinha`; "foto de perfil" → `perfil-quadrado` + `perfil-retangular`; "colinha" → `minha-colinha`; "estadual" → `time-do-estadual`; o próprio nome de cada modelo sempre vale.
|
||||
- URL de destino: `/cards?model=<id>` — o estúdio já valida o id e pré-seleciona o modelo (`src/app/(frontend)/(home)/cards/page.tsx:20-27`).
|
||||
- Filtro de Tipo: valor existente `card`, rótulo `Card` (`src/lib/contentPiece.ts:24-34`); peça publicada de tipo card continua peça comum, com o comportamento atual.
|
||||
- Supersessão explícita: a decisão D6 do S27 (`docs/plans/central-conteudos-publica-impl.md:81-85`) fica revogada na parte do tile único; valem os itens individuais por modelo, sem peça catalogada e sem linha no banco.
|
||||
- Regra de apresentação (decisão do gate): os itens de card aparecem **junto dos demais itens da Central, sem seção separada** — não existe cabeçalho/faixa própria de cards.
|
||||
- Analytics (se a questão (c) for aceita): o clique no item conta pelo mecanismo único do C213/S32 como abertura de card — `subjectType: 'card'`, `subjectId = model.id` (`src/app/(frontend)/api/content-events/route.ts:95-114`) — nunca como peça; sem segundo analytics.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/lib/cardModels.ts` (os 6 modelos/rótulos), `src/components/conteudos/` (`ContentPieceCatalog.tsx`, hoje `ContentPieceCardInvite.tsx`), `src/lib/contentPieceCatalog.ts` (itens/facetas/filtro/busca), `src/components/conteudos/ContentPieceFilters.tsx` e `src/app/(frontend)/conteudos/(catalog)/page.tsx` (o `showCardInvite` atual), o deep-link `src/app/(frontend)/(home)/cards/page.tsx` e, se (c) valer, `src/lib/contentEvents.ts` + `src/app/(frontend)/api/content-events/route.ts`.
|
||||
- **Precedente a olhar:** D6 no `central-conteudos-publica-impl.md:81-85` (o que este item revoga) e `ContentPieceCardInvite.tsx:16-44` (o tile que morre); S30/S31 (modelos/pickers) e S32 (`docs/changelog/2026-09-23-s32.md` — `subjectType: 'card'`, `subjectId = model.id`); S28 (facetas + busca por `searchText`).
|
||||
- **Risco de acoplamento:** itens sintéticos — nada de collection/migration/kill switch; a lista de modelos/labels é fonte única (não duplicar copy); a busca sem JS é contrato do catálogo; #1277 (`docs/plans/escala-dry-pos-s30.md`) mexe em `src/components/cards/` — sem conflito esperado com o catálogo público, mas serializar se rodar em paralelo.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma dura — catálogo (S27/S28) e os 6 modelos (S13–S16, S30, S31) já estão no repo.
|
||||
- **Suave:** C213/S32, se a questão (c) for aceita (reusa o mecanismo existente, sem nada novo).
|
||||
- Design UI aprovado no gate.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Card virar peça (linha, arquivo, publicação, kill switch) ou ganhar página/detalhe/OG próprios.
|
||||
- Rota nova, segunda galeria, alterar o estúdio `/cards` ou o funil de geração (foto/canvas seguem no aparelho).
|
||||
- Copy editável pelo CMS; busca semântica/tema aplicada a cards além do decidido; facetas próprias de card.
|
||||
- Analytics novo (o mecanismo é o do C213/S32).
|
||||
- Redesenho da Central/shell/nav; mudar a regra das peças publicadas (tipo card continua peça comum).
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Já que virou item, vira peça".** Se alguém "só completar": collection, migration, mídia, publicação e kill switch para cards — dono duplicado do catálogo. **Corte neste item:** item sintético, sem linha; o estúdio é o dono.
|
||||
- **"Baixar o card direto do catálogo".** Se alguém "só completar": geração no catálogo/servidor e a foto sai do aparelho. **Corte neste item:** o item só leva a `/cards`; o card nasce no aparelho.
|
||||
- **"Um SEO por card".** Se alguém "só completar": página, título e palavras-chave por modelo, virando segundo catálogo. **Corte neste item:** itens do board + apelidos decididos; sem rota nova.
|
||||
- **"Card com tema/cidade para combinar com os filtros".** Se alguém "só completar": metadados territoriais/editoriais por card, um segundo modelo de conteúdo. **Corte neste item:** cards fora das facetas geográficas; tema só se um dia declarado (v1: nenhum).
|
||||
- **"Contar quem fez o card".** Se alguém "só completar": identificar visitante para medir conversão do item. **Corte neste item:** só o evento anônimo existente, se (c) aceita.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Como os cards se comportam sob faceta geográfica e temas?** **Opções:** A) ignoram facetas e ficam visíveis | B) excluídos quando faceta geográfica ativa | C) ganham temas próprios declarados. **Recomendação:** B — cards não são territoriais; tema só se declarado por modelo (v1 não declara). _(assumido — validar com produto)_
|
||||
- **O tile único "Card personalizado" fica como "ver todos os cards"?** **Opções:** A) fica como entrada geral | B) morre e é substituído pelos itens individuais, com o estúdio alcançável por cada item e pelo estado vazio. **Recomendação:** B — evita convite duplicado e é o pedido do operador. _(assumido — validar com produto)_
|
||||
- **O clique no item conta abertura de card ou de peça?** **Opções:** A) abertura de card (`subjectType: 'card'`, `subjectId = model`) pelo mecanismo do C213/S32 | B) abertura de peça | C) não conta. **Recomendação:** A — mede o interesse real no modelo sem duplicar como peça. _(assumido — validar com produto)_
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue — a registrar (`pnpm agent:register`).
|
||||
- Design UI (gate): `docs/plans/central-conteudos-cards-no-catalogo-ui-design.html` (+ assets em `central-conteudos-cards-no-catalogo-ui-design-assets/`)
|
||||
- `docs/plans/central-conteudos-publica-impl.md:81-85` (D6 revogada) e `docs/plans/central-conteudos-publica.md` (S27 — o catálogo e o tile)
|
||||
- `src/components/conteudos/ContentPieceCardInvite.tsx:16-44`, `src/components/conteudos/ContentPieceCatalog.tsx:50-55`, `src/app/(frontend)/conteudos/(catalog)/page.tsx:108,153-157`
|
||||
- `src/lib/cardModels.ts:65-135`, `src/lib/contentPieceCatalog.ts:39-107,155-269,506-548`, `src/components/conteudos/ContentPieceFilters.tsx`
|
||||
- `src/app/(frontend)/api/content-events/route.ts:95-114`, `src/lib/contentEvents.ts`, `docs/changelog/2026-09-23-s32.md`
|
||||
- `docs/plans/escala-dry-pos-s30.md` (#1277 — sobreposição só em `components/cards/`)
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
5/5 — (1) fatia = um outcome verificável (cada modelo encontrável por nome, apelido, busca e Tipo "Card"); (2) appetite ~1–1,5 dia cabe: itens sintéticos no board e nos filtros existentes, sem rota nem migration; (3) persona/job/aceite em linguagem de produto, com os apelidos literais do dono e o guardrail "card não é peça"; (4) direção no codebase é hipótese, com D6 e o tile atual abertos como pista; (5) zero decisão dura de engenharia — sem collection/schema/signature, com as três dúvidas de produto posicionadas.
|
||||
96
docs/plans/central-conteudos-header-logo-ui-design.html
Normal file
96
docs/plans/central-conteudos-header-logo-ui-design.html
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR" data-theme="campaign-site">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<title>Design — S33 · Marca no header da Central</title>
|
||||
<style type="text/tailwindcss">
|
||||
@theme { --font-sans: Arimo, Arial, sans-serif; }
|
||||
:root { --red:#ae1603; --kit-red:#e4102f; --blue:#184e92; --yellow:#ffeb00; --cream:#fff8f2; --muted:#6c615e; --line:rgb(0 0 0/.12); --display:'Exo 2','Arial Black',sans-serif; }
|
||||
*{box-sizing:border-box} body{font-family:Arimo,Arial,sans-serif}.display{font-family:var(--display)}
|
||||
.board{background:#e7e3e0;background-image:radial-gradient(rgb(24 78 146/.09) .7px,transparent .7px);background-size:18px 18px}
|
||||
.frame{box-shadow:0 22px 60px rgb(39 25 22/.13)}.desktop{width:1280px}.phone{width:390px;border-radius:28px}
|
||||
.scene:after{content:'';height:1px;flex:1;background:#cfc9c5}
|
||||
.trimmed-lockup{position:relative;overflow:hidden;width:188px;height:50px}
|
||||
.trimmed-lockup img{position:absolute;width:246px;max-width:none;left:-29px;top:-38px}
|
||||
.trimmed-lockup.mobile{width:142px;height:39px}.trimmed-lockup.mobile img{width:186px;left:-22px;top:-29px}
|
||||
.option{border:1px solid var(--line);border-radius:14px;background:white;overflow:hidden}.recommended{border:2px solid var(--kit-red);box-shadow:0 10px 26px rgb(228 16 47/.13)}
|
||||
</style>
|
||||
</head>
|
||||
<body class="board min-h-screen text-black antialiased">
|
||||
<main class="mx-auto max-w-[1480px] space-y-14 px-4 py-12 md:px-8">
|
||||
<header class="max-w-3xl">
|
||||
<span class="rounded-full bg-[#e4102f] px-3 py-1 text-xs font-bold text-white">S33 · decisão visual</span>
|
||||
<h1 class="display mt-4 text-4xl font-black">A marca volta a assinar a Central.</h1>
|
||||
<p class="mt-2 text-sm leading-6 text-[#6c615e]">Mesmo header, mesma altura e mesma copy. O gate escolhe somente o ativo e seu peso visual.</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 01</span><h2>Desktop 1280 · opções A e B lado a lado</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-[#f9faff] p-8">
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
<article class="option recommended">
|
||||
<div class="flex items-center justify-between bg-[#ae1603] px-8 h-16">
|
||||
<div class="trimmed-lockup" aria-label="Jorge Solla"><img src="../../public/campaign-kit/jorge-solla-negativo.png" alt="Jorge Solla" /></div>
|
||||
<span class="text-sm font-bold text-white">Central de Conteúdos</span>
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<div class="flex items-center justify-between gap-3"><h3 class="font-extrabold">A · Lockup oficial com recorte técnico</h3><span class="rounded-full bg-[#e4102f] px-2.5 py-1 text-[11px] font-black text-white">RECOMENDADA</span></div>
|
||||
<p class="mt-2 text-sm leading-6 text-[#6c615e]">Preserva a assinatura horizontal desenhada no S27 e remove somente a moldura transparente do PNG. A tinta lê em aproximadamente 46 px, no peso da referência pública.</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="option">
|
||||
<div class="flex h-16 items-center justify-between bg-[#ae1603] px-8">
|
||||
<img src="../../public/campaign-kit/marca-negativa-completa.png" class="h-[58px] w-auto object-contain" alt="Jorge Solla 1313 — Mais Saúde, Mais Futuro" />
|
||||
<span class="text-sm font-bold text-white">Central de Conteúdos</span>
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<h3 class="font-extrabold">B · Marca negativa completa</h3>
|
||||
<p class="mt-2 text-sm leading-6 text-[#6c615e]">Oficial e correta sobre vermelho, mas comprime nome, número e slogan na barra de 64 px. O slogan perde leitura e a massa vertical compete com o nome da seção.</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div class="mt-7 rounded-xl bg-white p-6">
|
||||
<p class="text-xs font-black tracking-[.12em] text-[#e4102f]">DECISÃO RECOMENDADA</p>
|
||||
<p class="display mt-1 text-2xl font-black">A · manter o lockup e corrigir a caixa, não redesenhar o header.</p>
|
||||
<p class="mt-2 max-w-3xl text-sm leading-6 text-[#6c615e]">Altura do header: 64 px. Inset horizontal: 32 px dentro do conteúdo. Lockup visível: 188 × 50 px. Badge existente: 14 px, bold. Sem novo lockup e sem alteração de cor.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 02</span><h2>Mobile 390 · as duas opções na barra real de 56 px</h2></div>
|
||||
<div class="flex flex-wrap justify-center gap-8">
|
||||
<article class="phone frame overflow-hidden bg-white">
|
||||
<div class="flex h-14 items-center justify-between bg-[#ae1603] px-5">
|
||||
<div class="trimmed-lockup mobile"><img src="../../public/campaign-kit/jorge-solla-negativo.png" alt="Jorge Solla" /></div><span class="text-white">☰</span>
|
||||
</div>
|
||||
<div class="p-5"><span class="rounded-full bg-[#e4102f] px-2.5 py-1 text-[10px] font-black text-white">A · RECOMENDADA</span><h3 class="display mt-4 text-2xl font-black">Central de Conteúdos</h3><p class="mt-2 text-sm leading-5 text-[#6c615e]">A assinatura continua reconhecível sem disputar espaço com o menu.</p></div>
|
||||
</article>
|
||||
<article class="phone frame overflow-hidden bg-white">
|
||||
<div class="flex h-14 items-center justify-between bg-[#ae1603] px-5"><img src="../../public/campaign-kit/marca-negativa-completa.png" class="h-[52px] w-auto object-contain" alt="Jorge Solla 1313 — Mais Saúde, Mais Futuro" /><span class="text-white">☰</span></div>
|
||||
<div class="p-5"><span class="rounded-full border border-black/15 px-2.5 py-1 text-[10px] font-black">B · ALTERNATIVA</span><h3 class="display mt-4 text-2xl font-black">Central de Conteúdos</h3><p class="mt-2 text-sm leading-5 text-[#6c615e]">O conjunto completo fica pequeno demais para o slogan cumprir sua função.</p></div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 03</span><h2>Página da peça · “Voltar à Central” e badge preservados</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white">
|
||||
<header class="flex h-16 items-center justify-between bg-[#ae1603] px-10">
|
||||
<div class="trimmed-lockup"><img src="../../public/campaign-kit/jorge-solla-negativo.png" alt="Jorge Solla" /></div><a class="text-sm font-bold text-white">Voltar à Central</a>
|
||||
</header>
|
||||
<div class="mx-auto grid max-w-5xl grid-cols-[1.15fr_.85fr] gap-10 px-10 py-12">
|
||||
<div class="grid aspect-video place-items-center rounded-2xl bg-stone-200 text-xs font-black tracking-wide text-stone-500">NEEDS ASSET · PREVIEW REAL DA PEÇA</div>
|
||||
<div><span class="inline-flex rounded-full bg-[#eef4fb] px-2 py-1 text-[11px] font-extrabold text-[#184e92]">Central de Conteúdos</span><h3 class="display mt-3 text-3xl font-black">Título da peça publicada</h3><p class="mt-3 text-sm leading-6 text-[#6c615e]">Descrição editorial da peça, sem alteração neste item.</p><div class="mt-6 h-11 rounded-[10px] bg-[#ffe607]"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="phone frame mx-auto mt-8 overflow-hidden bg-white">
|
||||
<header class="flex h-14 items-center justify-between bg-[#ae1603] px-5"><div class="trimmed-lockup mobile"><img src="../../public/campaign-kit/jorge-solla-negativo.png" alt="Jorge Solla" /></div><a class="text-xs font-bold text-white">Voltar à Central</a></header>
|
||||
<div class="p-5"><div class="aspect-video rounded-xl bg-stone-200"></div><span class="mt-5 inline-flex rounded-full bg-[#eef4fb] px-2 py-1 text-[11px] font-extrabold text-[#184e92]">Central de Conteúdos</span><h3 class="display mt-2 text-2xl font-black">Título da peça publicada</h3></div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
99
docs/plans/central-conteudos-header-logo.md
Normal file
99
docs/plans/central-conteudos-header-logo.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# S33 — Central de Conteúdos — logo do header no tamanho da marca
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-23
|
||||
Issue: #1301
|
||||
Priority: P2
|
||||
Impeccable: B — encaixe no header existente da Central pública (sem rota nova)
|
||||
Design UI: docs/plans/central-conteudos-header-logo-ui-design.html
|
||||
Appetite: ~0,25–0,5 dia eng; correção de fidelidade visual no header
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
No header da Central de Conteúdos pública (`/conteudos`), a marca lê muito menor do que no resto do site público — testado em staging pelo operador. O ativo oficial tem uma moldura transparente grande em volta do desenho, então a caixa do header mostra só uma fração dele: a marca fica com peso de detalhe, não de assinatura. A Central é a casa das peças de "Peça voto pra Solla 1313" e o header é a primeira coisa que o eleitor vê; a marca precisa ler no mesmo peso das outras páginas públicas, tirada do kit como fonte única (sem lockup novo, sem paleta inventada).
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** eleitor/simpatizante no celular, com pressa, chegando de um link compartilhado no WhatsApp; a Central ainda não é familiar e a marca no topo é a âncora de confiança de que ele está no lugar certo.
|
||||
- **Job principal:** reconhecer de imediato que está na Central oficial de Solla 1313 e seguir para a peça.
|
||||
- **Fluxo desejado:** abre `/conteudos` → vê a marca no topo no mesmo peso das outras páginas públicas → filtra/escolhe a peça; na página da peça e no estado de não encontrado, a mesma marca com o caminho de volta.
|
||||
- **Anti-goals de produto:** não vira redesign do header (nem da Central); não cria rota nem tela nova; não troca a marca por um lockup próprio nem inventa cor/tipografia; não mexe em copy, badge ou comportamento do "Voltar à Central"; não é passada de olho nas outras páginas públicas.
|
||||
|
||||
### Esboço de fluxo (B)
|
||||
|
||||
```text
|
||||
[abre /conteudos (catálogo, peça, não encontrado)] → [header vermelho com a marca no peso das outras públicas]
|
||||
→ [segue para a peça / volta à Central]
|
||||
```
|
||||
|
||||
### Design UI (B)
|
||||
|
||||
- Design UI (gate): `docs/plans/central-conteudos-header-logo-ui-design.html` — o humano valida no gate que a marca lê no peso certo nos dois breakpoints, com a opção de ativo escolhida.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- A marca no header da Central lê, nos dois breakpoints, no mesmo peso visual do header público de referência (`/jingles`) — aferido lado a lado em staging.
|
||||
- Fonte única da marca é o kit 1313 (`public/campaign-kit/`); nenhum lockup recriado, nenhuma cor ou tipografia inventada.
|
||||
- A correção vive no header da Central (escolha de ativo e/ou tamanho renderizado), sem redesenhar o header.
|
||||
- Badge "Central de Conteúdos", link "Voltar à Central" e comportamento nos dois breakpoints permanecem.
|
||||
- Nenhuma outra página pública muda (sem drive-by).
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não.
|
||||
- **Decisões desbloqueadas:** N/A — correção de fidelidade visual; nenhum ator decide com número.
|
||||
- **Forma:** *adiada ao plano de implementação* — sem restrição de produto além da referência de peso visual acima.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- Superfícies do header: `/conteudos` (catálogo, com e sem peças publicadas), `/conteudos/<slug>` e o não encontrado da peça — todas usam `ContentPiecePageHeader`.
|
||||
- Header atual: `src/components/conteudos/ContentPiecePageHeader.tsx:12-22` — `<Image src="/campaign-kit/jorge-solla-negativo.png" ... className="h-7 w-auto object-contain sm:h-9" />`, dentro de um `div` `h-14 sm:h-16` sobre `bg-[#ae1603]`.
|
||||
- Ativo atual: canvas 1037×595; recorte visível 790×285 (transparência topo 162, base 148, esquerda 123, direita 124) → marca visível ≈13,4 px em `h-7` e ≈17,2 px em `sm:h-9`.
|
||||
- Referência de peso (`/jingles`): `src/components/CampaignPageHeader.tsx:20-27` com `marca-positiva-completa.png` (visível 552×415 no mesmo canvas 1037×595) em `h-[66px] sm:h-[74px]` → ≈46/52 px visíveis (≈3× a marca da Central).
|
||||
- O ativo negativo `jorge-solla-negativo.png` só é usado em `ContentPiecePageHeader.tsx:16`; o S27 portou fielmente o `h-9` do artefato `docs/plans/central-conteudos-publica-ui-design.html:158-164,427-433` (cenas 01/04), mas artefato+ativo juntos renderizam pequeno.
|
||||
- Dono da marca: `public/campaign-kit/README.md` (kit 1313). A pasta já tem, para fundo vermelho/escuro, a **marca completa** `marca-negativa-completa.png` (nome + 1313 + slogan; visível 552×415 no mesmo canvas, `README.md:35-37`) — ativo diferente do lockup de nome usado no header hoje; e não tem nenhuma variante **recortada** do lockup `jorge-solla-negativo.png`.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/components/conteudos/ContentPiecePageHeader.tsx` (único componente do header da Central) e `public/campaign-kit/` (ativo/kit); rotas consumidoras em `src/app/(frontend)/conteudos/`.
|
||||
- **Precedente a olhar:** `src/components/CampaignPageHeader.tsx` (header de `/jingles`, mesmo canvas, peso-alvo) e o S27 `docs/plans/central-conteudos-publica.md`.
|
||||
- **Risco de acoplamento:** o header é page-local da Central (não é shell do site) — a correção não deve virar componente compartilhado nem alterar `CampaignPageHeader`.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma dura. Contexto: S27 (#1255) entregou a Central pública e o header.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Redesenho do header da Central ou da página (fica para novo item, se houver pedido).
|
||||
- Outras páginas públicas e seus headers (`/jingles`, home, `/cards`) — sem mudanças de carona.
|
||||
- Recriar lockup, paleta ou tipografia; qualquer coisa fora do kit 1313.
|
||||
- Copy, badge, CTA e comportamento do "Voltar à Central".
|
||||
- Qualquer mudança de dados, consentimento ou rotas.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Já que estou no header, padronizo os outros."** Se alguém "só completar": vira refactor de todos os headers públicos e revisão de marca. **Corte neste item:** só o header da Central.
|
||||
- **"Monto um lockup novo com o ativo recortado no Figma."** Se alguém "só completar": nasce uma marca paralela fora do kit. **Corte neste item:** kit como fonte única; no máximo preparo técnico do ativo oficial (recorte do PNG existente), não desenho novo.
|
||||
- **"Ajusto o header inteiro para caber a marca."** Se alguém "só completar": muda altura, espaçamento e badge das telas. **Corte neste item:** a menor mudança que faça a marca ler no peso certo.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Qual ativo/tamanho faz a marca ler no peso certo?** **Opções:** A) lockup `jorge-solla-negativo.png` com o recorte técnico da moldura transparente (preparo do ativo oficial no kit, sem redesenho); B) usar a marca completa `marca-negativa-completa.png` (nome + 1313 + slogan), que o kit destina a fundos vermelhos/escuros e tem proporção visível muito maior; C) compensar no header o tamanho renderizado do lockup atual, sem distorcer. **Recomendação:** decidir no gate com o design hi-fi mostrando A e B lado a lado (o lockup é o que o S27 desenhou; a marca completa é o ativo do kit para o fundo vermelho); C só se nenhuma das duas servir. _(assumido — validar no gate do design)_
|
||||
|
||||
## Referências
|
||||
|
||||
- Design UI (gate): `docs/plans/central-conteudos-header-logo-ui-design.html` (+ assets em `central-conteudos-header-logo-ui-design-assets/`).
|
||||
- `docs/plans/central-conteudos-publica-ui-design.html` — artefato do S27 (cenas 01/04/06/07/08: header com `h-9`).
|
||||
- `src/components/conteudos/ContentPiecePageHeader.tsx`, `src/components/CampaignPageHeader.tsx`, `public/campaign-kit/README.md`.
|
||||
- S27: `docs/plans/central-conteudos-publica.md` (Issue #1255).
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
1. Fatia = um outcome verificável? 5/5 — a marca no peso certo, aferida lado a lado em staging.
|
||||
2. Appetite declarado e a intenção cabe nele? 5/5 — ~0,25–0,5 dia; uma escolha de ativo/tamanho.
|
||||
3. Persona + job + aceite claros (sem jargão de stack)? 4/5 — aceite fala em peso visual; a aferição exige comparação em staging.
|
||||
4. Direção no codebase é hipótese (não contrato técnico)? 5/5 — arquivos e classes são literais de estado atual/evidência, não prescrição.
|
||||
5. Zero decisões duras de engenharia no plano? 4/5 — a questão em aberto recomenda decidir no gate; a escolha final (ativo vs compensação) fica para o gate/impl.
|
||||
Média: 4,6/5 — ≥4/5.
|
||||
38
docs/plans/central-conteudos-liderancas-ui-design.html
Normal file
38
docs/plans/central-conteudos-liderancas-ui-design.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<title>Design — S34 · Lideranças nas peças</title>
|
||||
<style type="text/tailwindcss">
|
||||
@theme{--font-sans:Arimo,Arial,sans-serif} :root{--red:#a21c1c;--kit:#e4102f;--blue:#184e92;--yellow:#ffe607;--cream:#fff8f2;--muted:#6c615e;--line:rgb(0 0 0/.12);--display:'Exo 2','Arial Black',sans-serif}
|
||||
*{box-sizing:border-box}.display{font-family:var(--display)}.board{background:#e7e3e0;background-image:radial-gradient(rgb(24 78 146/.09) .7px,transparent .7px);background-size:18px 18px}.frame{box-shadow:0 22px 60px rgb(39 25 22/.13)}.desktop{width:1280px}.phone{width:390px;border-radius:28px}.scene:after{content:'';height:1px;flex:1;background:#cfc9c5}
|
||||
.field{min-height:44px;border:1px solid #d6d3d1;border-radius:6px;background:white;padding:10px 12px;font-size:14px}.label{font-size:13px;font-weight:600}.chip{display:inline-flex;min-height:36px;align-items:center;gap:6px;border:1px solid var(--line);border-radius:999px;background:white;padding:6px 11px;font-size:12px;font-weight:700}.active{border-color:rgb(24 78 146/.35);background:#eef4fb;color:#184e92}.tag{display:inline-flex;align-items:center;gap:5px;border-radius:999px;background:#f4f4f5;padding:5px 8px;font-size:12px;font-weight:600}.btn{display:inline-flex;min-height:44px;align-items:center;justify-content:center;border-radius:8px;padding:9px 14px;font-size:14px;font-weight:700}.primary{background:#c51414;color:white}.catalog-card{overflow:hidden;border:1px solid var(--line);border-radius:14px;background:white;box-shadow:0 8px 24px rgb(71 19 14/.07)}
|
||||
</style>
|
||||
</head>
|
||||
<body class="board min-h-screen text-black antialiased">
|
||||
<main class="mx-auto max-w-[1480px] space-y-14 px-4 py-12 md:px-8">
|
||||
<header class="max-w-3xl"><span class="rounded-full bg-[#e4102f] px-3 py-1 text-xs font-bold text-white">S34 · dois recortes, uma faceta</span><h1 class="display mt-4 text-4xl font-black">Quem aparece na peça fica encontrável — sem expor quem não aparece.</h1><p class="mt-2 text-sm leading-6 text-[#6c615e]">A ficha separa liderança interna de figura pública; a Central pública reúne apenas os nomes presentes em peças publicadas.</p></header>
|
||||
|
||||
<section><div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 01</span><h2>Ficha interna · desktop 1280 · os dois recortes</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white" data-theme="campaign"><header class="flex h-14 items-center justify-between border-b bg-[#fafaf9] px-6"><b>Campanha · Comunicação</b><span class="text-sm text-[#6b7280]">Central de Conteúdos</span></header><div class="p-8"><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><div class="mt-2 flex items-start justify-between"><div><h2 class="text-xl font-semibold">Título da peça em revisão</h2><div class="mt-2 flex gap-2"><span class="rounded-full bg-green-100 px-2 py-1 text-xs font-semibold text-green-800">Pronto</span><span class="rounded-full bg-[#f4f4f5] px-2 py-1 text-xs font-semibold text-[#6b7280]">Rascunho</span></div></div><button class="btn border bg-white">Publicar</button></div>
|
||||
<div class="mt-7 grid grid-cols-[300px_1fr] gap-8"><aside><div class="grid aspect-video place-items-center rounded-xl bg-stone-200 text-xs font-bold text-stone-500">NEEDS ASSET · PREVIEW REAL</div><dl class="mt-4 space-y-2 text-xs"><div class="flex justify-between"><dt class="text-[#6b7280]">Origem</dt><dd>Arquivo</dd></div><div class="flex justify-between"><dt class="text-[#6b7280]">Tipo</dt><dd>Vídeo</dd></div></dl></aside>
|
||||
<form class="grid grid-cols-2 gap-4"><div class="col-span-2"><p class="label">Título</p><div class="field mt-1">Título da peça em revisão</div></div><div class="col-span-2 rounded-xl border p-5"><div class="flex items-start justify-between gap-6"><div><h3 class="font-semibold">Quem aparece na peça</h3><p class="mt-1 text-xs leading-5 text-[#6b7280]">Marque somente pessoas visíveis ou participantes desta peça. A publicação expõe apenas o nome.</p></div><span class="rounded-full bg-[#fff5ed] px-2 py-1 text-[11px] font-semibold text-[#6b2d15]">Curadoria humana</span></div>
|
||||
<div class="mt-5 grid grid-cols-2 gap-5"><div><p class="label">Lideranças da campanha</p><p class="mt-1 text-xs leading-5 text-[#6b7280]">Busca nos registros existentes. Nenhum telefone, município ou voto vai para a Central pública.</p><div class="mt-2 flex flex-wrap gap-1.5"><span class="tag">Nome da liderança <b>×</b></span></div><div class="field mt-2 flex items-center justify-between text-[#6b7280]"><span>Buscar liderança…</span><span>⌄</span></div><div class="mt-1 rounded-lg border bg-white p-1 shadow-lg"><div class="rounded-md bg-[#f4f4f5] px-3 py-2 text-sm"><b>Nome da liderança</b><span class="block text-xs text-[#6b7280]">Registro da campanha</span></div><div class="px-3 py-2 text-sm">Outra liderança de exemplo</div></div></div>
|
||||
<div><p class="label">Figuras públicas</p><p class="mt-1 text-xs leading-5 text-[#6b7280]">Texto curado com catálogo, no mesmo molde de Instituição.</p><div class="mt-2 flex flex-wrap gap-1.5"><span class="tag">Dep. Estadual Exemplo <b>×</b></span></div><div class="field mt-2 flex items-center justify-between text-[#6b7280]"><span>Digite ou escolha uma figura pública…</span><span>⌄</span></div><div class="mt-1 rounded-lg border bg-white p-1 shadow-lg"><div class="rounded-md bg-[#f4f4f5] px-3 py-2 text-sm"><b>Dep. Estadual Exemplo</b><span class="block text-xs text-[#6b7280]">Figura pública catalogada</span></div><div class="px-3 py-2 text-sm">Personalidade Exemplo</div></div></div></div>
|
||||
</div><div><p class="label">Instituição</p><div class="field mt-1 text-[#6b7280]">Sem instituição</div></div><div><p class="label">Cidade</p><div class="field mt-1 text-[#6b7280]">Sem cidade</div></div><div class="col-span-2 flex justify-end"><button class="btn primary">Salvar alterações</button></div></form>
|
||||
</div></div></div>
|
||||
</section>
|
||||
|
||||
<section><div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 02</span><h2>Ficha interna · mobile 390 · pessoa marcada e ninguém marcado</h2></div>
|
||||
<div class="flex flex-wrap justify-center gap-8"><div class="phone frame min-h-[760px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between border-b px-4"><b>Central de Conteúdos</b><span>☰</span></header><div class="p-4"><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><h2 class="mt-2 text-lg font-semibold">Título da peça</h2><div class="mt-5 rounded-xl border p-4"><h3 class="font-semibold">Quem aparece na peça</h3><p class="mt-1 text-xs leading-5 text-[#6b7280]">Somente o nome poderá aparecer no filtro público.</p><p class="label mt-5">Lideranças da campanha</p><div class="mt-2 flex"><span class="tag">Nome da liderança <b>×</b></span></div><div class="field mt-2 flex justify-between text-[#6b7280]"><span>Buscar liderança…</span><span>⌄</span></div><p class="label mt-5">Figuras públicas</p><div class="mt-2 flex"><span class="tag">Dep. Estadual Exemplo <b>×</b></span></div><div class="field mt-2 flex justify-between text-[#6b7280]"><span>Digite ou escolha…</span><span>⌄</span></div></div><button class="btn primary mt-5 w-full">Salvar alterações</button></div></div>
|
||||
<div class="phone frame min-h-[620px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between border-b px-4"><b>Central de Conteúdos</b><span>☰</span></header><div class="p-4"><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><h2 class="mt-2 text-lg font-semibold">Peça sem ninguém marcado</h2><div class="mt-5 rounded-xl border p-4"><h3 class="font-semibold">Quem aparece na peça</h3><div class="mt-4 rounded-lg bg-[#f4f4f5] p-3 text-xs leading-5 text-[#6b7280]">Ninguém marcado. A peça pode ser publicada normalmente e não cria nenhum nome na faceta “Lideranças”.</div><p class="label mt-5">Lideranças da campanha</p><div class="field mt-2 text-[#6b7280]">Buscar liderança…</div><p class="label mt-5">Figuras públicas</p><div class="field mt-2 text-[#6b7280]">Digite ou escolha…</div></div><button class="btn primary mt-5 w-full">Salvar alterações</button></div></div></div>
|
||||
</section>
|
||||
|
||||
<section><div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 03</span><h2>Catálogo público · faceta única “Lideranças” · desktop e mobile</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white"><header class="flex h-16 items-center justify-between bg-[#ae1603] px-10"><div class="h-9 w-44 rounded bg-white/20"></div><b class="text-sm text-white">Central de Conteúdos</b></header><div class="mx-auto max-w-6xl px-10 py-10"><div class="rounded-xl bg-[#fff8f2] p-4"><div class="h-11 rounded-[10px] border bg-white px-3 py-3 text-sm text-[#6c615e]">Encontre uma peça por assunto, cidade ou pessoa…</div><div class="mt-3 flex flex-wrap gap-2"><span class="chip">Tipo⌄</span><span class="chip">Cidade⌄</span><span class="chip">Região⌄</span><span class="chip">Tema⌄</span><span class="chip">Instituição⌄</span><details open class="relative"><summary class="chip list-none border-[#184e92]/35 bg-[#eef4fb] text-[#184e92]">Lideranças⌄</summary><div class="absolute z-10 mt-1 w-64 rounded-xl border bg-white p-2 shadow-xl"><p class="px-2 py-1 text-[10px] font-black tracking-wide text-[#6c615e]">EM PEÇAS PUBLICADAS</p><div class="rounded-lg bg-[#f4f4f5] px-3 py-2 text-sm font-medium">Nome da liderança</div><div class="px-3 py-2 text-sm">Dep. Estadual Exemplo</div><div class="px-3 py-2 text-sm">Personalidade Exemplo</div></div></details></div></div><div class="mt-24 flex items-center justify-between"><div><h3 class="display text-2xl font-black">Peças com Nome da liderança</h3><p class="mt-1 text-sm text-[#6c615e]">O filtro combina com cidade, tema e os demais recortes.</p></div><span class="chip active">Lideranças · Nome da liderança ×</span></div><div class="mt-5 grid grid-cols-3 gap-6"><article class="catalog-card"><div class="grid aspect-video place-items-center bg-stone-200 text-[10px] font-black text-stone-500">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="rounded-full bg-[#eef4fb] px-2 py-1 text-[11px] font-extrabold text-[#184e92]">Vídeo</span><h4 class="mt-2 font-extrabold">Título da peça publicada</h4><p class="mt-1 text-xs text-[#6c615e]">Nome da liderança · Tema</p></div></article></div><div class="mt-7 rounded-lg border border-dashed p-4 text-xs leading-5 text-[#6c615e]"><b class="text-black">Regra visível do gate:</b> este menu é derivado somente das peças publicadas. Despublicar a última peça de um nome remove esse nome da faceta imediatamente. Sem contato, território, organização, status ou votos.</div></div></div>
|
||||
<div class="phone frame mx-auto mt-8 min-h-[740px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between bg-[#ae1603] px-4"><div class="h-7 w-32 rounded bg-white/20"></div><span class="text-white">☰</span></header><div class="p-4"><div class="h-11 rounded-[10px] border px-3 py-3 text-sm text-[#6c615e]">Busque uma pessoa…</div><div class="mt-3 flex gap-2 overflow-hidden"><span class="chip shrink-0">Tipo⌄</span><span class="chip active shrink-0">Lideranças · Nome da liderança ×</span></div><div class="mt-5 rounded-xl border bg-white p-3 shadow-lg"><p class="px-2 py-1 text-[10px] font-black tracking-wide text-[#6c615e]">LIDERANÇAS · EM PEÇAS PUBLICADAS</p><div class="rounded-lg bg-[#f4f4f5] px-3 py-3 text-sm font-medium">Nome da liderança</div><div class="px-3 py-3 text-sm">Dep. Estadual Exemplo</div></div><article class="catalog-card mt-5"><div class="grid aspect-video place-items-center bg-stone-200 text-[10px] font-black text-stone-500">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="rounded-full bg-[#eef4fb] px-2 py-1 text-[11px] font-extrabold text-[#184e92]">Vídeo</span><h4 class="mt-2 text-lg font-extrabold">Título da peça publicada</h4><p class="mt-1 text-xs text-[#6c615e]">Nome da liderança</p><button class="btn mt-4 w-full bg-[#ffe607] text-black">Compartilhar</button></div></article></div></div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
119
docs/plans/central-conteudos-liderancas.md
Normal file
119
docs/plans/central-conteudos-liderancas.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
# S34 — Central de Conteúdos — lideranças que aparecem nas peças (propriedade e filtro)
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-23
|
||||
Issue: #1303
|
||||
Priority: P2
|
||||
Impeccable: C — propriedade nova na ficha interna (C211) + faceta nova no catálogo público (S27)
|
||||
Design UI: docs/plans/central-conteudos-liderancas-ui-design.html
|
||||
Appetite: ~2 dias eng; um outcome verificável (a peça registra quem aparece e o catálogo público filtra por isso)
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
A campanha já tem a Central de Conteúdos interna (C211), onde a assessoria cataloga as peças, e a Central pública (S27), onde o eleitor filtra por Tipo, Cidade, Região, Tema e Instituição — mas "quem aparece na peça" não existe em lugar nenhum. Numa campanha de dobradinhas, é exatamente esse o recorte que o eleitor procura: o material em que a liderança dele ou o estadual dele aparece, para repassar no grupo. A comunicação quer registrar isso na peça; o eleitor quer filtrar por isso. A decisão do humano no planejamento foi "Os dois": a peça registra as lideranças da campanha que aparecem E as figuras públicas (dobradinhas/estaduais e outras personalidades), e o catálogo público tem os dois recortes na mesma faceta `Lideranças`. O cuidado que define o item: o que é interno (liderança é PII, escopada por perfil) não pode vazar no que é público — a faceta mostra só nomes de quem aparece em peça publicada.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** dois atores. A assessoria de comunicação, na mesa, editando a ficha da peça (o mesmo gate que já edita a ficha hoje); o eleitor/liderança, no celular, na Central, procurando o material em que a referência dele aparece.
|
||||
- **Job principal:** (comunicação) registrar quem aparece na peça; (eleitor) achar a peça em que uma pessoa aparece e repassá-la.
|
||||
- **Fluxo desejado:** comunicação abre a ficha da peça → marca as lideranças da campanha que aparecem e as figuras públicas (dobradinhas/personalidades) → publica; eleitor abre `/conteudos` → filtra pela faceta `Lideranças` → vê só nomes de quem aparece em peça publicada → abre a peça e compartilha.
|
||||
- **Anti-goals de produto:** segundo cadastro de pessoa; expor qualquer dado interno de liderança; virar diretório de lideranças ou placar de aparições; página pública por pessoa; mudar o que a liderança vê hoje (leader lockdown intocado).
|
||||
|
||||
### Esboço de fluxo (C)
|
||||
|
||||
```text
|
||||
[assessoria] ficha da peça (C211)
|
||||
→ marca quem aparece: lideranças da campanha (registros de Liderança) + figuras públicas (dobradinhas/personalidades)
|
||||
→ publica a peça
|
||||
[eleitor] /conteudos → faceta `Lideranças` (os dois recortes no mesmo filtro)
|
||||
→ só nomes de quem aparece em pelo menos uma peça publicada (fail-closed)
|
||||
→ abre a peça → baixa/compartilha
|
||||
[peça despublicada] → o nome some da faceta se não houver outra peça publicada com ele
|
||||
```
|
||||
|
||||
### Design UI (C)
|
||||
|
||||
- Design UI (gate): `docs/plans/central-conteudos-liderancas-ui-design.html` (+ assets em `central-conteudos-liderancas-ui-design-assets/`) — cenas: ficha interna com os dois recortes (lideranças + figuras públicas), faceta `Lideranças` no catálogo público (mobile/desktop) e o estado de peça sem ninguém marcado.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- A ficha da peça registra dois recortes de "quem aparece": (1) as lideranças da campanha — os registros de Liderança existentes, sem cadastro novo — e (2) figuras públicas (dobradinhas/estaduais e outras personalidades), em texto curado com catálogo, no molde de Instituição.
|
||||
- O catálogo público ganha a faceta `Lideranças`, unindo os dois recortes no mesmo filtro (decisão do humano: "Os dois"); os filtros continuam combinando entre si como hoje.
|
||||
- **Fail-closed de exposição:** a faceta mostra só NOMES de pessoas referenciadas por pelo menos uma peça publicada; nunca expõe liderança ou figura que não aparece em peça publicada.
|
||||
- **Nada de dado interno:** sem contato, telefone, e-mail, municípios, organizações, status ou votos (declarados/estimados) de liderança; o leader lockdown segue intocado.
|
||||
- Quem edita é quem já edita a ficha hoje (gate da assessoria de comunicação); a catalogação pode sugerir, mas nunca sobrescreve curadoria humana.
|
||||
- Os nomes marcados entram na busca por termo da Central como qualquer outro conteúdo — buscar o nome de quem aparece acha a peça.
|
||||
- Publicar/despublicar atualiza a faceta na hora: sem peça publicada com o nome, ele não aparece.
|
||||
- Guardrails: sem cadastro paralelo de pessoa (relaciona ao dono existente ou usa o molde texto+catálogo); nada novo de PII é capturado e Consent/LGPD ficam intocados — a metade "lideranças da campanha" só mostra dados quando existirem lideranças (o dado de liderança segue atrás do bloqueio LGPD de produção).
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — a faceta é uma lista de nomes; sem contagem, sem ranking, sem placar de aparições.
|
||||
- **Decisões desbloqueadas:** a comunicação decide quem aparece em cada peça; o eleitor decide qual peça procurar pelo nome de quem aparece nela.
|
||||
- **Forma:** *adiada ao plano de implementação* — restrição de produto: só nomes de exibição (sem número, sem contagem por pessoa, sem métrica de aparições).
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- ID `S34`; slug `central-conteudos-liderancas` (arquivo `docs/plans/central-conteudos-liderancas.md`); tipo `feature`; Priority `P2`.
|
||||
- Faceta pública: rótulo `Lideranças` (uma só), unindo os dois recortes no mesmo filtro.
|
||||
- Recorte 1 — lideranças da campanha: os registros de `Liderança` existentes (dono atual; não criar cadastro de pessoa).
|
||||
- Recorte 2 — figuras públicas: dobradinhas/estaduais do roster público e outras personalidades, em texto curado com catálogo (molde de `Instituição`), semeado com os nomes das dobradinhas.
|
||||
- Regra de exposição (fail-closed): só NOMES de pessoas que aparecem em pelo menos uma peça publicada; sem peça publicada, o nome não aparece.
|
||||
- Resposta do humano no planejamento (verbatim): **"Os dois"** — a peça registra lideranças da campanha E figuras públicas, e o filtro público tem os dois recortes na mesma faceta.
|
||||
- Guardrail literal: **sem cadastro paralelo de pessoa**; sem exposição de contato/território/votos da liderança.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** ficha interna da peça (`src/components/campaign/content/ContentPieceForm.tsx`, `src/utilities/content/…`); contrato/filtro público (`src/lib/contentPieceCatalog.ts`, `src/components/conteudos/ContentPieceFilters.tsx`); catalogação (`src/utilities/content/contentPieceCataloging.ts`).
|
||||
- **Precedente a olhar:** `institution` — campo texto na peça (`src/collections/ContentPiece.ts:303-307`) + catálogo (`src/lib/institutionCatalog.ts`) + aliases (`src/lib/institutionNameAliases.ts`) + match na catalogação (`contentPieceCataloging.ts:181-193`); a faceta pública deriva rótulos das peças publicadas por `slugify` (`contentPieceCatalog.ts:155-184,252-269`), parâmetro `instituicao` (`:39-55,96-107`). `Speech.mentionedPeople` (`src/collections/Speech.ts:306-312`) é precedente de "pessoas citadas" por texto, mas sem filtro público — não copiar o par acervo/C200.
|
||||
- **Roster público de pessoas:** `src/lib/stateDeputyCatalog.ts` (53 dobradinhas, nome+número, público via S30).
|
||||
- **Risco de acoplamento:** `leadership` é interno e PII-bound (leitura escopada por perfil — `src/utilities/access/leaderships.ts:31-32`); a superfície pública não pode ler `leadership`, `Contact`, `campaignUser` ou `electionCandidate` nem expor campo interno — os nomes públicos derivam só das peças publicadas. A busca pública casa o texto normalizado da peça (`src/lib/contentPiece.ts:323`), então o nome precisa ser encontrável por lá. Leader lockdown intocado.
|
||||
|
||||
## Dependências
|
||||
|
||||
- C211 (peças catalogadas/publicadas) e S27 (catálogo público com facetas) entregues — dura: sem peça publicada não há nome na faceta.
|
||||
- Roster das dobradinhas (S30) como semente do recorte de figuras públicas — soft.
|
||||
- Design hi-fi aprovado no gate.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Cards personalizados: a escolha do estadual no estúdio (S30/S31) é do visitante, não propriedade da peça.
|
||||
- C200 (separação por pessoa no acervo / speakers em gravações, #1167) — superfície distinta; não acoplar.
|
||||
- Expor qualquer dado interno de liderança (contato, telefone, e-mail, municípios, organizações, votos declarados/estimados).
|
||||
- Mudanças de LGPD/Consent: nada novo de PII é capturado; o dado de liderança segue atrás do bloqueio LGPD de produção (a metade campanha só mostra quando houver lideranças).
|
||||
- Filtro/coluna na lista interna de peças — só se o gate pedir (ver Q(a)).
|
||||
- Página pública por pessoa, diretório/ranking de aparições, analytics de circulação (C213).
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **Cadastro paralelo de pessoa.** Se alguém "só completar": collection de "pessoas que aparecem" com nome/telefone/cidade. **Corte neste item:** liderança = registro existente; figura pública = texto curado + catálogo; nenhum cadastro novo.
|
||||
- **A faceta virar diretório de lideranças.** Se alguém "só completar": listar todas as lideranças, com município e status. **Corte neste item:** só nomes de quem aparece em peça publicada; nada de dado interno.
|
||||
- **Placar de aparições.** Se alguém "só completar": contador por pessoa, "quem aparece mais", ranking. **Corte neste item:** lista de nomes sem número.
|
||||
- **Página por pessoa.** Se alguém "só completar": `/conteudos/pessoa/<nome>` ou um hub da liderança. **Corte neste item:** uma faceta no catálogo existente; a peça continua sendo a unidade.
|
||||
- **A catalogação automática decidir por gente.** Se alguém "só completar": o pipeline preenche e sobrescreve os nomes. **Corte neste item:** sugestão só quando confiável; curadoria humana manda.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Filtro só público ou também filtro/coluna na lista interna?** **Opções:** A) faceta pública (o pedido) + propriedade visível/editável na ficha interna | B) também filtro/coluna na lista interna. **Recomendação:** A — é o pedido; filtro/coluna interno só se o gate pedir. _(assumido — validar com produto)_
|
||||
- **Uma faceta unindo os dois recortes ou duas facetas?** **Opções:** A) uma faceta `Lideranças` com os dois recortes | B) `Lideranças` + `Figuras públicas`. **Recomendação:** A — o humano escolheu "Os dois" no mesmo filtro; B fica registrada como alternativa se o volume de figuras públicas justificar separar. _(assumido — validar com produto)_
|
||||
- **O recorte de figuras públicas reusa o roster das dobradinhas ou é texto com aliases?** **Opções:** A) texto curado + catálogo no molde de Instituição, semeado com os nomes das dobradinhas | B) só o roster fechado das 53 dobradinhas | C) texto livre sem catálogo. **Recomendação:** A — cobre dobradinhas e outras personalidades sem inventar cadastro; C perde o casamento de grafias. _(assumido — validar com produto)_
|
||||
- **Que nome da liderança aparece?** **Opções:** A) o nome do contato (é o título da Liderança hoje) | B) algum rótulo composto. **Recomendação:** A — só o nome; nunca telefone, e-mail ou município. _(assumido — validar com produto)_
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue — a registrar (`pnpm agent:register`).
|
||||
- Design UI (gate): `docs/plans/central-conteudos-liderancas-ui-design.html` (+ assets em `central-conteudos-liderancas-ui-design-assets/`).
|
||||
- Planos irmãos: `docs/plans/central-conteudos-ingestao.md` (C211), `docs/plans/central-conteudos-publica.md` (S27), `docs/plans/cards-estadual-dobradinha.md` (S30), `docs/plans/acervo-separacao-por-pessoa.md` (C200 — fora de escopo).
|
||||
- Arquivos-pista: `src/collections/ContentPiece.ts`, `src/components/campaign/content/ContentPieceForm.tsx`, `src/lib/contentPieceCatalog.ts`, `src/components/conteudos/ContentPieceFilters.tsx`, `src/lib/institutionCatalog.ts`, `src/lib/institutionNameAliases.ts`, `src/utilities/content/contentPieceCataloging.ts`, `src/lib/stateDeputyCatalog.ts`, `src/collections/Leadership.ts`, `src/utilities/access/leaderships.ts`, `src/collections/Speech.ts`.
|
||||
- `AGENTS.md` — convenções já travadas (Contact como dono da pessoa; sem cadastro paralelo; migrations para schema).
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
5/5 — um outcome verificável, appetite declarado e nenhuma decisão dura de engenharia.
|
||||
|
||||
- Fatia = um outcome verificável: a peça registra quem aparece e o catálogo público filtra por isso.
|
||||
- Appetite ~2 dias cabe: uma propriedade na ficha existente + uma faceta no catálogo existente, sem fluxo novo.
|
||||
- Persona + job + aceite claros, em linguagem de produto, sem jargão de stack.
|
||||
- Direção no codebase é hipótese: arquivos citados como pista, nenhum nome novo cravado.
|
||||
- Zero schema/migration/signature no plano; literais são só de produto (rótulo, recortes, regra de exposição e a resposta do humano).
|
||||
46
docs/plans/central-conteudos-link-instagram-ui-design.html
Normal file
46
docs/plans/central-conteudos-link-instagram-ui-design.html
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR" data-theme="campaign">
|
||||
<head>
|
||||
<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<title>Design — C215 · Link do Instagram</title>
|
||||
<style type="text/tailwindcss">
|
||||
@theme{--font-sans:Inter,Arial,sans-serif;--color-background:#fff;--color-foreground:#1c1917;--color-primary:#c51414;--color-muted:#f4f4f5;--color-muted-foreground:#6b7280;--color-border:rgb(28 25 23/.12)}
|
||||
*{box-sizing:border-box}.board{background:#ecebea;background-image:radial-gradient(#d5d1cd .7px,transparent .7px);background-size:18px 18px}.frame{box-shadow:0 20px 55px rgb(28 25 23/.12)}.desktop{width:1280px}.phone{width:390px;border-radius:28px}.scene:after{content:'';height:1px;flex:1;background:#cbc7c2}
|
||||
.field{min-height:44px;border:1px solid #d6d3d1;border-radius:6px;background:white;padding:10px 12px;font-size:14px}.label{font-size:13px;font-weight:600}.badge{display:inline-flex;align-items:center;border-radius:999px;padding:3px 8px;font-size:12px;font-weight:600}.btn{display:inline-flex;min-height:44px;align-items:center;justify-content:center;gap:8px;border-radius:6px;padding:9px 14px;font-size:14px;font-weight:600}.primary{background:#c51414;color:white}.outline{border:1px solid #d6d3d1;background:white}.shell{display:grid;grid-template-columns:220px 1fr}.side{background:#fafaf9;border-right:1px solid rgb(28 25 23/.12)}
|
||||
</style>
|
||||
</head>
|
||||
<body class="board min-h-screen text-[#1c1917] antialiased">
|
||||
<main class="mx-auto max-w-[1480px] space-y-14 px-4 py-12 md:px-8">
|
||||
<header class="max-w-3xl"><span class="rounded-full bg-[#c51414] px-3 py-1 text-xs font-bold text-white">C215 · ficha existente</span><h1 class="mt-4 text-4xl font-bold tracking-tight">O link nunca degrada em silêncio.</h1><p class="mt-2 text-sm leading-6 text-[#6b7280]">A ficha conta o que está acontecendo, o que foi extraído e por que uma peça ficou apenas como link.</p></header>
|
||||
|
||||
<section><div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6b7280]"><span>CENA 01</span><h2>Desktop 1280 · processando → extraída e catalogada</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white">
|
||||
<div class="shell min-h-[710px]"><aside class="side p-5"><div class="h-7 w-32 rounded bg-[#c51414]"></div><nav class="mt-8 space-y-2 text-sm"><div class="rounded-md bg-[#f5f5f4] px-3 py-2 font-semibold">Comunicação</div><div class="px-3 py-2 text-[#6b7280]">Central de Conteúdos</div></nav></aside>
|
||||
<div class="p-8"><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><div class="mt-2 flex items-start justify-between"><div><h2 class="text-xl font-semibold">Peça adicionada pelo Instagram</h2><div class="mt-2 flex gap-2"><span class="badge bg-amber-100 text-amber-900">Processando</span><span class="badge bg-[#f4f4f5] text-[#6b7280]">Rascunho</span></div></div><button class="btn outline">Publicar</button></div>
|
||||
<div class="mt-7 grid grid-cols-[300px_1fr] gap-8"><aside><div class="grid aspect-video place-items-center rounded-xl border bg-stone-100 text-center text-xs font-semibold text-[#6b7280]">Buscando a mídia<br/>no perfil oficial…</div><dl class="mt-4 space-y-2 text-xs"><div class="flex justify-between"><dt class="text-[#6b7280]">Origem</dt><dd>Instagram</dd></div><div class="flex justify-between gap-3"><dt class="text-[#6b7280]">Link</dt><dd class="truncate text-[#c51414]">instagram.com/…/reel/ABC/</dd></div></dl><div class="mt-5 rounded-lg bg-[#f4f4f5] p-3"><div class="h-2 overflow-hidden rounded-full bg-white"><div class="h-full w-1/2 rounded-full bg-[#c51414]"></div></div><p class="mt-2 text-xs text-[#6b7280]">Procurando a publicação no perfil oficial…</p></div></aside>
|
||||
<div><div class="rounded-xl border p-5"><p class="text-sm font-semibold">Processamento da peça</p><ol class="mt-4 grid grid-cols-3 gap-3 text-xs"><li class="rounded-lg border border-green-200 bg-green-50 p-3"><b>1. Link recebido</b><p class="mt-1 text-green-800">Concluído</p></li><li class="rounded-lg border border-amber-200 bg-amber-50 p-3"><b>2. Mídia oficial</b><p class="mt-1 text-amber-900">Em andamento</p></li><li class="rounded-lg border bg-[#f4f4f5] p-3 text-[#6b7280]"><b>3. Catalogação</b><p class="mt-1">Aguardando</p></li></ol></div><div class="mt-6 grid grid-cols-2 gap-4"><div><p class="label">Título</p><div class="field mt-1 text-[#9a9692]">Disponível após a catalogação</div></div><div><p class="label">Tipo</p><div class="field mt-1 text-[#9a9692]">—</div></div><div class="col-span-2"><p class="label">Transcrição / texto</p><div class="mt-1 h-36 rounded-md border bg-[#fafafa]"></div></div></div></div>
|
||||
</div>
|
||||
<div class="mt-8 border-t pt-8"><div class="flex items-center gap-3"><span class="badge bg-green-100 text-green-800">Pronto</span><b class="text-sm">Estado final — mídia extraída</b></div><div class="mt-4 grid grid-cols-[300px_1fr] gap-8"><div><div class="grid aspect-video place-items-center rounded-xl bg-stone-200 text-[11px] font-bold text-stone-500">NEEDS ASSET · PREVIEW REAL</div><button class="btn outline mt-3 w-full">↓ Baixar arquivo</button></div><div class="rounded-xl border border-green-200 bg-green-50 p-5"><h3 class="font-semibold text-green-900">Arquivo e transcrição prontos</h3><p class="mt-1 text-sm leading-6 text-green-900/80">A mídia oficial foi baixada e a ficha foi catalogada. Revise os campos antes de publicar.</p><div class="mt-4 rounded-md border border-green-200 bg-white p-3 text-sm">“Transcrição gerada aparece aqui para revisão editorial.”</div><button class="btn primary mt-4">Salvar alterações</button></div></div></div>
|
||||
</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section><div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6b7280]"><span>CENA 02</span><h2>Peça-link · motivo honesto e caminho para anexar o original</h2></div>
|
||||
<div class="desktop frame mx-auto rounded-xl bg-white p-8"><div class="flex items-start justify-between"><div><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><h2 class="mt-2 text-xl font-semibold">Peça adicionada pelo Instagram</h2><div class="mt-2 flex gap-2"><span class="badge bg-green-100 text-green-800">Pronto</span><span class="badge bg-[#f4f4f5] text-[#6b7280]">Rascunho</span></div></div><button class="btn outline">Publicar</button></div>
|
||||
<div class="mt-7 grid grid-cols-[300px_1fr] gap-8"><aside><div class="grid aspect-video place-items-center rounded-xl border bg-stone-100 text-xs font-semibold text-[#6b7280]">Peça-link</div><div class="mt-5 rounded-lg border border-amber-200 bg-amber-50 p-4"><p class="text-xs font-semibold text-amber-950">A peça continua disponível pelo link</p><p class="mt-1 text-xs leading-5 text-amber-900">A mídia não foi baixada. Você pode revisar a ficha ou anexar o arquivo original.</p><button class="btn outline mt-3 w-full">⌕ Anexar arquivo original</button></div></aside>
|
||||
<div><h3 class="text-sm font-semibold">Motivo da peça-link</h3><p class="mt-1 text-xs text-[#6b7280]">A ficha mostra um destes quatro motivos, sem código de erro nem jargão técnico.</p><div class="mt-4 grid grid-cols-2 gap-3 text-sm"><div class="rounded-lg border p-4"><span class="badge bg-amber-100 text-amber-900">Motivo</span><p class="mt-2 font-medium">Link não encontrado entre as mídias recentes do perfil</p></div><div class="rounded-lg border p-4"><span class="badge bg-amber-100 text-amber-900">Motivo</span><p class="mt-2 font-medium">Carrossel: sem arquivo único para baixar</p></div><div class="rounded-lg border p-4"><span class="badge bg-amber-100 text-amber-900">Motivo</span><p class="mt-2 font-medium">Instagram indisponível no momento</p></div><div class="rounded-lg border p-4"><span class="badge bg-amber-100 text-amber-900">Motivo</span><p class="mt-2 font-medium">Sem credencial do Instagram configurada</p></div></div><div class="mt-5 rounded-lg bg-[#f4f4f5] p-4 text-xs leading-5 text-[#6b7280]">Mídia de terceiro nunca é baixada. Esta peça não foi apagada e continua circulando pelo link.</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section><div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6b7280]"><span>CENA 03</span><h2>Mobile 390 · estados essenciais na ficha e lista compacta</h2></div>
|
||||
<div class="flex flex-wrap justify-center gap-8">
|
||||
<div class="phone frame min-h-[780px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between border-b px-4"><b>Central de Conteúdos</b><span>☰</span></header><div class="p-4"><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><h2 class="mt-2 text-lg font-semibold">Peça adicionada pelo Instagram</h2><div class="mt-2 flex gap-2"><span class="badge bg-amber-100 text-amber-900">Processando</span><span class="badge bg-[#f4f4f5] text-[#6b7280]">Rascunho</span></div><div class="mt-5 grid aspect-video place-items-center rounded-xl border bg-stone-100 text-xs text-[#6b7280]">Buscando mídia oficial…</div><div class="mt-4 rounded-lg bg-[#f4f4f5] p-3"><div class="h-2 rounded-full bg-white"><div class="h-full w-1/2 rounded-full bg-[#c51414]"></div></div><p class="mt-2 text-xs text-[#6b7280]">Procurando a publicação no perfil oficial…</p></div><div class="mt-5 space-y-3"><div class="h-11 rounded-md border"></div><div class="h-24 rounded-md border"></div></div></div></div>
|
||||
<div class="phone frame min-h-[780px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between border-b px-4"><b>Central de Conteúdos</b><span>☰</span></header><div class="p-4"><a class="text-xs font-semibold text-[#c51414]">← Conteúdos</a><h2 class="mt-2 text-lg font-semibold">Peça adicionada pelo Instagram</h2><div class="mt-2 flex gap-2"><span class="badge bg-green-100 text-green-800">Pronto</span><span class="badge bg-[#f4f4f5] text-[#6b7280]">Rascunho</span></div><div class="mt-5 grid aspect-video place-items-center rounded-xl border bg-stone-100 text-xs text-[#6b7280]">Peça-link</div><div class="mt-4 rounded-lg border border-amber-200 bg-amber-50 p-4"><p class="text-xs font-semibold text-amber-950">Por que o arquivo não foi baixado</p><p class="mt-2 text-sm font-medium text-amber-950">Carrossel: sem arquivo único para baixar</p><p class="mt-2 text-xs leading-5 text-amber-900">A peça continua disponível pelo link.</p><button class="btn outline mt-4 w-full">⌕ Anexar arquivo original</button></div><button class="btn primary mt-6 w-full">Salvar alterações</button></div></div>
|
||||
<div class="phone frame min-h-[560px] overflow-hidden bg-white"><header class="flex h-14 items-center justify-between border-b px-4"><b>Conteúdos</b><span>☰</span></header><div class="space-y-3 p-4"><article class="rounded-xl border p-4"><div class="flex justify-between gap-3"><b class="text-sm">Peça adicionada pelo Instagram</b><span class="badge shrink-0 bg-amber-100 text-amber-900">Processando</span></div><p class="mt-2 text-xs text-[#6b7280]">Instagram · Preparando a peça…</p><div class="mt-3 h-2 rounded-full bg-[#f4f4f5]"><div class="h-full w-1/2 rounded-full bg-[#c51414]"></div></div><button class="btn outline mt-3 w-full">Abrir</button></article><article class="rounded-xl border p-4"><div class="flex justify-between gap-3"><b class="text-sm">Peça adicionada pelo Instagram</b><span class="badge shrink-0 bg-green-100 text-green-800">Pronto</span></div><p class="mt-2 text-xs text-[#6b7280]">Instagram · Peça-link</p><button class="btn outline mt-3 w-full">Abrir</button></article><p class="px-2 text-center text-[11px] leading-4 text-[#6b7280]">Recomendação: a lista continua limpa; o motivo completo vive na ficha.</p></div></div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
112
docs/plans/central-conteudos-link-instagram.md
Normal file
112
docs/plans/central-conteudos-link-instagram.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# C215 — Central de Conteúdos — link do Instagram do deputado baixa e cataloga a peça
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-23
|
||||
Issue: #1302
|
||||
Priority: P1
|
||||
Impeccable: B — encaixe na lista/ficha existentes do C211 (estado honesto), sem tela nova
|
||||
Design UI: docs/plans/central-conteudos-link-instagram-ui-design.html
|
||||
Appetite: ~1,5–2 dias eng; um outcome verificável — link do próprio perfil deixa de degradar em silêncio
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
A assessoria de comunicação colou na Central de Conteúdos (`/campanha/comunicacao/conteudos`) o link de uma peça do **próprio** Instagram do deputado e a peça não foi baixada nem analisada: virou uma "peça-link" em silêncio. A promessa do fluxo — decidida no gate e registrada no C212 — é que peça adicionada por link tenha a mídia extraída e catalogada quando houver caminho oficial. O caminho oficial existe (Graph API da própria conta) e o pipeline existe; o que faltou foi o link do próprio perfil ser encontrado e resolvido. Este item conserta essa quebra.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** assessoria de comunicação (`communicator`) na mesa, operando a Central, colando links das peças do perfil oficial (@depjorgesolla) que acabaram de sair.
|
||||
- **Job principal:** colar o link de uma peça do próprio Instagram e receber a peça baixada, transcrita e catalogada — como se tivesse enviado o arquivo.
|
||||
- **Fluxo desejado:** cola o link → a peça nasce "Processando" → o post é procurado no perfil oficial → achou e é extraível: arquivo baixado, transcrito e catalogado → não achou/não extraível: peça-link **com motivo honesto na ficha** → assessoria revisa/edita ou anexa o arquivo; nada é apagado.
|
||||
- **Anti-goals de produto:** não vira varredura automática do perfil; não vira tela nova nem segundo fluxo de configuração; não vira scraping/contorno; não baixa mídia de terceiro; não apaga peça-link; não encosta no board da home.
|
||||
|
||||
### Esboço de fluxo (B)
|
||||
|
||||
```text
|
||||
[Central] → "Adicionar por link" → cola link do próprio perfil
|
||||
(ex.: instagram.com/depjorgesolla/reel/ABC/ · .../reel/ABC/?igsh=… · .../p/ABC/)
|
||||
→ peça "Processando" → busca o post no perfil oficial (além das 50 mais recentes)
|
||||
→ achou + extraível: baixa o arquivo → transcreve → cataloga (igual ao envio por arquivo)
|
||||
→ não achou / não extraível: peça-link com motivo na ficha
|
||||
("Link não encontrado…" · "Carrossel…" · "Instagram indisponível…" · "Sem credencial…")
|
||||
→ revisa, edita, anexa o arquivo se quiser — a peça nunca é apagada
|
||||
[outcome: link do próprio perfil vira peça baixada e catalogada — ou falha com motivo, nunca em silêncio]
|
||||
```
|
||||
|
||||
### Design UI (B)
|
||||
|
||||
- Design UI (gate): `docs/plans/central-conteudos-link-instagram-ui-design.html`
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- Colar um link do próprio perfil — nas formas que o browser copia — resulta em peça com mídia baixada, transcrita e catalogada, igual ao envio por arquivo.
|
||||
- A busca pelo post colado não para na janela atual: vai para trás o suficiente para o uso real, com limite declarado; post além do limite recebe motivo honesto (não silêncio).
|
||||
- Quando a extração não acontecer, a ficha mostra o motivo em linguagem de produto (vocabulário literal abaixo). Peça-link é resultado legítimo, não "Falhou".
|
||||
- Peça-link continua fallback: circula pelo link, o arquivo original pode ser anexado e a peça nunca é apagada.
|
||||
- Curadoria preservada: campos que a assessoria editou não são sobrescritos pela catalogação.
|
||||
- **Guardrails:** extração só por caminho oficial (Graph API da própria conta) — nunca scraping/contorno; mídia de terceiro nunca é baixada; token nunca em log; o contrato do feed/board da home (cache de 5 min, snapshot, kill switch) não é reusado nem alterado; YouTube segue link-only por desenho (a Data API não entrega arquivo) — sem motivo de falha.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — não há agregado nem KPI; o que muda é o estado da peça e o motivo visível na ficha.
|
||||
- **Decisões desbloqueadas:** N/A — a decisão da assessoria é editorial/operacional ("anexar o arquivo original?"), não numérica.
|
||||
- **Forma:** N/A — restrição: motivo em linguagem de produto, sem código de erro, stack ou jargão de API.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- **Decisão do gate (C212, verbatim):** "Quando o assessor adiciona uma peça por link do Instagram ou Youtube, a mídia deve ser automaticamente extraída e catalogada." — com o corte do C211: **quando houver caminho oficial**.
|
||||
- **Motivos (verbatim):** "Link não encontrado entre as mídias recentes do perfil" · "Carrossel: sem arquivo único para baixar" · "Instagram indisponível no momento" · "Sem credencial do Instagram configurada".
|
||||
- **Formas de link aceitas:** `instagram.com` com `p|reel|reels|tv` + shortcode, com ou sem `www.`/`m.`, query ignorada (`?igsh=` ok) e **caminho prefixado pelo perfil** (`/depjorgesolla/reel/<shortcode>/`, `/depjorgesolla/p/<shortcode>/`); rejeitar `/stories/`, `instagr.am` e hosts fora de Instagram/YouTube (como hoje).
|
||||
- **Fallback:** peça-link permanece, com aviso na ficha; "Mídia de terceiro nunca é baixada"; o arquivo original pode ser anexado pela assessoria; a peça nunca é apagada.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** resolução do link `src/utilities/content/contentPieceLink.ts`; job `src/utilities/content/contentPieceJob.ts`; parse `src/lib/contentPiece.ts`; feed `src/utilities/socialFeed/instagramFeed.ts`; action `src/app/(campaign)/campanha/actions/contentPieces.ts`; lista/ficha em `src/components/campaign/content/` e `.../comunicacao/conteudos/[id]/page.tsx`.
|
||||
- **Fatos verificados (a revalidar):** hoje degradam para peça-link sem erro nem motivo — origem ≠ Instagram, parse falho, credencial ausente, `loadInstagramFeed` lançando, post fora da janela de 50, carrossel/sem `mediaUrl`; o job termina "Pronto" (`contentPieceJob.ts:278`). O parse rejeita caminho prefixado pelo perfil (`src/lib/contentPiece.ts:352-407`). Não há paginação no repo (`INSTAGRAM_MAX_RESULTS_CAP=50`). Falha depois de um match/download já vira "Falhou" com mensagem.
|
||||
- **Precedente a olhar:** `docs/plans/central-conteudos-varredura-instagram.md` (C212 §Q1/Q2/Q4 — limites e regra de terceiro) e `downloadSource` (`src/utilities/speech/speechMediaPipeline.ts`) como download remoto→mídia.
|
||||
- **Risco de acoplamento:** não reusar o caminho do sync do board (lock transacional do hook, snapshot, kill switch, cache de 5 min); o `sourceUrl` canônico é a identidade (não criar peça gêmea); `curatedFields` da assessoria não podem ser sobrescritos; nada de import que feche ciclo.
|
||||
|
||||
## Dependências
|
||||
|
||||
- **Dura: C211 (#1254)** — o fluxo de link, a ficha e o pipeline existem; este item corrige o comportamento (defeito).
|
||||
- **Soft: C212 (#1256, entregue)** — os achados (janela de 50 sem paginação, `media_url`, regra de terceiro) são a base da decisão.
|
||||
- Credencial do Instagram já governada pelo `SocialFeedSettings` (admin-only) — a ausência dela vira motivo honesto, não tela nova.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Varredura agendada do perfil (webhook + reconciliação + cursor próprio) — recomendação do C212 §Q4; vira item próprio se produto quiser.
|
||||
- oEmbed/embed de terceiro (C211-FOLLOWUP-OEMBED, #1263) e download/persistência de mídia de terceiro (permanente).
|
||||
- Backfill/reprocessamento em massa de peças-link antigas — item próprio, se produto quiser; "anexar arquivo" segue como caminho.
|
||||
- Montar carrossel/álbum a partir dos filhos; redesenhar feed/board da home; nova tela ou novo estado de sync.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Já que vai paginar, varre o perfil inteiro".** Se alguém "só completar": webhook, agendador, cursor e painel de status. **Corte neste item:** só o link colado é procurado; a varredura é outro item (C212 §Q4).
|
||||
- **"A API não achou → scraping/yt-dlp".** Se alguém "só completar": crawler e download de terceiro. **Corte:** nunca; o resultado é motivo honesto + anexar arquivo.
|
||||
- **"Carrossel vira álbum".** Se alguém "só completar": baixar cada filho, montar álbum, inventar capa. **Corte:** carrossel fica peça-link com motivo.
|
||||
- **"Reprocessar todo o acervo".** Se alguém "só completar": job em massa sobre peças-link antigas. **Corte:** o fix vale para colagens novas; o resto é item próprio.
|
||||
- **"Consertar o token/tela de config".** Se alguém "só completar": novo painel de credencial. **Corte:** `SocialFeedSettings` já é o dono; falta de credencial é motivo na ficha.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Até onde a busca pelo post deve ir para trás?** **Opções:** A) paginação limitada (tudo dentro de uma janela declarada) | B) só as N mais recentes | C) só a janela atual (50). **Recomendação:** A, com motivo honesto quando o post estiver além da janela. _(assumido — validar com produto)_
|
||||
- **O que o operador vê quando a extração falha?** **Opções:** A) motivo só na ficha | B) motivo na ficha + selo na lista. **Recomendação:** A — a lista mantém o estado atual (evita ruído novo); o detalhe é onde a decisão acontece. _(assumido — validar com produto)_
|
||||
- **Aceitar também links prefixados pelo perfil e outras grafias?** **Opções:** A) sim, as grafias que o copiar-e-colar do browser produz | B) só a forma canônica atual. **Recomendação:** A — nunca aceitar stories/terceiros; o que muda é só a grafia do próprio post. _(assumido — validar com produto)_
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue — a registrar com `pnpm agent:register`.
|
||||
- Design UI (gate): `docs/plans/central-conteudos-link-instagram-ui-design.html` (+ assets em `central-conteudos-link-instagram-ui-design-assets/`)
|
||||
- Planos irmãos: `docs/plans/central-conteudos-ingestao.md` (C211) · `docs/plans/central-conteudos-varredura-instagram.md` (C212)
|
||||
- Arquivos-pista: `src/utilities/content/contentPieceLink.ts` · `src/utilities/content/contentPieceJob.ts` · `src/lib/contentPiece.ts` · `src/utilities/socialFeed/instagramFeed.ts` · `src/app/(campaign)/campanha/actions/contentPieces.ts` · `src/components/campaign/content/AddContentPieceLinkDialog.tsx` · `src/components/campaign/content/ContentPieceCardList.tsx` · `src/app/(campaign)/campanha/(app)/comunicacao/conteudos/[id]/page.tsx`
|
||||
- `AGENTS.md` — guardrails de campanha (sem scraping, sem credencial em log) e convenções de UI/nav
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
1. Fatia = um outcome verificável? **Sim** — link do próprio perfil deixa de degradar em silêncio (baixa e cataloga, ou explica).
|
||||
2. Appetite declarado e a intenção cabe? **Sim** (~1,5–2 dias; varredura, backfill e scraping cortados).
|
||||
3. Persona + job + aceite claros sem jargão de stack? **Sim**.
|
||||
4. Direção no codebase é hipótese? **Sim** — áreas e fatos como pista, sem contrato técnico.
|
||||
5. Zero decisões duras de engenharia no plano? **Sim** — paginação, armazenamento do motivo e shape ficam no plano de implementação.
|
||||
|
||||
**Score: 5/5.**
|
||||
88
docs/plans/central-conteudos-secao-home-ui-design.html
Normal file
88
docs/plans/central-conteudos-secao-home-ui-design.html
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR" data-theme="campaign-site">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<title>Design — S36 · Central local na home</title>
|
||||
<style type="text/tailwindcss">
|
||||
@theme { --font-sans: Arimo, Arial, sans-serif; }
|
||||
:root { --red:#a21c1c;--dark:#47130e;--yellow:#ffe607;--cream:#fff8f2;--band:#ebe9e9;--surface:#f9faff;--muted:#6c615e;--line:rgb(0 0 0/.12);--display:'Exo 2','Arial Black',sans-serif; }
|
||||
*{box-sizing:border-box}.display{font-family:var(--display)}
|
||||
.board{background:#dedbd8;background-image:radial-gradient(rgb(24 78 146/.09) .7px,transparent .7px);background-size:18px 18px}
|
||||
.frame{box-shadow:0 22px 60px rgb(39 25 22/.13)}.desktop{width:1280px}.phone{width:390px;border-radius:28px}.scene:after{content:'';height:1px;flex:1;background:#c6c1bd}
|
||||
.preview{overflow:hidden;border:1px solid var(--line);border-radius:14px;background:#fff;box-shadow:0 8px 24px rgb(71 19 14/.07)}
|
||||
.asset{position:relative;display:grid;place-items:center;background:linear-gradient(135deg,#e6e2df,#f7f5f3);color:#77706c;text-align:center;font-size:10px;font-weight:800;letter-spacing:.04em}
|
||||
.tag{display:inline-flex;align-items:center;border-radius:999px;background:#eef4fb;padding:4px 8px;color:#184e92;font-size:11px;font-weight:800}.local{background:#fff3c4;color:#6b5100}
|
||||
.cta{display:inline-flex;min-height:48px;align-items:center;justify-content:center;gap:8px;border-radius:10px;background:#ffe607;padding:10px 18px;color:#171000;font-family:var(--display);font-size:14px;font-weight:900;box-shadow:0 4px 0 #cfb900}
|
||||
.secondary{display:inline-flex;min-height:36px;align-items:center;gap:6px;border-radius:8px;padding:6px 8px;color:#a21c1c;font-size:12px;font-weight:800;text-decoration:underline;text-underline-offset:4px}
|
||||
.surround{border-bottom:1px solid var(--line);padding:26px 40px;text-align:center}.eyebrow{font-size:12px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;color:#a21c1c}
|
||||
.skeleton{background:linear-gradient(100deg,#eee 20%,#ddd 38%,#eee 56%);background-size:220% 100%}
|
||||
</style>
|
||||
</head>
|
||||
<body class="board min-h-screen text-black antialiased">
|
||||
<main class="mx-auto max-w-[1480px] space-y-14 px-4 py-12 md:px-8">
|
||||
<header class="max-w-3xl">
|
||||
<span class="rounded-full bg-[#e4102f] px-3 py-1 text-xs font-bold text-white">S36 · revisão do gate</span>
|
||||
<h1 class="display mt-4 text-4xl font-black">A peça do lugar da pessoa vem primeiro.</h1>
|
||||
<p class="mt-2 text-sm leading-6 text-[#6c615e]">Até três peças: município → região → recentes. Sem localização, a seção simplesmente mostra recentes — sem erro, prompt surpresa ou espera eterna.</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 01</span><h2>Localizada · desktop 1280 · município, região e complemento recente</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white">
|
||||
<div class="surround bg-[#fff8f2]"><p class="eyebrow">Faça parte</p><h3 class="display mt-1 text-2xl font-black">Mostre que você está com Solla</h3><div class="mx-auto mt-4 grid max-w-3xl grid-cols-6 gap-3"><div class="h-20 rounded-lg bg-[#ebe9e9]"></div><div class="h-20 rounded-lg bg-[#ebe9e9]"></div><div class="h-20 rounded-lg bg-[#ebe9e9]"></div><div class="h-20 rounded-lg bg-[#ebe9e9]"></div><div class="h-20 rounded-lg bg-[#ebe9e9]"></div><div class="h-20 rounded-lg bg-[#ebe9e9]"></div></div><p class="mt-3 text-[11px] font-bold text-[#6c615e]">SEÇÃO EXISTENTE · CARDS PERSONALIZÁVEIS</p></div>
|
||||
<section class="relative overflow-hidden border-b border-black/10 bg-white px-10 py-16"><div class="absolute -top-24 -right-20 size-64 rounded-full bg-[#ffe607]/35"></div><div class="absolute -bottom-28 -left-24 size-64 rounded-full bg-[#e4102f]/8"></div><div class="relative mx-auto max-w-[1080px]">
|
||||
<div class="mx-auto max-w-2xl text-center"><p class="eyebrow">Central de Conteúdos</p><h2 class="display mt-2 text-4xl font-black tracking-tight">Peça voto pra Solla 1313</h2><p class="mx-auto mt-3 max-w-xl text-base leading-6 text-[#6c615e]">Comece pelo material do seu território e mande para quem você conhece.</p><div class="mt-3 flex items-center justify-center gap-2"><span class="tag local">⌖ Para seu município</span><span class="text-[11px] text-[#6c615e]">Localização usada só nesta visita</span></div></div>
|
||||
<div class="mt-9 grid grid-cols-3 gap-6">
|
||||
<article class="preview"><div class="asset aspect-video">NEEDS ASSET · FOTO REAL</div><div class="p-4"><div class="flex flex-wrap gap-1"><span class="tag">Foto</span><span class="tag local">Do seu município</span></div><h3 class="mt-2 font-extrabold">Título da peça local</h3><p class="mt-1 text-xs text-[#6c615e]">Seu município · Tema</p><a class="mt-4 inline-block text-xs font-bold text-[#a21c1c]">Ver esta peça →</a></div></article>
|
||||
<article class="preview"><div class="asset relative aspect-video"><span>NEEDS ASSET · POSTER REAL</span><span class="absolute grid size-12 place-items-center rounded-full bg-[#ffe607] text-xl text-black shadow">▶</span><span class="absolute right-3 bottom-3 rounded bg-black/70 px-2 py-1 text-[10px] text-white">Tocar para carregar</span></div><div class="p-4"><div class="flex flex-wrap gap-1"><span class="tag">Vídeo</span><span class="tag local">Da sua região</span></div><h3 class="mt-2 font-extrabold">Título da peça regional</h3><p class="mt-1 text-xs text-[#6c615e]">Sua região · sem autoplay</p><a class="mt-4 inline-block text-xs font-bold text-[#a21c1c]">Ver esta peça →</a></div></article>
|
||||
<article class="preview"><div class="asset relative aspect-video"><span>NEEDS ASSET · CAPA REAL</span><span class="absolute grid size-12 place-items-center rounded-full bg-[#ffe607] text-xl text-black shadow">▶</span></div><div class="p-4"><div class="flex flex-wrap gap-1"><span class="tag">Áudio</span><span class="tag">Mais recente</span></div><h3 class="mt-2 font-extrabold">Mensagem recente para compartilhar</h3><p class="mt-1 text-xs text-[#6c615e]">Completa a seleção local</p><a class="mt-4 inline-block text-xs font-bold text-[#a21c1c]">Ver esta peça →</a></div></article>
|
||||
</div>
|
||||
<div class="mt-9 text-center"><a class="cta" href="/conteudos">Ver todas as peças →</a><p class="mt-3 text-xs text-[#6c615e]">Nenhum card personalizável entra nesta amostra.</p></div>
|
||||
</div></section>
|
||||
<div class="surround bg-[#ebe9e9]"><p class="eyebrow">Apoie e acompanhe</p><h3 class="display mt-1 text-2xl font-black">Receba as novidades da campanha</h3><div class="mx-auto mt-5 h-20 max-w-2xl rounded-xl border bg-white"></div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 02</span><h2>Localizada · mobile 390 · recorte discreto, sem pedir GPS ao carregar</h2></div>
|
||||
<div class="phone frame mx-auto overflow-hidden bg-white"><div class="border-b bg-[#fff8f2] px-5 py-7 text-center"><p class="eyebrow text-[10px]">Faça parte</p><h3 class="display mt-1 text-xl font-black">Mostre que você está com Solla</h3><div class="mt-4 grid grid-cols-3 gap-2"><div class="h-16 rounded bg-[#ebe9e9]"></div><div class="h-16 rounded bg-[#ebe9e9]"></div><div class="h-16 rounded bg-[#ebe9e9]"></div></div></div>
|
||||
<section class="relative overflow-hidden border-b px-5 py-10"><div class="absolute -top-16 -right-20 size-48 rounded-full bg-[#ffe607]/35"></div><div class="relative text-center"><p class="eyebrow text-[10px]">Central de Conteúdos</p><h2 class="display mt-2 text-[30px] font-black leading-[1.05]">Peça voto pra<br/>Solla 1313</h2><p class="mt-3 text-sm leading-5 text-[#6c615e]">Material do seu território para compartilhar.</p><span class="tag local mt-3">⌖ Para seu município</span></div>
|
||||
<div class="relative mt-6 space-y-4"><article class="preview grid grid-cols-[124px_1fr]"><div class="asset min-h-36">NEEDS ASSET<br/>FOTO REAL</div><div class="p-4 text-left"><span class="tag local">Do seu município</span><h3 class="mt-2 text-sm font-extrabold">Título da peça local</h3><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article><article class="preview grid grid-cols-[124px_1fr]"><div class="asset relative min-h-36"><span>NEEDS ASSET<br/>POSTER REAL</span><span class="absolute grid size-10 place-items-center rounded-full bg-[#ffe607] text-black">▶</span></div><div class="p-4 text-left"><span class="tag local">Da sua região</span><h3 class="mt-2 text-sm font-extrabold">Título da peça regional</h3><p class="mt-1 text-[11px] text-[#6c615e]">Só carrega no toque</p><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article><article class="preview grid grid-cols-[124px_1fr]"><div class="asset min-h-36">NEEDS ASSET<br/>CAPA REAL</div><div class="p-4 text-left"><span class="tag">Mais recente</span><h3 class="mt-2 text-sm font-extrabold">Mensagem recente</h3><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article></div>
|
||||
<a class="cta relative mt-7 w-full" href="/conteudos">Ver todas as peças →</a><p class="relative mt-3 text-center text-[11px] leading-4 text-[#6c615e]">A localização não é guardada. Cards personalizáveis ficam na seção anterior.</p>
|
||||
</section><div class="bg-[#ebe9e9] px-5 py-8 text-center"><p class="eyebrow text-[10px]">Apoie e acompanhe</p><h3 class="display mt-1 text-xl font-black">Receba as novidades</h3><div class="mt-4 h-20 rounded-xl border bg-white"></div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 03</span><h2>Sem localização ou fora da Bahia · recentes, sem erro e sem insistência</h2></div>
|
||||
<div class="grid gap-8 lg:grid-cols-[1fr_390px]">
|
||||
<div class="frame overflow-hidden rounded-xl bg-white"><section class="relative overflow-hidden px-10 py-12"><div class="absolute -top-24 -right-20 size-64 rounded-full bg-[#ffe607]/35"></div><div class="relative"><div class="mx-auto max-w-2xl text-center"><p class="eyebrow">Central de Conteúdos</p><h2 class="display mt-2 text-4xl font-black">Peça voto pra Solla 1313</h2><p class="mt-3 text-base text-[#6c615e]">Veja as peças mais recentes e escolha uma para compartilhar.</p><span class="tag mt-3">Seleção recente</span></div><div class="mt-8 grid grid-cols-3 gap-5"><article class="preview"><div class="asset aspect-video">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="tag">Foto</span><h3 class="mt-2 font-extrabold">Peça recente</h3></div></article><article class="preview"><div class="asset aspect-video">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="tag">Vídeo</span><h3 class="mt-2 font-extrabold">Outra peça recente</h3></div></article><article class="preview"><div class="asset aspect-video">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="tag">Áudio</span><h3 class="mt-2 font-extrabold">Mensagem recente</h3></div></article></div><div class="mt-8 text-center"><a class="cta" href="/conteudos">Ver todas as peças →</a><div><button class="secondary mt-2">⌖ Usar minha localização</button></div><p class="text-[11px] text-[#6c615e]">Opcional e secundário. A seção já funciona sem isso.</p></div></div></section></div>
|
||||
<div class="phone frame overflow-hidden bg-white"><section class="relative overflow-hidden px-5 py-10 text-center"><div class="absolute -top-16 -right-20 size-48 rounded-full bg-[#ffe607]/35"></div><div class="relative"><p class="eyebrow text-[10px]">Central de Conteúdos</p><h2 class="display mt-2 text-[30px] font-black leading-[1.05]">Peça voto pra<br/>Solla 1313</h2><p class="mt-3 text-sm leading-5 text-[#6c615e]">Veja as peças mais recentes.</p><span class="tag mt-3">Seleção recente</span><article class="preview mt-6 text-left"><div class="asset aspect-video">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="tag">Foto</span><h3 class="mt-2 font-extrabold">Título da peça recente</h3><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article><a class="cta mt-6 w-full" href="/conteudos">Ver todas as peças →</a><button class="secondary mt-3">⌖ Usar minha localização</button><p class="text-[11px] leading-4 text-[#6c615e]">Opcional. Sem prompt no carregamento.</p></div></section></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 04</span><h2>Resolução da localização · transitória, não bloqueia e termina em recentes</h2></div>
|
||||
<div class="grid gap-6 lg:grid-cols-3">
|
||||
<article class="frame rounded-xl bg-white p-6"><span class="rounded-full bg-[#fff3c4] px-2 py-1 text-[10px] font-black text-[#6b5100]">INSTANTE INICIAL</span><h3 class="display mt-3 text-xl font-black">Peça voto pra Solla 1313</h3><p class="mt-2 text-sm leading-5 text-[#6c615e]">A home já está utilizável. Só esta amostra define a melhor seleção.</p><div class="mt-5 grid grid-cols-3 gap-2"><div class="skeleton aspect-video rounded-lg"></div><div class="skeleton aspect-video rounded-lg"></div><div class="skeleton aspect-video rounded-lg"></div></div><p class="mt-4 text-xs font-bold text-[#6c615e]">Sem modal, sem overlay e sem prompt automático.</p></article>
|
||||
<article class="frame rounded-xl bg-white p-6"><span class="rounded-full bg-green-100 px-2 py-1 text-[10px] font-black text-green-800">LOCALIZAÇÃO ACESSÍVEL</span><h3 class="display mt-3 text-xl font-black">Seleção do seu território</h3><p class="mt-2 text-sm leading-5 text-[#6c615e]">GPS já acessível; senão, recorte aproximado por IP. A interface entrega o mesmo resultado: município → região → recentes.</p><div class="mt-5 flex gap-2"><span class="tag local">Do seu município</span><span class="tag local">Da sua região</span></div><p class="mt-5 text-xs text-[#6c615e]">Nada é guardado, registrado ou usado fora desta seção.</p></article>
|
||||
<article class="frame rounded-xl bg-white p-6"><span class="rounded-full bg-[#eef4fb] px-2 py-1 text-[10px] font-black text-[#184e92]">SEM SINAL ÚTIL</span><h3 class="display mt-3 text-xl font-black">Seleção recente</h3><p class="mt-2 text-sm leading-5 text-[#6c615e]">A espera termina e as peças recentes aparecem. Nenhum erro é mostrado.</p><div class="mt-5 h-24 rounded-lg border bg-[#f9faff] p-3 text-xs text-[#6c615e]">Preview recente disponível</div><p class="mt-4 text-xs font-bold text-[#184e92]">Nunca há spinner eterno.</p></article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 05</span><h2>Uma peça publicada · sem lacunas, independentemente da localização</h2></div>
|
||||
<div class="grid gap-8 lg:grid-cols-[1fr_390px]"><div class="frame overflow-hidden rounded-xl bg-white"><section class="relative overflow-hidden px-10 py-12"><div class="absolute -top-24 -right-20 size-64 rounded-full bg-[#ffe607]/35"></div><div class="relative grid grid-cols-[1fr_360px] items-center gap-10"><div><p class="eyebrow">Central de Conteúdos</p><h2 class="display mt-2 text-4xl font-black">Peça voto pra Solla 1313</h2><p class="mt-3 max-w-lg text-base leading-6 text-[#6c615e]">Uma peça oficial já está pronta para você compartilhar.</p><a class="cta mt-6" href="/conteudos">Ver todas as peças →</a></div><article class="preview"><div class="asset aspect-video">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="tag">Foto</span><h3 class="mt-2 font-extrabold">Título da única peça publicada</h3><a class="mt-3 inline-block text-xs font-bold text-[#a21c1c]">Ver esta peça →</a></div></article></div></section></div>
|
||||
<div class="phone frame overflow-hidden bg-white"><section class="relative overflow-hidden px-5 py-10 text-center"><div class="absolute -top-16 -right-20 size-48 rounded-full bg-[#ffe607]/35"></div><div class="relative"><p class="eyebrow text-[10px]">Central de Conteúdos</p><h2 class="display mt-2 text-[30px] font-black leading-[1.05]">Peça voto pra<br/>Solla 1313</h2><p class="mt-3 text-sm leading-5 text-[#6c615e]">Uma peça oficial já está pronta.</p><article class="preview mt-6 text-left"><div class="asset aspect-video">NEEDS ASSET · PREVIEW REAL</div><div class="p-4"><span class="tag">Foto</span><h3 class="mt-2 font-extrabold">Título da única peça publicada</h3><a class="mt-3 block text-xs font-bold text-[#a21c1c]">Ver peça →</a></div></article><a class="cta mt-6 w-full" href="/conteudos">Ver todas as peças →</a></div></section></div></div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="scene mb-3 flex items-center gap-3 text-xs font-bold text-[#6c615e]"><span>CENA 06</span><h2>Zero peças · seção inteira ausente (fail-closed)</h2></div>
|
||||
<div class="desktop frame mx-auto overflow-hidden rounded-xl bg-white"><div class="surround bg-[#fff8f2]"><p class="eyebrow">Faça parte</p><h3 class="display mt-1 text-2xl font-black">Mostre que você está com Solla</h3><div class="mx-auto mt-5 h-20 max-w-3xl rounded-xl bg-[#ebe9e9]"></div></div><div class="flex h-16 items-center justify-center border-b border-dashed bg-white text-xs font-bold text-[#6c615e]">A SEÇÃO DA CENTRAL NÃO É RENDERIZADA · SEM LOCALIZAÇÃO, VAZIO OU CTA</div><div class="surround bg-[#ebe9e9]"><p class="eyebrow">Apoie e acompanhe</p><h3 class="display mt-1 text-2xl font-black">Receba as novidades da campanha</h3><div class="mx-auto mt-5 h-20 max-w-2xl rounded-xl border bg-white"></div></div></div>
|
||||
<div class="phone frame mx-auto mt-8 overflow-hidden bg-white"><div class="border-b bg-[#fff8f2] px-5 py-7 text-center"><p class="eyebrow text-[10px]">Faça parte</p><h3 class="display mt-1 text-xl font-black">Mostre que você está com Solla</h3><div class="mt-4 h-16 rounded bg-[#ebe9e9]"></div></div><div class="flex h-14 items-center justify-center border-b border-dashed text-[10px] font-bold text-[#6c615e]">CENTRAL AUSENTE</div><div class="bg-[#ebe9e9] px-5 py-8 text-center"><p class="eyebrow text-[10px]">Apoie e acompanhe</p><h3 class="display mt-1 text-xl font-black">Receba as novidades</h3><div class="mt-4 h-20 rounded-xl border bg-white"></div></div></div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
121
docs/plans/central-conteudos-secao-home.md
Normal file
121
docs/plans/central-conteudos-secao-home.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# S36 — Home — seção divulgando a Central de Conteúdos
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-23
|
||||
Issue: #1305
|
||||
Priority: P1
|
||||
Impeccable: C — seção nova na home pública (superfície nova dentro de página existente)
|
||||
Design UI: docs/plans/central-conteudos-secao-home-ui-design.html
|
||||
Appetite: ~2–3 dias eng; um outcome verificável (a home leva à Central com peças do território do visitante; a seção some quando não há peça publicada)
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
A Central de Conteúdos (`/conteudos`, S27) está no ar com as peças "Peça voto pra Solla 1313", mas quem chega na home — o lugar mais visitado do site — só a descobre pelo link condicional do rodapé e pelo selo local da própria peça. Na reta final até 04/10, a home precisa empurrar o eleitor para a Central: uma seção curta que mostre peças do **território do visitante** (para ele se reconhecer e repassar) e o leve para lá. A localização é resolvida pelo próprio visitante — GPS quando acessível, senão IP —, sem guardar nada.
|
||||
|
||||
Esta seção **supersede a decisão D7 do S27** ("Descoberta (rodapé + selo; sem seção nova)", `docs/plans/central-conteudos-publica-impl.md:87-91`), que rejeitou a seção nova na home por estar fora do escopo daquele item. A reabertura é decisão de produto do dono (pedido do operador); o rodapé e o selo local do S27 permanecem como estão — este item só acrescenta a seção.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** eleitor/simpatizante que abre jorgesolla1313.com.br no celular (link no WhatsApp, busca, indicação) e quer ajudar, mas não sabe onde pegar material nem o que escrever; o que o convence é ver o material do lugar dele.
|
||||
- **Job principal:** descobrir que existe uma Central de peças oficiais de voto, reconhecer o material do seu território e chegar nela em um toque.
|
||||
- **Fluxo desejado:** rola a home → a seção resolve a localização (GPS se acessível, senão IP; sem localização, segue) → vê até 3 peças publicadas do seu município (completando com a região e, se faltar, recentes) → toca numa peça ou no CTA "Ver todas as peças" → cai em `/conteudos` → baixa/compartilha dali (fluxo do S27).
|
||||
- **Anti-goals de produto:** não é uma segunda Central nem catálogo paralelo (quem cataloga é o interno, C211); não duplica a seção S3 "Acompanhe de perto" (feed de redes/artigos) nem a seção de cards logo acima — **cards personalizáveis nunca são amostra**; não captura dado, não pede login, não guarda/loga a localização e não adiciona rastreio (analytics é C213); não re-hospeda mídia; não autoplaya áudio/vídeo; não redesenha a home.
|
||||
|
||||
### Esboço de fluxo (C)
|
||||
|
||||
```text
|
||||
[visitante na home] → a seção resolve a localização
|
||||
(GPS se acessível · senão IP no servidor · senão desconhecida — nunca guarda nem loga)
|
||||
→ até 3 peças publicadas do município do visitante
|
||||
(sem peça local: completa com a região; ainda faltando: recentes; sem localização: recentes)
|
||||
→ nunca cards personalizáveis como amostra (a seção anterior da home já os mostra)
|
||||
→ toca numa peça (mídia só no toque) ou no CTA "Ver todas as peças" → /conteudos
|
||||
[zero peças publicadas] → a seção inteira some (fail-closed)
|
||||
[localização indisponível/fora da Bahia] → recentes, sem erro e sem prompt insistente
|
||||
```
|
||||
|
||||
### Design UI (C)
|
||||
|
||||
- Design UI (gate): `docs/plans/central-conteudos-secao-home-ui-design.html` — cenas mobile/desktop da seção na home: peças do território, fallback sem localização, uma peça só, zero peças (seção ausente) e o estado de resolução da localização (sem spinner eterno). Revisão do gate: a primeira versão não tinha seleção por localização nem excluía os cards.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- A home pública ganha uma seção dedicada à Central, visível só quando há peça publicada: sem peça, a seção não existe na página (fail-closed a zero, mesma condição do link do rodapé hoje).
|
||||
- **Amostra por território do visitante:** a seção mostra até 3 peças publicadas do município do visitante; se não houver peças locais suficientes, completa com a região e, ainda faltando, com as mais recentes; sem localização ou fora da Bahia, mostra as mais recentes.
|
||||
- **Localização sem rastro:** GPS só quando acessível (permissão já concedida ou affordance explícita — ver questão (a)); senão IP resolvido no servidor; **nunca persistir, logar ou setar cookie** com a localização ou o IP; nada de PII.
|
||||
- **Cards personalizáveis nunca são amostra:** a seção anterior da home (`CampaignCardsSection`) já os mostra; peças publicadas de qualquer tipo (inclusive tipo card de arquivo) podem ser amostra.
|
||||
- A seção leva à Central: CTA principal para `/conteudos` e prévia leve das peças (foto) ou só chamada de play (vídeo/áudio) — nada carrega sozinho.
|
||||
- Kill switch instantâneo: despublicar uma peça reflete na seção sem deploy (mesmo contrato de cache/tag do catálogo, `contentPieces`).
|
||||
- Sem autoplay, sem mídia pesada na abertura da home (contrato do S27); seção distinta do S3 e da seção de cards; sem rastreio novo; demais seções da home intocadas.
|
||||
- **A seção é por visitante** (localização): não pode ser servida no mesmo HTML estático compartilhado do resto da home — o executor decide o mecanismo (resolver no cliente após a localização, ou render no servidor por IP), mantendo o resto da home como está.
|
||||
- Celular primeiro: sem overflow horizontal (o e2e da home mede), usável em conexão ruim; nenhuma espera bloqueia o resto da home (a seção pode aparecer depois).
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Dados: N/A** — a seção é superfície de descoberta; nenhum número, contador ou ranking. **Decisões desbloqueadas:** o visitante decide entrar na Central (e o que pegar lá); a comunicação decide o que publicar/despublicar. Nenhum dado do visitante é coletado ou guardado.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- Item `S36`; slug `central-conteudos-secao-home`; tipo `feature`; Priority `P1`; Impeccable `C`.
|
||||
- Condição da seção: **sem peça publicada → a seção inteira não aparece** (mesma condição do link "Conteúdos" no rodapé, hoje via `hasPublishedContentPieces`).
|
||||
- CTA principal: `Ver todas as peças` → `/conteudos`.
|
||||
- Conteúdo: **até 3 peças publicadas**, na ordem de seleção **município do visitante → região → mais recentes**; sem localização/fora da Bahia → mais recentes.
|
||||
- Exclusão literal: **cards personalizáveis (os itens sintéticos dos 6 modelos) nunca entram como amostra** — a seção logo acima (`CampaignCardsSection`) já os mostra.
|
||||
- Localização: GPS só se acessível (permissão já concedida ou affordance explícita); senão IP no servidor; **proibido persistir/logar/cookiar** localização ou IP; fora da Bahia ou indisponível → recentes.
|
||||
- Sinal de IP: a viabilidade de resolver **município** pelo IP no deploy (headers do túnel Cloudflare e/ou fonte de geo-IP) é **a confirmar na implementação** — nunca estimada; se só resolver país/estado, a seleção degrada para região/recentes.
|
||||
- Convenção das seções irmãs da home: `data-home-section` — valores existentes `hero`, `proof`, `contents`, `problem`, `flags`, `story`, `sound`, `cards`, `newsletter`; a seção nova segue a convenção (valor definido no plano de implementação).
|
||||
- Cache/kill switch: mesma tag de listagem do catálogo (`contentPieces`), revalidada no publish/unpublish; a seleção por localização não entra no cache compartilhado.
|
||||
- **Supersessão:** D7 do S27 (`docs/plans/central-conteudos-publica-impl.md:87-91`), opção A (rodapé + selo; sem seção nova), rejeitava a opção B (seção nova na home). Este item reabre e adota a seção nova; rodapé e selo local do S27 permanecem.
|
||||
- Escopo do S27 intocado: filtros, busca, páginas de peça, share e mensagens de voto continuam como entregues.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** a home compõe seções hardcoded em `src/app/(frontend)/(home)/page.tsx:127-251`; a seção nova é um componente no molde de `JingleHomeSection` (`data-home-section="sound"`, "Ver todos" → `/jingles`) e `CampaignCardsSection` (`data-home-section="cards"`); a seleção local usa as facetas já existentes da peça (município/região, `src/lib/contentPieceCatalog.ts`) sobre a leitura pública cacheada (`src/utilities/content/contentPieceReads.ts`).
|
||||
- **Precedentes de localização a olhar:** `src/lib/municipalityProximity.ts` (ponto → município/ZE, fora da Bahia, mais próximo — puro e testado), `src/utilities/campaignGeolocation.ts` e `src/components/campaign/shared/useNearestMunicipalitySlug.ts` / `NearestMunicipalityCard.tsx` (B14, geolocalização no dashboard staff — atenção: lá resolve só entre os municípios do portfólio; aqui o universo é o catálogo inteiro), e a extração de IP do túnel em `src/utilities/content/contentEventRateLimit.ts:33-37` / `src/utilities/ai/themeSearchGuard.ts:22` (`cf-connecting-ip` → `x-forwarded-for` → `x-real-ip`).
|
||||
- **Descoberta hoje:** link condicional no rodapé (`CampaignFooter.tsx:34-37,65-67`) + selo local (`ContentPiecePageHeader.tsx:31-33`); `SiteHeader.tsx` não tem link.
|
||||
- **Risco de acoplamento:** a home é estática/cacheada — a seção por visitante não pode contaminar o cache compartilhado nem virar leitura crua pesada; não editar as seções irmãs, `/conteudos` nem o rodapé; o e2e da home mede overflow horizontal; não acoplar ao #44 PUB2 (editabilidade da home é issue separada).
|
||||
|
||||
## Dependências
|
||||
|
||||
- **C211** (peças catalogadas e publicadas) — dura, indireta: sem peça publicada a seção some (fail-closed).
|
||||
- S27 (`/conteudos` no ar) — dura: o CTA precisa do destino.
|
||||
- B14 (mecânica de geolocalização/proximidade) — soft: precedente a reusar, não dependência de entrega.
|
||||
- Design hi-fi aprovado no gate.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Cards personalizáveis como amostra (a seção anterior os mostra) e mudanças na `CampaignCardsSection`.
|
||||
- Guardar/logar/cookiar a localização ou o IP; analytics/UTM (C213); login/captura/PII; novo Consent.
|
||||
- Editabilidade/toggles/ordem das seções da home (#44 PUB2); mudar o rodapé, o selo local, o `SiteHeader` ou a própria `/conteudos`.
|
||||
- Redesign de qualquer outra seção da home (S3 incluída) e personalização do resto da home por localização.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Já que tem localização, personaliza a home inteira".** Se alguém "só completar": hero, cards e notícias por cidade. **Corte neste item:** só a seção da Central usa a localização; o resto da home fica como está.
|
||||
- **"Guarda a cidade para a próxima visita".** Se alguém "só completar": cookie/localStorage de localização, perfil de visitante. **Corte:** nada é persistido — a resolução vale para a visita e morre nela.
|
||||
- **"Pede o GPS de novo a cada visita".** Se alguém "só completar": prompt repetido no carregamento, spinner eterno. **Corte:** GPS só quando acessível (ou affordance); indisponível → IP/recentes, sem insistir.
|
||||
- **"A seção vira uma mini-Central".** Se alguém "só completar": filtros, busca e ações de baixar/compartilhar na home. **Corte:** a seção só apresenta e leva; quem faz tudo é `/conteudos`.
|
||||
- **"Publicar para não sumir".** Se alguém "só completar": hardcode de peças para a seção nunca ficar vazia. **Corte:** fail-closed a zero é regra (kill switch); o código não publica conteúdo.
|
||||
- **"Tocar sozinho".** Se alguém "só completar": autoplay/preview animado para engajar. **Corte:** mídia só no toque, como no S27.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Como obter o GPS?** **Opções:** A) prompt do navegador ao carregar a home | B) sem prompt: usa GPS só quando a permissão já estiver concedida (ou por uma affordance explícita na seção), senão IP. **Recomendação:** B — o prompt surpresa no carregamento queima confiança e a maioria nega; o IP já dá o recorte territorial na primeira visita. _(assumido — validar com produto)_
|
||||
- **Amostra local estrita ou completada?** **Opções:** A) só do município (pode mostrar menos de 3) | B) município → região → recentes | C) só recentes com selo local. **Recomendação:** B — a seção não fica vazia nem parece genérica. _(assumido — validar com produto)_
|
||||
- **Posição na home?** **Opções:** A) depois de `CampaignCardsSection`, antes da newsletter | B) junto de `CampaignContentSection` (S3). **Recomendação:** A — fecha a página com CTA de compartilhamento, mantendo cards + newsletter como bloco final de conversão. _(assumido — validar com produto)_
|
||||
- **Copy/CTA literais?** **Opções:** A) título na voz da Central ("Peça voto pra Solla 1313") + CTA `Ver todas as peças` | B) copy neutra ("Conheça a Central de Conteúdos") | C) outra. **Recomendação:** A — mesma voz do S27; copy final validada no gate/design. _(assumido — validar com produto)_
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue: a registrar para o S36 (`pnpm agent:register`).
|
||||
- Design UI (gate): `docs/plans/central-conteudos-secao-home-ui-design.html`.
|
||||
- `docs/plans/central-conteudos-publica.md` (S27) e `central-conteudos-publica-impl.md` (D7 superseded); `central-conteudos-publica-ui-design.html`.
|
||||
- `src/app/(frontend)/(home)/page.tsx`, `src/components/jingles/JingleHomeSection.tsx`, `src/app/(frontend)/(home)/CampaignCardsSection.tsx`, `src/utilities/content/contentPieceReads.ts`, `src/components/CampaignFooter.tsx`, `src/components/CampaignContentSection.tsx`
|
||||
- Localização: `src/lib/municipalityProximity.ts`, `src/utilities/campaignGeolocation.ts`, `src/components/campaign/shared/useNearestMunicipalitySlug.ts`, `src/utilities/content/contentEventRateLimit.ts`, `src/utilities/ai/themeSearchGuard.ts`
|
||||
- `tests/e2e/frontend.e2e.spec.ts` e `scripts/lib/e2e-affected-manifest.mjs` (manifesto de e2e afetado pela home).
|
||||
- `AGENTS-public.md` — convenções do site público (cache, kill switch, mídia).
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
4,6/5 — (1) fatia = um outcome verificável (a home leva à Central com peças do território; a seção some sem peça); (2) appetite ~2–3 dias cabe (seção + resolução de localização + seleção, com o resto da home intocado); (3) persona/job/aceite em linguagem de produto; (4) direção no codebase é hipótese (precedentes citados como pista); (5) zero decisão dura de engenharia — o mecanismo de resolução fica no plano de implementação e a viabilidade do sinal de IP está marcada "a confirmar".
|
||||
Loading…
Reference in a new issue