From 0bbba099d172fe01815d77f53df38008ca97d7e6 Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Sun, 20 Sep 2026 20:31:33 -0300 Subject: [PATCH] =?UTF-8?q?docs(S23,S24):=20planos=20+=20designs=20hi-fi?= =?UTF-8?q?=20=E2=80=94=20drawer=20mobile=20do=20card=20e=20r=C3=A1dio=20e?= =?UTF-8?q?mbed=20direto=20(Related=20#1234=20#1235)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-time-de-voce-drawer-mobile-ui-design.html | 315 ++++++++++++++++++ .../plans/cards-time-de-voce-drawer-mobile.md | 93 ++++++ docs/plans/radio-embed-direto-ui-design.html | 143 ++++++++ docs/plans/radio-embed-direto.md | 99 ++++++ 4 files changed, 650 insertions(+) create mode 100644 docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html create mode 100644 docs/plans/cards-time-de-voce-drawer-mobile.md create mode 100644 docs/plans/radio-embed-direto-ui-design.html create mode 100644 docs/plans/radio-embed-direto.md diff --git a/docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html b/docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html new file mode 100644 index 00000000..4f9ec2ff --- /dev/null +++ b/docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html @@ -0,0 +1,315 @@ + + + + + + + Design S23 · Drawer mobile do card Time de você + + + +
+ Design tier: openai/gpt-5.6-sol · frontier · gate humano obrigatório +
+ +
+
+

Gate visual · S23

+

Ajuste fino sem vaivém no celular

+

+ Alvo do port: no mobile de 390px, o drawer do estúdio ocupa toda a viewport, respeitando a safe-area. O aviso abre a área rolável e sai de cena ao descer; nada fica sobre a prévia. Zoom e setas continuam no mesmo fluxo. O shell do dialog desktop mantém sua geometria. +

+
+ 390px · alvo do port + 1280px · conferência de escopo + Conteúdo da prévia · NEEDS ASSET +
+
+ +
+
+
+

Cena 01 · mobile 390 × 844

+

Altura total · aviso no fluxo, prévia e controles

+
+ Alvo do port +
+ +
+
+ +
+
+
+
+

Time de você

+

Confira seu card

+
+ +
+ +
+

+ O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles. +

+
+ +
+

Prévia real do visitante · NEEDS ASSET

+ +
+
+ + + + +
+
+

Ajuste fino

+
+ + + + +
+
+
+ + + Harmonizar cores + Ajusta o brilho e as cores da sua foto para combinar com as fotos do card. + +
+
+
+ +
+ + +
+
+
+
+

O topo branco coincide com a viewport e reserva a safe-area. A área rolável começa no aviso; imagem, zoom e setas vêm em seguida, sem qualquer camada sobre a prévia.

+
+ +
+
+

Cena 02 · mobile 390 × 844 · conteúdo rolado

+

Aviso fora de cena · nada sobre a prévia

+
+
+
+
+
+
+
+

Time de você

+

Confira seu card

+
+ +
+
+
+ +
+

Prévia real do visitante · NEEDS ASSET

+
+ Zoom
+
+

Ajuste fino

+
+
+
+
+
+ + +
+
+ +
+
+
+

Cena 03 · desktop 1280 × 800

+

Dialog desktop · aviso no fluxo, imagem limpa

+
+ Sem mudança no shell desktop +
+ +
+
+
+
+
+
+

Time de você

+

Confira seu card

+
+ +
+
+

O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles.

+
+ +
+

Prévia real do visitante · NEEDS ASSET

+
+
Zoom
+

Ajuste fino

+
+
+
+
+
+
Dialog 512px · 92dvh
+
+
+

O dialog permanece centralizado, com largura e teto atuais. A nova regra vale no conteúdo compartilhado: aviso dentro do fluxo rolável e nenhuma camada sobre a imagem.

+
+ +
+

Contrato visual para o port

+
    +
  • • Mobile: drawer encosta no topo, cobre os 844px e respeita a safe-area.
  • +
  • • O aviso é o primeiro item da área rolável, acima da prévia.
  • +
  • • Ao descer, o aviso rola para fora; prévia, zoom e quatro setas ficam juntos.
  • +
  • • Nada se sobrepõe à imagem em drawer ou dialog.
  • +
  • • O badge “Arraste para ajustar” sai; gesto, zoom e setas permanecem.
  • +
  • • Desktop mantém dialog centralizado e dimensões atuais.
  • +
+
+
+ + diff --git a/docs/plans/cards-time-de-voce-drawer-mobile.md b/docs/plans/cards-time-de-voce-drawer-mobile.md new file mode 100644 index 00000000..53969ef0 --- /dev/null +++ b/docs/plans/cards-time-de-voce-drawer-mobile.md @@ -0,0 +1,93 @@ +# Ajuste fino da foto no celular: drawer "Time de você" até o topo, sem nada sobre a imagem + +Status: rascunho +Atualizado em: 2026-09-20 +Issue: #1234 +Priority: P2 +Impeccable: B — encaixe no drawer mobile do estúdio de cards (funil público) +Design UI: docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html +Appetite: ~0,5–1 dia eng; um outcome verificável — no celular, o ajuste fino da foto cabe na tela sem vaivém de rolagem +Responsável: — + +## Intenção + +No celular, a etapa de ajuste fino da foto do card "Time de você" é desastrada: o visitante ou vê a imagem, ou vê os controles — precisa rolar para cima e para baixo no meio do gesto. Duas correções pedidas no gate: (a) nada de sobreposto à imagem — o badge "Arraste para ajustar" sai de cima da prévia — e o aviso "O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles." pode continuar existindo, desde que role junto com o conteúdo, sem ficar em cima da imagem quando o visitante desce para ver o conteúdo completo; (b) fazer o drawer inferior subir até o topo da página, removendo a faixa livre que hoje sobra acima dele e devolvendo espaço ao conteúdo. O enquadramento automático (S18), os controles existentes (arrastar, zoom, setas) e o resto do funil não mudam; o shell desktop (dialog) mantém a geometria. + +## Persona e fluxo + +- **Persona / contexto:** visitante do site público no celular, no meio do funil de cards, já com a foto preparada pelo recorte automático; quer ajustar e compartilhar sem fricção. +- **Job principal:** conferir e ajustar o enquadramento da foto com a prévia e os controles visíveis ao mesmo tempo, sem rolar a tela para lá e para cá. +- **Fluxo desejado:** escolhe o modelo "Time de você" → envia a foto → o drawer sobe até o topo da tela → vê a prévia; ao descer, o aviso rola junto e sai de cena, sem nada fixo sobre a imagem, e os controles de zoom/ajuste fino aparecem juntos → ajusta → segue para o card pronto e o compartilhamento. +- **Anti-goals de produto:** não redesenhar o estúdio nem o composer; não mudar a primitiva `Drawer` global; não mexer na geometria do dialog desktop; não remover a frase própria dos modelos de foto; não reabrir S18/S20. + +### Esboço de fluxo (B) + +```text +[galeria de modelos] → [foto enviada / recorte automático] → [drawer sobe até o topo] +→ [prévia; aviso rola junto e sai de cena ao descer] → [controles na mesma tela] → [card pronto] → [compartilhar] +``` + +### Design UI (B) + +- Design UI (gate): `docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html` + +## Objetivo e aceite + +- Nada fica sobreposto à imagem: o badge "Arraste para ajustar" sai de cima da prévia, no drawer e no dialog. +- O aviso "O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles." permanece, mas dentro da área rolável: rola junto com o conteúdo e sai de cena quando o visitante desce para ver os controles — nunca fica fixo por cima da imagem. +- No celular, o drawer ocupa até o topo da tela, sem faixa livre; o passo de ajuste fino mostra a prévia e os controles de zoom/ajuste fino sem o vaivém de rolagem (o restante do conteúdo pode rolar). +- A geometria do shell desktop (dialog) e os demais modelos de card permanecem intocados; a regra "nada sobreposto à imagem / aviso rolável" vale nos dois shells. +- Swipe-down/fechar e acessibilidade continuam funcionando; o drawer segue anunciando título e conteúdo. +- **Guardrail:** a orientação `aria-describedby` do drawer precisa ser tratada ao remover a descrição — sem prescrever como (a decisão fica para o plano de implementação). +- A intenção diz "até o topo": nenhum token ou valor de altura é fixado aqui; a implementação decide o valor. + +## Dados (intenção) + +- **Vou apresentar dados?** Não — nenhuma PII é coletada ou exibida; a foto e a posição do recorte existem só no aparelho do visitante e nunca saem dele. Sem métrica nova neste item. +- **Decisões desbloqueadas:** N/A — ajuste de layout/UX, sem decisão de dado. +- **Forma:** N/A. + +## Dados da decisão (literais) + +- ID: `S23`; slug: `cards-time-de-voce-drawer-mobile`; tipo: `feature`; Priority: `P2`; Impeccable: `B`. +- Texto exato do aviso do time (verbatim): "O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles." — permanece, porém dentro da área rolável (rola com o conteúdo); a frase própria dos modelos de foto ("Arraste para posicionar e use os controles para aproximar ou ajustar.") fica intocada no header. +- Badge sobre a prévia: "Arraste para ajustar" — sai da posição sobreposta à imagem; nada fica por cima da prévia. +- Alvo do drawer no celular: subir até o topo da viewport, respeitando safe-area — o `92dvh` de hoje vira teto efetivo da tela (validar o teclado no aparelho real). +- Rotas afetadas: `/` (home, seção de cards) e `/cards`. +- Drawer desktop (dialog) fica como está. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `src/components/cards/CardComposer.tsx` (composição da descrição/header), `src/components/cards/CardsStudio.tsx` (override do drawer mobile no ponto de uso), `src/components/ui/Drawer.tsx` (primitiva compartilhada — leitura apenas). +- **Precedente a olhar:** `docs/plans/atualizacoes-mobile-sheet-criacao-usavel.md` e o impl (C107: mesmo padrão de sheet que expande só o necessário, teto no topo; decisão de manter o override no ponto de uso), `docs/plans/bottom-drawer-busca-fullscreen-polimento.md` (fullscreen `100dvh`), `docs/plans/cards-time-de-voce-ajuste-lateral.md`. +- **Risco de acoplamento:** a primitiva `Drawer` serve outros drawers de campanha; manter o override no ponto de uso para não ampliar o blast radius. Respeitar `data-theme="campaign-site"` e o swipe handle/foco do drawer. + +## Dependências + +- Nenhuma. Sucessor de S20 (Issue #1216, entregue) — não reabre S18/S20. + +## Fora de escopo + +- Tutorial ou e2e novo de rolagem. +- Mudanças de copy do funil (o aviso do time permanece — só muda de lugar). +- Outros drawers de campanha. + +## Rabbit holes de produto + +- **"Já que vamos mexer no drawer, ajustamos todos os drawers de campanha."** Se alguém "só completar": vira refactor da primitiva com blast radius em campanha. **Corte neste item:** só o drawer do estúdio de cards; primitiva intacta. +- **"Já que o badge sai, tira o aviso também."** Se alguém "só completar": reabre a decisão do gate. **Corte neste item:** o aviso fica, rolando com o conteúdo. +- **"Aproveita e redesenha os controles do passo de ajuste."** Se alguém "só completar": redesign do composer estoura o appetite. **Corte neste item:** só espaço vertical e a remoção do aviso. + +## Questões em aberto (produto) + +- **Nada sobreposto à imagem e aviso rolável (resolvido no gate):** o badge "Arraste para ajustar" sai de cima da prévia; o aviso do time rola com o conteúdo; nada fica fixo sobre a imagem. _(decidido com o humano no gate)_ +- **Topo da tela com safe-area (resolvido no gate):** subir até o topo respeitando safe-area; validar o teclado no celular real durante o work-issue. _(decidido com o humano no gate)_ + +## Referências + +- GitHub Issue: a registrar (`S23`); S20 = Issue #1216 (entregue, sucessor). +- Design UI (gate): `docs/plans/cards-time-de-voce-drawer-mobile-ui-design.html` +- `docs/plans/atualizacoes-mobile-sheet-criacao-usavel.md` (precedente C107) e `docs/plans/atualizacoes-mobile-sheet-criacao-usavel-impl.md` +- `docs/plans/bottom-drawer-busca-fullscreen-polimento.md` +- `docs/plans/cards-time-de-voce-ajuste-lateral.md` +- `src/components/cards/CardComposer.tsx`, `src/components/cards/CardsStudio.tsx`, `src/components/ui/Drawer.tsx` diff --git a/docs/plans/radio-embed-direto-ui-design.html b/docs/plans/radio-embed-direto-ui-design.html new file mode 100644 index 00000000..0e87bfd6 --- /dev/null +++ b/docs/plans/radio-embed-direto-ui-design.html @@ -0,0 +1,143 @@ + + + + + + + Design S24 · Embed direto da Rádio 1313 + + + +
Design tier: openai/gpt-5.6-sol · frontier · gate humano obrigatório
+ +
+
+

Gate visual · S24

+

Rádio 1313: o player já está na página

+

A seção mantém seu cabeçalho e sua copy. No lugar do card-facade entra somente o embed oficial, em moldura mínima e com footprint reservado. O widget fica nu: sem arte, eyebrow interno, escudo, botão intermediário, link “Abrir no Zeno” ou aviso de terceiro.

+
1280px · desktop390px · alvo mobile do portWidget zeno.fm · NEEDS ASSET
+
+ +
+

Cena 01 · desktop 1280 · 0 jingles publicados

Rádio sozinha · estado real de produção

Variante compact preservada
+
+
+
+
+

A trilha da nossa caminhada

Sintonize com a Rádio 1313

Ainda não há jingles publicados por aqui. Enquanto isso, ouça a Rádio Jorge Solla 1313.

+
+
Embed oficial zeno.fm
conteúdo de terceiro · NEEDS ASSET
+
+
168px reservadosO espaço do widget existe desde o primeiro paint: sem salto quando o iframe responder.
+
+
+
+
+ +
+

Cena 02 · mobile 390 · 0 jingles publicados

Player direto sem overflow horizontal

+
+
+
+

A trilha da nossa caminhada

Sintonize com a Rádio 1313

Ainda não há jingles publicados por aqui. Enquanto isso, ouça a Rádio Jorge Solla 1313.

+
Embed oficial zeno.fm
NEEDS ASSET · 150px reservados
+
+
390px · alvo mobile do port · sem botão intermediário
+
+
+ +
+

Cena 03 · desktop 1280 · com jingles

Embed direto + grade existente com 3 cards

+
+
+
+
+

A trilha da nossa caminhada

Cante, baixe e espalhe

Ouça a Rádio Jorge Solla 1313 e os jingles oficiais da campanha. Dê o play e baixe o seu preferido para levar com você.

+
Embed oficial zeno.fm
conteúdo de terceiro · NEEDS ASSET
+

Jingles oficiais

Dê o play. O próximo ritmo é seu.

Um jingle toca por vez.
+
+
Capa do jingle
NEEDS ASSET

Nome do jingle

Pronto para tocar

Tempo —:—Duração —:—
↓ Baixar MP3
+
Capa do jingle
NEEDS ASSET

Nome do jingle

Pronto para tocar

Tempo —:—Duração —:—
↓ Baixar MP3
+
Capa do jingle
NEEDS ASSET

Nome do jingle

Pronto para tocar

Tempo —:—Duração —:—
↓ Baixar MP3
+
+ +
+
+
+
+ +
+

Removido da superfície

Nada entre a seção e o player

  • • Sem arte “Rádio online” e ondas.
  • • Sem eyebrow “Sintonize com a gente” dentro do card.
  • • Sem título/textos próprios da facade.
  • • Sem escudo, “Ouvir a rádio” ou “Abrir no Zeno”.
  • • Sem estados da facade nem aviso de serviço externo.
+

Mantido no port

Seção e footprint reservado

  • • Header/copy variam com 0 ou N jingles como hoje.
  • • Embed direto ocupa 150px mobile / 168px desktop na cena.
  • • Moldura mínima: borda, raio e sombra baixa.
  • • Widget nu, sem linha, chip, badge ou escudo abaixo.
  • • Grade e “Ver todos os jingles” seguem abaixo quando existirem.
+
+
+ + diff --git a/docs/plans/radio-embed-direto.md b/docs/plans/radio-embed-direto.md new file mode 100644 index 00000000..c822ea5e --- /dev/null +++ b/docs/plans/radio-embed-direto.md @@ -0,0 +1,99 @@ +# Rádio 1313 na home — embed direto (S24) + +Status: rascunho +Atualizado em: 2026-09-20 +Issue: #1235 +Priority: P2 +Impeccable: B — encaixe/remoção na seção de som da home (substitui o card-facade pela moldura mínima do embed) +Design UI: docs/plans/radio-embed-direto-ui-design.html +Appetite: ~0,5–1 dia eng; um outcome verificável — a rádio toca a partir do embed direto, sem clique prévio +Responsável: — + +## Intenção + +A Rádio Jorge Solla 1313 na home hoje mora dentro de um card-wrapper com facade click-to-load: arte "Rádio online" com ondas, eyebrow "Sintonize com a gente", título, textos explicativos, aviso com escudo, botão "Ouvir a rádio" e estados de carregamento — o iframe do zeno.fm só monta depois do clique. O humano achou esse layout desnecessário: basta o embed direto do zeno.fm (`https://zeno.fm/player/jorge-solla-1313/`), carregado automaticamente desde o início do carregamento da página. O embed oficial já traz os detalhes da rádio (capa, nome, programação). A seção de jingles publicados e a página `/jingles` não mudam. + +**Trade-off assumido (decisão do humano):** o auto-carregamento reverte de propósito a razão da facade do S22 (#1228) — o widget do zeno carrega Google Analytics `G-2T527NZWVM` e redes de anúncio em todo pageview. Isso passa a ser esperado, não um defeito: decisão explícita do humano, registrada com honestidade; o plano antigo é imutável e não é reaberto. Não coletamos PII nova; o visitante apenas acessa um serviço externo. **Sem linha de transparência (decisão do humano no gate):** o embed fica nu — sem aviso de terceiro, chip, badge ou escudo sob o player. + +## Persona e fluxo + +- **Persona / contexto:** visitante e militante que chega pela home no celular (link no WhatsApp, busca, indicação), com pressa e em conexão qualquer. +- **Job principal:** ouvir a Rádio Jorge Solla 1313 na home no primeiro play, sem um passo de "carregar player". +- **Fluxo desejado:** abre a home → rola até a seção de som → o embed oficial já está ali, tocável → dá play direto. Com jingles publicados, a grade e o "Ver todos" seguem abaixo; sem jingles, a rádio fica sozinha. +- **Anti-goals de produto:** não redesenha a seção de som; não vira player custom nem proxy/stream; não mexe nos jingles nem em `/jingles`; não autoplay com som; não promete analytics/contador de ouvintes; não cria framework de consent/CSP. + +### Esboço de fluxo (B) + +```text +[visitante na home] → rola até a seção de som +→ embed oficial da Rádio 1313 já montado e tocável (sem clique intermediário) +→ dá play direto · segue ouvindo enquanto rola +[zero jingles publicados] → rádio sozinha (comportamento da variante compact) +[com jingles] → grade + "Ver todos os jingles" → /jingles +``` + +### Design UI (B) + +- Design UI (gate): `docs/plans/radio-embed-direto-ui-design.html` (cenas da seção com o embed direto, com 0 e N jingles, e o footprint reservado antes do iframe responder). + +## Objetivo e aceite + +- Ao carregar a home, o embed oficial do zeno já está montado e tocável, sem botão nem clique prévio. +- Os elementos do wrapper/facade somem: arte "Rádio online", eyebrow "Sintonize com a gente", textos explicativos, aviso com escudo, botão "Ouvir a rádio" e estados loading/loaded. +- A regra da seção de som permanece: rádio sempre visível; grade de jingles fail-closed por publicação (funciona com 0 publicados; kill switch do S21 valendo). +- Sem salto vertical perceptível ao carregar o iframe; celular primeiro, sem overflow horizontal a 390px; o embed nunca toca sozinho com som e mantém rótulo acessível. +- `/jingles` e o player dos jingles publicados ficam intocados. +- O site segue sem coletar PII e a home segue estática (cache tag `jingles`). + +## Dados (intenção) + +- **Vou apresentar dados?** Não — nenhum dado nosso é apresentado ou coletado; a superfície é um player de terceiro (sem PII). +- **Decisões desbloqueadas:** N/A — a decisão é do visitante (ouvir agora), não leitura de números. +- **Forma:** N/A — sem dado agregado a definir. + +## Dados da decisão (literais) + +- ID `S24`; slug `radio-embed-direto`; tipo `feature`; Priority `P2`; Impeccable `B`; rota: a home `/` (sem rota nova). +- Embed a auto-carregar: `https://zeno.fm/player/jorge-solla-1313/`; página da rádio: `https://zeno.fm/radio/jorge-solla-1313/`. +- Estado de hoje em produção (verificado 2026-09-20): **0 jingles publicados** — a seção mostra a rádio sozinha na variante `compact`. +- Rastro de terceiros que passa a rodar em todo pageview da home: Google Analytics `G-2T527NZWVM` + redes de anúncio do widget zeno — assumido; sem PII nossa. +- Sem linha nem aviso de transparência sob o embed (decidido com o humano no gate): o player fica nu. +- Design UI (gate): `docs/plans/radio-embed-direto-ui-design.html`. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** seção de som da home — `src/components/jingles/` (hoje `JingleHomeSection.tsx` renderiza `RadioFacade.tsx`, que sai) e, se preciso, `src/app/(frontend)/(home)/page.tsx`; CSS da facade em `src/app/(frontend)/styles.css` (`campaign-radio-art/wave/spinner`) tende a ficar órfão e deve sair junto. +- **Precedente a olhar:** S22 (#1228) em `docs/plans/jingles-radio-homepage.md` + `-impl.md`; a leitura cacheada da publicação (tag `jingles`) que alimenta a seção. +- **Risco de acoplamento:** manter a home estática/ISR; não tocar no player nem em `/jingles`; o spec e2e `frontend` roda em paralelo e não stuba zeno — o hermetismo dos testes que pinam a facade hoje terá de ser resolvido na execução (fixture só roteia youtube/facebook e falha em erro de console externo); e2e mede overflow a 390px. + +## Dependências + +- Nenhuma dura. Estação ativa no zeno.fm; S22 (#1228) entregue (decisão revertida de propósito). Design hi-fi aprovado no gate. + +## Fora de escopo + +- Consent/CSP/click-to-play global; analytics de reprodução; trocar o embed por outro provedor. +- Alterar a decisão de facade dos jingles publicados; qualquer mudança em `/jingles`. +- Player custom, proxy ou stream próprio. + +## Rabbit holes de produto + +- **Player custom ou proxy do stream.** Se alguém "só completar": vira projeto de player e infra de stream. **Corte neste item:** embed oficial do zeno. +- **Framework de consent/CSP global.** Se alguém "só completar": banner, categorias, política nova. **Corte:** embed oficial do zeno, nu, sem moldura de consent/aviso. +- **Analytics/contador de ouvintes.** Se alguém "só completar": API do zeno, polling, dado frágil. **Corte:** a rádio é um play, não um dashboard. +- **Redesenhar a seção de som.** Se alguém "só completar": craft da seção inteira, copy e headings. **Corte:** a mudança é remoção do wrapper + moldura mínima do embed; header/copy atuais ficam. + +## Questões em aberto (produto) + +- **Linha de transparência sob o embed (resolvido no gate):** não existe — o embed fica nu, sem aviso de terceiro. _(decidido com o humano no gate)_ +- **Manter a variante compact (zero jingles)?** **Opções:** A) manter o comportamento da seção, com o embed direto no lugar do card | B) unificar os dois casos. **Recomendação:** A — validar no design. +- **O link externo "Abrir no Zeno" some?** **Opções:** A) some com o wrapper | B) manter ao lado do embed. **Recomendação:** A — o embed tem os próprios links. + +## Referências + +- GitHub Issue: a registrar (`S24`); S22 = Issue #1228 (entregue; decisão revertida de propósito, não reabrir). +- Design UI (gate): `docs/plans/radio-embed-direto-ui-design.html` +- `docs/plans/jingles-radio-homepage.md` e `docs/plans/jingles-radio-homepage-impl.md` — decisão original de facade (histórico; não editar). +- `src/components/jingles/RadioFacade.tsx`, `src/components/jingles/JingleHomeSection.tsx` — o que sai/encaixa. +- `tests/unit/radioFacade.unit.spec.tsx`, `tests/unit/jingleHomeSection.unit.spec.tsx`, `tests/unit/campaignHome.unit.spec.tsx`, `tests/e2e/frontend.e2e.spec.ts`, `tests/e2e/frontendJingles.e2e.spec.ts` — contratos que pinam a facade hoje. +- `AGENTS.md` — home pública estática/cache tag `jingles` e postura LGPD.