mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
docs(S25,S26): planos + designs — player próprio da Rádio 1313 e crédito do artista (Related #1239 #1240)
This commit is contained in:
parent
5aefb2f3ba
commit
162dc8d017
4 changed files with 1391 additions and 0 deletions
492
docs/plans/jingle-titulo-credito-artista-ui-design.html
Normal file
492
docs/plans/jingle-titulo-credito-artista-ui-design.html
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
<!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 S26 · Título e crédito do artista no jingle</title>
|
||||
<style type="text/tailwindcss">
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #000000;
|
||||
--pt-red: #a21c1c;
|
||||
--pt-red-dark: #47130e;
|
||||
--pt-yellow: #ffe607;
|
||||
--pt-yellow-ink: #000000;
|
||||
--campaign-cream: #fff8f2;
|
||||
--campaign-ink: #000000;
|
||||
--campaign-muted: #6c615e;
|
||||
--campaign-surface: #f9faff;
|
||||
--campaign-band: #ebe9e9;
|
||||
--campaign-line: rgb(0 0 0 / 12%);
|
||||
--font-exo2: 'Exo 2', 'Arial Black', sans-serif;
|
||||
--font-arimo: Arimo, Arial, sans-serif;
|
||||
--radius: 0.875rem;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--font-arimo);
|
||||
}
|
||||
.font-display,
|
||||
.eyebrow {
|
||||
font-family: var(--font-exo2);
|
||||
}
|
||||
.eyebrow {
|
||||
font-size: clamp(10px, calc(0.32vw + 8.75px), 12px);
|
||||
line-height: 1.25;
|
||||
}
|
||||
.stage {
|
||||
box-shadow: 0 26px 80px rgb(0 0 0 / 30%);
|
||||
}
|
||||
.focus-ring:focus-visible {
|
||||
outline: 3px solid var(--pt-yellow);
|
||||
outline-offset: 3px;
|
||||
box-shadow: 0 0 0 2px var(--pt-red-dark);
|
||||
}
|
||||
.card {
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--campaign-line);
|
||||
border-radius: 14px;
|
||||
background: white;
|
||||
box-shadow: 0 12px 34px rgb(71 19 14 / 8%);
|
||||
}
|
||||
.card[data-state='playing'] {
|
||||
border-color: rgb(162 28 28 / 36%);
|
||||
box-shadow: 0 14px 38px rgb(162 28 28 / 14%);
|
||||
}
|
||||
.cover {
|
||||
position: relative;
|
||||
aspect-ratio: 1;
|
||||
overflow: hidden;
|
||||
background: var(--campaign-band);
|
||||
}
|
||||
.cover img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.cover::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 58% 0 0;
|
||||
background: linear-gradient(to bottom, transparent, rgb(24 10 9 / 42%));
|
||||
}
|
||||
.play {
|
||||
display: grid;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
flex: none;
|
||||
place-items: center;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: var(--pt-yellow);
|
||||
color: #000;
|
||||
box-shadow:
|
||||
0 6px 0 #cfb900,
|
||||
0 10px 22px rgb(0 0 0 / 15%);
|
||||
}
|
||||
.play svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: currentColor;
|
||||
}
|
||||
.jingle-title {
|
||||
overflow-wrap: anywhere;
|
||||
font-family: var(--font-exo2);
|
||||
font-size: 24px;
|
||||
line-height: 1.02;
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
.credit {
|
||||
margin-top: 6px;
|
||||
color: var(--campaign-muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.25;
|
||||
font-weight: 700;
|
||||
}
|
||||
.progress {
|
||||
height: 6px;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: #dedbd8;
|
||||
}
|
||||
.progress > span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: var(--pt-red);
|
||||
}
|
||||
.download {
|
||||
display: flex;
|
||||
min-height: 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
border: 1.5px solid rgb(162 28 28 / 32%);
|
||||
border-radius: 10px;
|
||||
color: var(--pt-red);
|
||||
font-family: var(--font-exo2);
|
||||
font-weight: 800;
|
||||
}
|
||||
.proof-card .jingle-title {
|
||||
font-size: 22px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-zinc-950 text-zinc-100 antialiased">
|
||||
<div
|
||||
class="border-b border-emerald-400/40 bg-emerald-400/10 px-4 py-2 text-center text-[11px] font-black tracking-[0.14em] text-emerald-300 uppercase"
|
||||
>
|
||||
Design tier: openai/gpt-5.6-sol · gate humano obrigatório
|
||||
</div>
|
||||
<main class="mx-auto max-w-[1440px] px-4 py-10 sm:px-6 lg:px-10">
|
||||
<header class="max-w-4xl">
|
||||
<p class="font-display text-xs font-black tracking-[0.12em] text-red-400 uppercase">
|
||||
Gate visual · S26
|
||||
</p>
|
||||
<h1 class="font-display mt-2 text-3xl font-black tracking-[-0.03em]">
|
||||
O nome do artista não vira reticências
|
||||
</h1>
|
||||
<p class="mt-3 max-w-3xl text-sm leading-6 text-zinc-400">
|
||||
O card mantém capa, controles, progresso e download. Só o bloco textual muda: título-base
|
||||
em até duas linhas e <strong class="text-zinc-200">feat. artista</strong> em linha
|
||||
própria, menor e sempre visível.
|
||||
</p>
|
||||
<div class="mt-5 flex flex-wrap gap-2 text-[11px] font-bold text-zinc-300">
|
||||
<span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2"
|
||||
>1280px · 3 títulos reais</span
|
||||
><span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2"
|
||||
>390px · tocando + provas de estresse</span
|
||||
><span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2"
|
||||
>Sem ativo novo</span
|
||||
>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="mt-12" aria-labelledby="desktop-cards">
|
||||
<div class="mb-5">
|
||||
<p
|
||||
class="font-display text-[11px] font-black tracking-[0.12em] text-emerald-300 uppercase"
|
||||
>
|
||||
Cena 01 · desktop 1280 · parado e tocando
|
||||
</p>
|
||||
<h2 id="desktop-cards" class="font-display mt-1 text-xl font-black">
|
||||
Os três créditos reais cabem sem diminuir a capa
|
||||
</h2>
|
||||
</div>
|
||||
<div class="overflow-x-auto pb-4">
|
||||
<div
|
||||
class="stage mx-auto w-[1280px] overflow-hidden bg-(--campaign-cream) text-black"
|
||||
data-theme="campaign"
|
||||
>
|
||||
<section class="relative px-[60px] py-16">
|
||||
<div
|
||||
class="absolute -top-28 -right-20 size-64 rounded-full bg-(--pt-yellow)/45"
|
||||
></div>
|
||||
<div class="relative flex items-end justify-between gap-6">
|
||||
<div>
|
||||
<p class="eyebrow font-black tracking-[.1em] text-(--pt-red) uppercase">
|
||||
Jingles oficiais
|
||||
</p>
|
||||
<h3 class="font-display mt-1 text-2xl font-black tracking-[-.02em]">
|
||||
Dê o play. O próximo ritmo é seu.
|
||||
</h3>
|
||||
</div>
|
||||
<span class="text-sm text-(--campaign-muted)">Um jingle toca por vez.</span>
|
||||
</div>
|
||||
<div class="relative mt-6 grid grid-cols-3 gap-6">
|
||||
<article class="card" data-state="stopped">
|
||||
<div class="cover">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-forro.jpg"
|
||||
alt="Capa oficial do jingle Forró"
|
||||
/>
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="play focus-ring"
|
||||
aria-label="Tocar jingle Jorge Solla 1313 (feat. Felipe Forrozeiro)"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z" /></svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4 class="jingle-title">Jorge Solla 1313</h4>
|
||||
<p class="credit">feat. Felipe Forrozeiro</p>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="progress"><span class="w-0"></span></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[11px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo —:—</span><span>Duração —:—</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="download mt-5">↓ Baixar MP3</a>
|
||||
<p class="mt-3 truncate text-center text-[11px] text-black/45">
|
||||
jorge-solla-1313-jingle-forro.mp3
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="card" data-state="playing">
|
||||
<div class="cover">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-axe.jpg"
|
||||
alt="Capa oficial do jingle Axé"
|
||||
/>
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="play focus-ring"
|
||||
aria-label="Pausar jingle Jorge Solla 1313 (feat. Nagib Barroso)"
|
||||
aria-pressed="true"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="M8 5h3v14H8zM14 5h3v14h-3z" /></svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4 class="jingle-title">Jorge Solla 1313</h4>
|
||||
<p class="credit">feat. Nagib Barroso</p>
|
||||
<p class="mt-2 flex items-center gap-2 text-sm font-bold text-(--pt-red)">
|
||||
<span class="size-2 rounded-full bg-(--pt-red)"></span>Em reprodução
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="progress"><span class="w-[38%]"></span></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[11px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo 0:38</span><span>Duração 1:40</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="download mt-5">↓ Baixar MP3</a>
|
||||
<p class="mt-3 truncate text-center text-[11px] text-black/45">
|
||||
jorge-solla-1313-jingle-axe.mp3
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="card" data-state="stopped">
|
||||
<div class="cover">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-pagodao.jpg"
|
||||
alt="Capa oficial do jingle Pagodão"
|
||||
/>
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="play focus-ring"
|
||||
aria-label="Tocar jingle Jorge Solla 1313 (feat. É O MT)"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z" /></svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4 class="jingle-title">Jorge Solla 1313</h4>
|
||||
<p class="credit">feat. É O MT</p>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="progress"><span class="w-0"></span></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[11px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo —:—</span><span>Duração —:—</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="download mt-5">↓ Baixar MP3</a>
|
||||
<p class="mt-3 truncate text-center text-[11px] text-black/45">
|
||||
jorge-solla-1313-jingle-pagodao.mp3
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16" aria-labelledby="mobile-proof">
|
||||
<div class="mb-5">
|
||||
<p class="font-display text-[11px] font-black tracking-[0.12em] text-amber-300 uppercase">
|
||||
Cena 02 · mobile 390 · tocando
|
||||
</p>
|
||||
<h2 id="mobile-proof" class="font-display mt-1 text-xl font-black">
|
||||
Crédito permanece entre título e estado
|
||||
</h2>
|
||||
</div>
|
||||
<div
|
||||
class="stage mx-auto w-[390px] max-w-full overflow-hidden bg-(--campaign-cream) p-5 text-black"
|
||||
data-theme="campaign"
|
||||
>
|
||||
<p class="eyebrow font-black tracking-[.1em] text-(--pt-red) uppercase">
|
||||
Jingles oficiais
|
||||
</p>
|
||||
<h3 class="font-display mt-1 text-2xl font-black">Dê o play</h3>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Um jingle toca por vez.</p>
|
||||
<article class="card mt-5" data-state="playing">
|
||||
<div class="cover">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-forro.jpg"
|
||||
alt="Capa oficial do jingle Forró"
|
||||
/>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="play focus-ring"
|
||||
aria-label="Pausar jingle Jorge Solla 1313 (feat. Felipe Forrozeiro)"
|
||||
aria-pressed="true"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="M8 5h3v14H8zM14 5h3v14h-3z" /></svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4 class="jingle-title">Jorge Solla 1313</h4>
|
||||
<p class="credit">feat. Felipe Forrozeiro</p>
|
||||
<p class="mt-2 flex items-center gap-2 text-sm font-bold text-(--pt-red)">
|
||||
<span class="size-2 rounded-full bg-(--pt-red)"></span>Em reprodução
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="progress"><span class="w-[38%]"></span></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[10px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo 0:38</span><span>Duração 1:40</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="download mt-5">↓ Baixar MP3</a>
|
||||
<p class="mt-3 truncate text-center text-[11px] text-black/45">
|
||||
jorge-solla-1313-jingle-forro.mp3
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16" aria-labelledby="stress-proof">
|
||||
<div class="mb-5">
|
||||
<p class="font-display text-[11px] font-black tracking-[0.12em] text-sky-300 uppercase">
|
||||
Cena 03 · mobile 390 · prova de estresse
|
||||
</p>
|
||||
<h2 id="stress-proof" class="font-display mt-1 text-xl font-black">
|
||||
Título-base longo e fallback sem crédito
|
||||
</h2>
|
||||
</div>
|
||||
<div class="grid gap-6 lg:grid-cols-2">
|
||||
<div class="rounded-2xl border border-zinc-800 bg-zinc-900 p-5">
|
||||
<p class="mb-3 text-[11px] font-black tracking-[.1em] text-amber-300 uppercase">
|
||||
Título-base no limite · parado
|
||||
</p>
|
||||
<div class="mx-auto w-[350px] max-w-full text-black">
|
||||
<article class="proof-card card" data-state="stopped">
|
||||
<div class="h-28 bg-(--campaign-band) p-4">
|
||||
<span
|
||||
class="inline-flex rounded-full border border-dashed border-black/25 bg-white px-3 py-2 text-[10px] font-black tracking-[.08em] text-(--campaign-muted) uppercase"
|
||||
>Capa existente · não alterada</span
|
||||
>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="play"
|
||||
aria-label="Tocar jingle Nome muito longo do jingle oficial da campanha (feat. Nome do artista)"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z" /></svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h3 class="jingle-title">Nome muito longo do jingle oficial da campanha</h3>
|
||||
<p class="credit">feat. Nome do artista</p>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5"><div class="progress"></div></div>
|
||||
<a class="download mt-5">↓ Baixar MP3</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<p class="mt-4 text-xs leading-5 text-zinc-400">
|
||||
No conteúdo real, o título-base cabe em até duas linhas. Este placeholder extremo
|
||||
passa de duas para provar o fail-safe: nada recebe <code>truncate</code> e o crédito
|
||||
continua inteiro.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-2xl border border-zinc-800 bg-zinc-900 p-5">
|
||||
<p class="mb-3 text-[11px] font-black tracking-[.1em] text-emerald-300 uppercase">
|
||||
Sem “(feat. …)” · fallback
|
||||
</p>
|
||||
<div class="mx-auto w-[350px] max-w-full text-black">
|
||||
<article class="proof-card card" data-state="stopped">
|
||||
<div class="h-28 overflow-hidden bg-(--campaign-band)">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-axe.jpg"
|
||||
alt="Capa oficial do jingle Axé"
|
||||
class="h-full w-full object-cover object-[center_38%]"
|
||||
/>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start gap-4">
|
||||
<button class="play" aria-label="Tocar jingle Axé">
|
||||
<svg viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z" /></svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h3 class="jingle-title">Axé</h3>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5"><div class="progress"></div></div>
|
||||
<a class="download mt-5">↓ Baixar MP3</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<p class="mt-4 text-xs leading-5 text-zinc-400">
|
||||
Sem crédito, nenhuma linha vazia é reservada: o card segue natural e apenas deixa de
|
||||
truncar o título.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16 rounded-2xl border border-zinc-800 bg-zinc-900/70 p-6">
|
||||
<p class="font-display text-[11px] font-black tracking-[.12em] text-emerald-300 uppercase">
|
||||
Especificação visual aprovada no gate
|
||||
</p>
|
||||
<div class="mt-4 grid gap-6 text-sm leading-6 text-zinc-300 md:grid-cols-3">
|
||||
<div>
|
||||
<h2 class="font-display font-black text-white">Título-base</h2>
|
||||
<p class="mt-2">
|
||||
Exo 2, 24px (22px no estresse), peso 900, entrelinha 1.02. Os títulos reais ocupam até
|
||||
duas linhas; não há corte silencioso.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="font-display font-black text-white">Crédito</h2>
|
||||
<p class="mt-2">
|
||||
<strong>feat. Nome do artista</strong>, sem parênteses, 13px, peso 700, cor
|
||||
<code>--campaign-muted</code>. Nunca truncado.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="font-display font-black text-white">Continuidade</h2>
|
||||
<p class="mt-2">
|
||||
Capas existentes, botão amarelo, estado, progresso, download, raios e sombras
|
||||
permanecem como hoje.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
106
docs/plans/jingle-titulo-credito-artista.md
Normal file
106
docs/plans/jingle-titulo-credito-artista.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# Card de jingle — título completo e crédito "(feat. …)" visível (S26)
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-21
|
||||
Issue: #1240
|
||||
Priority: P2
|
||||
Impeccable: B — encaixe fino no card de jingle existente (home + `/jingles`), sem redesenhar a seção
|
||||
Design UI: docs/plans/jingle-titulo-credito-artista-ui-design.html
|
||||
Appetite: ~0,5 dia eng; um outcome verificável — o título não corta e o crédito do artista aparece no card
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
Os jingles oficiais são de Jorge Solla 1313 **com** artistas convidados, e o card não conta isso. Em produção o título chega como `Jorge Solla 1313 (feat. Felipe Forrozeiro)`, mas o card impõe uma única linha com reticências e o nome do parceiro some: lê-se `Jorge Solla 1313 (fe…`. O mesmo acontece com Nagib Barroso e É O MT. Crédito de artista é reconhecimento devido a quem fez a música — e é informação de escolha: o militante procura e repassa "o jingle do fulano".
|
||||
|
||||
A decisão é de layout, não de dado: nenhum título publicado será reescrito. O `(feat. …)` passa a viver numa linha própria, em corpo menor, abaixo do título-base, que pode ocupar até duas linhas. O crédito não pode sumir em estado nenhum — parado ou tocando, na home ou em `/jingles` — e o card é o mesmo nos dois lugares.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** visitante/militante no celular, chegando pela home ou por `/jingles` (link no WhatsApp, busca); de perto, a assessoria que ouve e repassa o material.
|
||||
- **Job principal:** identificar de relance o jingle e o artista que participa, sem que o nome do parceiro fique escondido atrás de reticências.
|
||||
- **Fluxo desejado:** vê o card → lê o título completo (até 2 linhas) e, abaixo, o crédito `feat. <artista>` em corpo menor → toca/pausa (crédito continua lá) → baixa o MP3 com o nome de hoje.
|
||||
- **Anti-goals de produto:** não vira ficha técnica nem discografia; não muda capa, áudio, slug, ordem, published ou download; não redesenha a seção de som nem o player da rádio (irmã S25); não cria dado novo de artista.
|
||||
|
||||
### Esboço de fluxo (B)
|
||||
|
||||
```text
|
||||
[card na home ou /jingles]
|
||||
→ título-base completo (até 2 linhas, sem esconder o crédito)
|
||||
→ linha "feat. <artista>" em corpo menor — visível parado e tocando
|
||||
→ play/pausa (um por vez) → Baixar MP3 (nome do arquivo inalterado)
|
||||
```
|
||||
|
||||
### Design UI (B)
|
||||
|
||||
- Design UI (gate): `docs/plans/jingle-titulo-credito-artista-ui-design.html`
|
||||
- Cenas exigidas: card a 390 (mobile) e 1280 (desktop), parado e tocando, com os 3 títulos reais; e o caso extremo de título-base longo (2+ linhas) provando que o crédito nunca é cortado. O artefato é a fonte de verdade do port; o tamanho exato da fonte do título-base e a cor de apoio do crédito ficam no design.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- O título-base de cada jingle aparece por inteiro em até 2 linhas (nada de reticências antes do crédito), na home e em `/jingles`.
|
||||
- O crédito `feat. <artista>` aparece sempre numa linha própria, em corpo menor e cor de apoio, nos estados parado e tocando, nas duas superfícies.
|
||||
- O crédito nunca recebe `truncate`; se o título-base for longo, ele quebra — o crédito permanece legível.
|
||||
- Os 3 títulos reais de produção ficam legíveis de ponta a ponta, com o artista creditado.
|
||||
- Aria-labels continuam com o título completo (crédito incluso) no play/pausar, no progresso e no download; a linha do crédito é conteúdo real, não decoração.
|
||||
- Nada do dado muda: títulos, capas, áudio, slug, ordem, published e o nome do arquivo baixado seguem exatamente como estão.
|
||||
- Jingle sem `(feat. …)` (ex.: `Axé`) continua com o layout de hoje, agora sem truncamento.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — N/A: esta fatia não apresenta métrica, agregado nem decisão de dados; o que se lê é o título já publicado.
|
||||
- **Decisões desbloqueadas:** nenhuma — nenhum ator decide algo a partir de dado novo.
|
||||
- **Forma:** _adiada ao plano de implementação_ — restrição de produto: nada de telemetria nova nem de superfície de dados; sem PII/Consent.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- ID `S26`; slug `jingle-titulo-credito-artista`; tipo `feature`; Priority `P2`; Impeccable `B`.
|
||||
- Design UI (gate): `docs/plans/jingle-titulo-credito-artista-ui-design.html`.
|
||||
- Títulos reais em produção (verificados em `/jingles` de jorgesolla1313.com.br, 2026-09-21): `Jorge Solla 1313 (feat. Felipe Forrozeiro)`, `Jorge Solla 1313 (feat. Nagib Barroso)`, `Jorge Solla 1313 (feat. É O MT)`.
|
||||
- Defeito literal: o card corta o título em 1 linha com `truncate` e o `(feat. …)` não aparece.
|
||||
- Regra literal de exibição: separar o segmento `(feat. …)` do título **apenas na exibição** — o segmento vira a linha de crédito, o restante é o título-base; sem segmento, o card fica como hoje.
|
||||
- Aria-labels preservam o título completo: `Tocar/Pausar jingle <título completo>`, `Progresso do jingle <título completo>`, `Baixar <título completo> em MP3`.
|
||||
- Download inalterado (deriva do slug): `jorge-solla-1313-jingle-axe.mp3`, `jorge-solla-1313-jingle-forro.mp3`, `jorge-solla-1313-jingle-pagodao.mp3`.
|
||||
- Sem schema/migration; sem editar conteúdo em produção; o mesmo card serve home (até 3 jingles) e `/jingles`.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/components/jingles/JingleCards.tsx` — dono do card (heading `:191-193`, bloco play+texto `:178-203`, estados `:194-201`, aria-labels `:184/:208/:237`); `src/lib/jingle.ts` é a casa natural de uma função pura de quebra título/crédito (`toJingleViewModel` `:57-75`), se o executor preferir derivar no view model.
|
||||
- **Precedente a olhar:** planos S21 `docs/plans/jingles-site-publico.md` (dono do card) e S22 `docs/plans/jingles-radio-homepage.md`; testes que pinam título/aria — `tests/unit/jingle.unit.spec.ts`, `tests/unit/jinglePlayer.unit.spec.tsx`, `tests/unit/jingleHomeSection.unit.spec.tsx`; e2e `tests/e2e/frontendJingles.e2e.spec.ts`.
|
||||
- **Risco de acoplamento:** o card é único para home e `/jingles` (`JingleHomeSection.tsx:81` passa `headingLevel="h4"`) — corrigir no dono, sem twin; a home segue estática; não tocar no player da rádio (S25) nem no schema/`Jingle.ts`; grid `:143` e filename truncado `:242` ficam como estão.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma (S21/S22/S24 entregues; S25 é irmã, não pré-requisito).
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Campo/relação de artista ou `feat` na collection `Jingle` — migration + reedição dos 3 registros (alternativa registrada; gatilho de revisita em Questões).
|
||||
- Renomear/encurtar títulos, ou mexer em capa, áudio, slug, ordem e published no admin/produção.
|
||||
- Redesenhar a seção de som, o grid de jingles ou o player da rádio (S25).
|
||||
- Metadata/OG de `/jingles` (`page.tsx:56-57` usa título fixo) — não muda.
|
||||
- Ajustar a descrição do campo `title` no admin (`Jingle.ts:48-50`, hoje "Nome curto … (ex.: Axé)") — curadoria futura, se a revisita do campo estruturado acontecer.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Já que dá para separar, cria o campo do artista".** Se alguém "só completar": migration + curadoria dos títulos + risco de divergência entre título e campo. **Corte neste item:** layout apenas, extração na exibição; sucessor só com o gatilho de filtrar/ordenar por artista.
|
||||
- **"Reescreve os títulos no admin para o card caber".** Se alguém "só completar": edita conteúdo publicado e mexe no que já foi distribuído. **Corte neste item:** não se toca no dado; quem se ajusta é o layout.
|
||||
- **"Redesenha a seção para caber título grande".** Se alguém "só completar": vira reabertura do S21/S22/S24 e da home. **Corte neste item:** encaixe fino no card; grid, capa e player ficam.
|
||||
- **"Aproveita e melhora a tipografia da seção inteira".** Se alguém "só completar": reabre o design das seções anteriores. **Corte neste item:** mudam só o heading do card e a linha de crédito.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **O crédito mora no título ou vira campo estruturado?** **Opções:** A) extrair `(feat. …)` na exibição, sem schema (recomendado) | B) campo `feat`/artista na collection com migration + reedição dos 3 títulos | C) manter tudo no título e só reduzir a fonte. **Recomendação:** A — resolve crédito e corte sem tocar em dado publicado; B fica como sucessora **se** surgir necessidade de filtrar/ordenar por artista ou de títulos curtos por ritmo (Axé/Forró/Pagodão), com gatilho explícito; C não garante que o crédito apareça. _(assumido — validar com produto no gate)_
|
||||
- **A linha do crédito mantém os parênteses do título?** **Opções:** A) `(feat. Felipe Forrozeiro)` literal | B) `feat. Felipe Forrozeiro` sem parênteses, já que a linha própria sinaliza o crédito. **Recomendação:** B — mais limpo na segunda linha; o texto integral continua nos aria-labels. _(assumido — validar no gate, o design decide o rótulo final)_
|
||||
- **Título sem crédito muda de layout?** **Opções:** sim (padronizar as duas linhas) | não (só sem truncar). **Recomendação:** não — ausência de `(feat. …)` não inventa linha nem muda o card de hoje; só deixa de cortar. _(assumido — validar no gate)_
|
||||
|
||||
## Referências
|
||||
|
||||
- Issue irmã S25 (player da rádio) — não é dependência; esta fatia não toca no player.
|
||||
- Design UI (gate): `docs/plans/jingle-titulo-credito-artista-ui-design.html`.
|
||||
- `src/components/jingles/JingleCards.tsx` — dono do card (heading, estados, aria-labels, download).
|
||||
- `src/lib/jingle.ts` — derivados do título no view model, se a extração virar função pura.
|
||||
- `src/components/jingles/JingleHomeSection.tsx` — home (headingLevel `h4`, até 3 jingles).
|
||||
- `src/collections/Jingle.ts` — schema (não muda); descrição atual do campo em `:48-50`.
|
||||
- Página em produção: `https://jorgesolla1313.com.br/jingles` (títulos reais verificados em 2026-09-21).
|
||||
- `AGENTS.md` — convenções de identificadores/copy e "edite o dono, sem twin".
|
||||
683
docs/plans/radio-player-proprio-ui-design.html
Normal file
683
docs/plans/radio-player-proprio-ui-design.html
Normal file
|
|
@ -0,0 +1,683 @@
|
|||
<!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 S25 · Player próprio da Rádio 1313</title>
|
||||
<style type="text/tailwindcss">
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #000000;
|
||||
--pt-red: #a21c1c;
|
||||
--pt-red-dark: #47130e;
|
||||
--pt-yellow: #ffe607;
|
||||
--pt-yellow-ink: #000000;
|
||||
--campaign-cream: #fff8f2;
|
||||
--campaign-ink: #000000;
|
||||
--campaign-muted: #6c615e;
|
||||
--campaign-surface: #f9faff;
|
||||
--campaign-band: #ebe9e9;
|
||||
--campaign-line: rgb(0 0 0 / 12%);
|
||||
--font-exo2: 'Exo 2', 'Arial Black', sans-serif;
|
||||
--font-arimo: Arimo, Arial, sans-serif;
|
||||
--radius: 0.875rem;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--font-arimo);
|
||||
}
|
||||
button,
|
||||
a {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
.font-display,
|
||||
.eyebrow,
|
||||
.section-title {
|
||||
font-family: var(--font-exo2);
|
||||
}
|
||||
.eyebrow {
|
||||
font-size: clamp(10px, calc(0.32vw + 8.75px), 12px);
|
||||
line-height: 1.25;
|
||||
}
|
||||
.section-title {
|
||||
font-size: clamp(34px, calc(1.7vw + 18px), 40px);
|
||||
line-height: 1.02;
|
||||
}
|
||||
.section-copy {
|
||||
font-size: clamp(14px, calc(0.32vw + 12.75px), 16px);
|
||||
line-height: 1.55;
|
||||
}
|
||||
.stage {
|
||||
box-shadow: 0 26px 80px rgb(0 0 0 / 30%);
|
||||
}
|
||||
.focus-ring:focus-visible {
|
||||
outline: 3px solid var(--pt-yellow);
|
||||
outline-offset: 3px;
|
||||
box-shadow: 0 0 0 2px var(--pt-red-dark);
|
||||
}
|
||||
|
||||
.radio-player {
|
||||
border: 1px solid var(--campaign-line);
|
||||
border-radius: 14px;
|
||||
background: white;
|
||||
box-shadow: 0 10px 28px rgb(71 19 14 / 7%);
|
||||
}
|
||||
.radio-art {
|
||||
position: relative;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background: var(--campaign-band);
|
||||
}
|
||||
.radio-art::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 13%;
|
||||
border: 1px solid rgb(0 0 0 / 8%);
|
||||
border-radius: 999px;
|
||||
background: white;
|
||||
box-shadow: 0 7px 18px rgb(71 19 14 / 10%);
|
||||
}
|
||||
.radio-art img {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 64%;
|
||||
height: 64%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.play-button {
|
||||
display: inline-flex;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: var(--pt-yellow);
|
||||
color: var(--pt-yellow-ink);
|
||||
box-shadow:
|
||||
0 6px 0 #cfb900,
|
||||
0 10px 22px rgb(0 0 0 / 15%);
|
||||
}
|
||||
.play-button svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: currentColor;
|
||||
}
|
||||
.share-button {
|
||||
display: inline-flex;
|
||||
min-height: 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
border: 1.5px solid rgb(162 28 28 / 32%);
|
||||
border-radius: 10px;
|
||||
background: transparent;
|
||||
padding: 0 14px;
|
||||
color: var(--pt-red);
|
||||
font-family: var(--font-exo2);
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.live-dot {
|
||||
box-shadow: 0 0 0 4px rgb(162 28 28 / 11%);
|
||||
}
|
||||
.spinner {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid rgb(162 28 28 / 18%);
|
||||
border-top-color: var(--pt-red);
|
||||
border-radius: 999px;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.jingle-card {
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--campaign-line);
|
||||
border-radius: 14px;
|
||||
background: white;
|
||||
box-shadow: 0 12px 34px rgb(71 19 14 / 8%);
|
||||
}
|
||||
.jingle-card img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
object-fit: cover;
|
||||
}
|
||||
.mini-play {
|
||||
display: grid;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
flex: none;
|
||||
place-items: center;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: var(--pt-yellow);
|
||||
box-shadow: 0 5px 0 #cfb900;
|
||||
}
|
||||
.download {
|
||||
display: flex;
|
||||
min-height: 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
border: 1.5px solid rgb(162 28 28 / 32%);
|
||||
border-radius: 10px;
|
||||
color: var(--pt-red);
|
||||
font-family: var(--font-exo2);
|
||||
font-weight: 800;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.spinner {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-zinc-950 text-zinc-100 antialiased">
|
||||
<div
|
||||
class="border-b border-emerald-400/40 bg-emerald-400/10 px-4 py-2 text-center text-[11px] font-black tracking-[0.14em] text-emerald-300 uppercase"
|
||||
>
|
||||
Design tier: openai/gpt-5.6-sol · gate humano obrigatório
|
||||
</div>
|
||||
<main class="mx-auto max-w-[1440px] px-4 py-10 sm:px-6 lg:px-10">
|
||||
<header class="max-w-4xl">
|
||||
<p class="font-display m-0 text-xs font-black tracking-[0.12em] text-red-400 uppercase">
|
||||
Gate visual · S25
|
||||
</p>
|
||||
<h1 class="font-display mt-2 text-3xl font-black tracking-[-0.03em]">
|
||||
Player próprio da Rádio 1313
|
||||
</h1>
|
||||
<p class="mt-3 max-w-3xl text-sm leading-6 text-zinc-400">
|
||||
Um player horizontal, discreto e inteiramente da campanha substitui o iframe. O play é o
|
||||
único controle dominante; compartilhar permanece secundário. Nenhum dado de “tocando
|
||||
agora”, duração ou ouvintes é inventado.
|
||||
</p>
|
||||
<div class="mt-5 flex flex-wrap gap-2 text-[11px] font-bold text-zinc-300">
|
||||
<span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2"
|
||||
>1280px · seção cheia</span
|
||||
>
|
||||
<span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2"
|
||||
>390px · compacta</span
|
||||
>
|
||||
<span
|
||||
class="rounded-full border border-amber-400/30 bg-amber-400/10 px-3 py-2 text-amber-200"
|
||||
>NEEDS ASSET · confirmar arte oficial do player</span
|
||||
>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="mt-12" aria-labelledby="scene-full">
|
||||
<div class="mb-5">
|
||||
<p
|
||||
class="font-display text-[11px] font-black tracking-[0.12em] text-emerald-300 uppercase"
|
||||
>
|
||||
Cena 01 · desktop 1280 · 3 jingles · rádio parada
|
||||
</p>
|
||||
<h2 id="scene-full" class="font-display mt-1 text-xl font-black">
|
||||
Player primeiro, grade existente logo abaixo
|
||||
</h2>
|
||||
</div>
|
||||
<div class="overflow-x-auto pb-4">
|
||||
<div
|
||||
class="stage relative mx-auto w-[1280px] overflow-hidden bg-(--campaign-cream) text-black"
|
||||
data-theme="campaign"
|
||||
>
|
||||
<div
|
||||
class="pointer-events-none absolute -top-28 -right-20 h-64 w-64 rounded-full bg-(--pt-yellow)/45"
|
||||
></div>
|
||||
<div class="relative mx-auto max-w-[1160px] px-10 py-16">
|
||||
<div class="mx-auto max-w-2xl text-center">
|
||||
<p class="eyebrow font-black tracking-[0.1em] text-(--pt-red) uppercase">
|
||||
A trilha da nossa caminhada
|
||||
</p>
|
||||
<h3 class="section-title font-black tracking-[-0.03em]">Cante, baixe e espalhe</h3>
|
||||
<p class="section-copy mx-auto mt-3 max-w-xl text-(--campaign-muted)">
|
||||
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ê.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<article class="radio-player mt-9 p-4" aria-label="Player da Rádio Jorge Solla 1313">
|
||||
<div class="grid grid-cols-[112px_1fr_auto] items-center gap-5">
|
||||
<div
|
||||
class="radio-art size-28"
|
||||
aria-label="Arte provisória da Rádio Jorge Solla 1313"
|
||||
>
|
||||
<img
|
||||
src="../../public/campaign-kit/estrela.png"
|
||||
alt="Estrela oficial da campanha Jorge Solla 1313"
|
||||
/>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-2 rounded-full bg-(--pt-red)/8 px-3 py-1 text-[11px] font-black tracking-[0.08em] text-(--pt-red) uppercase"
|
||||
><span class="live-dot size-2 rounded-full bg-(--pt-red)"></span>Ao
|
||||
vivo</span
|
||||
>
|
||||
<span class="text-xs text-(--campaign-muted)">Rádio online</span>
|
||||
</div>
|
||||
<h4
|
||||
class="font-display mt-3 text-[28px] leading-none font-black tracking-[-0.025em]"
|
||||
>
|
||||
Rádio Jorge Solla 1313
|
||||
</h4>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronta para tocar</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-4 pr-2">
|
||||
<button
|
||||
class="share-button focus-ring"
|
||||
type="button"
|
||||
aria-label="Compartilhar Rádio Jorge Solla 1313"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 24 24"
|
||||
class="size-[18px]"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<circle cx="18" cy="5" r="3" />
|
||||
<circle cx="6" cy="12" r="3" />
|
||||
<circle cx="18" cy="19" r="3" />
|
||||
<path d="m8.6 10.5 6.8-4M8.6 13.5l6.8 4" />
|
||||
</svg>
|
||||
Compartilhar
|
||||
</button>
|
||||
<button
|
||||
class="play-button focus-ring"
|
||||
type="button"
|
||||
aria-label="Ouvir Rádio Jorge Solla 1313"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<svg aria-hidden="true" viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z" /></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<p
|
||||
class="mt-2 text-right text-[10px] font-bold tracking-[0.06em] text-(--campaign-muted) uppercase"
|
||||
>
|
||||
NEEDS ASSET · estrela oficial usada como candidato, confirmar arte final
|
||||
</p>
|
||||
|
||||
<div class="mt-12 flex items-end justify-between gap-6">
|
||||
<div>
|
||||
<p class="eyebrow font-black tracking-[0.1em] text-(--pt-red) uppercase">
|
||||
Jingles oficiais
|
||||
</p>
|
||||
<h3 class="font-display mt-1 text-2xl font-black tracking-[-0.02em]">
|
||||
Dê o play. O próximo ritmo é seu.
|
||||
</h3>
|
||||
</div>
|
||||
<span class="text-sm text-(--campaign-muted)">Um áudio toca por vez.</span>
|
||||
</div>
|
||||
<div class="mt-6 grid grid-cols-3 gap-6">
|
||||
<article class="jingle-card">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-axe.jpg"
|
||||
alt="Capa oficial do jingle Axé"
|
||||
/>
|
||||
<div class="p-5">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="mini-play"
|
||||
aria-label="Tocar jingle Jorge Solla 1313 (feat. Nagib Barroso)"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" class="size-6 fill-current">
|
||||
<path d="m8 5 11 7-11 7z" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4
|
||||
class="font-display text-2xl leading-[1.02] font-black tracking-[-0.02em]"
|
||||
>
|
||||
Jorge Solla 1313
|
||||
</h4>
|
||||
<p
|
||||
class="mt-1.5 text-[13px] leading-tight font-bold text-(--campaign-muted)"
|
||||
>
|
||||
feat. Nagib Barroso
|
||||
</p>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 h-1.5 rounded-full bg-[#dedbd8]"></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[10px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo —:—</span><span>Duração —:—</span>
|
||||
</div>
|
||||
<a class="download mt-5">Baixar MP3</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="jingle-card">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-forro.jpg"
|
||||
alt="Capa oficial do jingle Forró"
|
||||
/>
|
||||
<div class="p-5">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="mini-play"
|
||||
aria-label="Tocar jingle Jorge Solla 1313 (feat. Felipe Forrozeiro)"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" class="size-6 fill-current">
|
||||
<path d="m8 5 11 7-11 7z" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4
|
||||
class="font-display text-2xl leading-[1.02] font-black tracking-[-0.02em]"
|
||||
>
|
||||
Jorge Solla 1313
|
||||
</h4>
|
||||
<p
|
||||
class="mt-1.5 text-[13px] leading-tight font-bold text-(--campaign-muted)"
|
||||
>
|
||||
feat. Felipe Forrozeiro
|
||||
</p>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 h-1.5 rounded-full bg-[#dedbd8]"></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[10px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo —:—</span><span>Duração —:—</span>
|
||||
</div>
|
||||
<a class="download mt-5">Baixar MP3</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="jingle-card">
|
||||
<img
|
||||
src="jingles-site-publico-ui-design-assets/capa-pagodao.jpg"
|
||||
alt="Capa oficial do jingle Pagodão"
|
||||
/>
|
||||
<div class="p-5">
|
||||
<div class="flex items-start gap-4">
|
||||
<button
|
||||
class="mini-play"
|
||||
aria-label="Tocar jingle Jorge Solla 1313 (feat. É O MT)"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" class="size-6 fill-current">
|
||||
<path d="m8 5 11 7-11 7z" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="min-w-0 flex-1">
|
||||
<h4
|
||||
class="font-display text-2xl leading-[1.02] font-black tracking-[-0.02em]"
|
||||
>
|
||||
Jorge Solla 1313
|
||||
</h4>
|
||||
<p
|
||||
class="mt-1.5 text-[13px] leading-tight font-bold text-(--campaign-muted)"
|
||||
>
|
||||
feat. É O MT
|
||||
</p>
|
||||
<p class="mt-2 text-sm text-(--campaign-muted)">Pronto para tocar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 h-1.5 rounded-full bg-[#dedbd8]"></div>
|
||||
<div
|
||||
class="mt-2 flex justify-between text-[10px] font-bold text-black/50 uppercase"
|
||||
>
|
||||
<span>Tempo —:—</span><span>Duração —:—</span>
|
||||
</div>
|
||||
<a class="download mt-5">Baixar MP3</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div class="mt-8 text-center">
|
||||
<a
|
||||
class="inline-flex min-h-11 items-center gap-1.5 rounded-md px-2 font-bold text-(--pt-red)"
|
||||
>Ver todos os jingles <span aria-hidden="true">›</span></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16" aria-labelledby="scene-compact">
|
||||
<div class="mb-5">
|
||||
<p class="font-display text-[11px] font-black tracking-[0.12em] text-amber-300 uppercase">
|
||||
Cena 02 · mobile 390 · 0 jingles · rádio tocando
|
||||
</p>
|
||||
<h2 id="scene-compact" class="font-display mt-1 text-xl font-black">
|
||||
Variante compacta sem parecer vazia
|
||||
</h2>
|
||||
</div>
|
||||
<div
|
||||
class="stage relative mx-auto w-[390px] max-w-full overflow-hidden bg-(--campaign-cream) text-black"
|
||||
data-theme="campaign"
|
||||
>
|
||||
<div class="absolute -top-16 -right-16 size-44 rounded-full bg-(--pt-yellow)/45"></div>
|
||||
<div class="relative px-5 py-12">
|
||||
<header class="text-center">
|
||||
<p class="eyebrow font-black tracking-[0.1em] text-(--pt-red) uppercase">
|
||||
A trilha da nossa caminhada
|
||||
</p>
|
||||
<h3 class="section-title mt-2 text-[34px] font-black tracking-[-0.03em]">
|
||||
Sintonize com a Rádio 1313
|
||||
</h3>
|
||||
<p class="section-copy mt-3 text-(--campaign-muted)">
|
||||
Ainda não há jingles publicados por aqui. Enquanto isso, ouça a Rádio Jorge Solla
|
||||
1313.
|
||||
</p>
|
||||
</header>
|
||||
<article class="radio-player mt-8 p-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="radio-art size-[76px] flex-none">
|
||||
<img
|
||||
src="../../public/campaign-kit/estrela.png"
|
||||
alt="Estrela oficial da campanha Jorge Solla 1313"
|
||||
/>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-2 text-[10px] font-black tracking-[0.08em] text-(--pt-red) uppercase"
|
||||
><span class="live-dot size-2 rounded-full bg-(--pt-red)"></span>Ao vivo</span
|
||||
>
|
||||
<h4 class="font-display mt-1 text-lg leading-tight font-black">
|
||||
Rádio Jorge Solla 1313
|
||||
</h4>
|
||||
<p class="mt-1 text-xs font-bold text-(--pt-red)">Em reprodução</p>
|
||||
</div>
|
||||
<button
|
||||
class="play-button focus-ring !size-12"
|
||||
aria-label="Pausar Rádio Jorge Solla 1313"
|
||||
aria-pressed="true"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="M8 5h3v14H8zM14 5h3v14h-3z" /></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-3 flex justify-end border-t border-(--campaign-line) pt-2">
|
||||
<button
|
||||
class="focus-ring inline-flex min-h-11 items-center gap-2 rounded-lg px-2 text-sm font-bold text-(--pt-red)"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 24 24"
|
||||
class="size-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<circle cx="18" cy="5" r="3" />
|
||||
<circle cx="6" cy="12" r="3" />
|
||||
<circle cx="18" cy="19" r="3" />
|
||||
<path d="m8.6 10.5 6.8-4M8.6 13.5l6.8 4" /></svg
|
||||
>Compartilhar
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
<p
|
||||
class="mt-2 text-center text-[10px] font-bold tracking-[0.04em] text-(--campaign-muted) uppercase"
|
||||
>
|
||||
NEEDS ASSET · confirmar arte final do player
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16" aria-labelledby="state-lab">
|
||||
<div class="mb-5">
|
||||
<p class="font-display text-[11px] font-black tracking-[0.12em] text-sky-300 uppercase">
|
||||
Cenas 03–05 · estados críticos
|
||||
</p>
|
||||
<h2 id="state-lab" class="font-display mt-1 text-xl font-black">
|
||||
Conectando, erro e compartilhar são explícitos
|
||||
</h2>
|
||||
</div>
|
||||
<div class="grid gap-6 lg:grid-cols-3">
|
||||
<article class="rounded-2xl border border-zinc-800 bg-zinc-900 p-5">
|
||||
<p class="mb-3 text-[11px] font-black tracking-[0.1em] text-zinc-400 uppercase">
|
||||
Carregando / conectando
|
||||
</p>
|
||||
<div class="radio-player p-3 text-black">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="radio-art size-16 flex-none">
|
||||
<img src="../../public/campaign-kit/estrela.png" alt="" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<span class="text-[10px] font-black tracking-[0.08em] text-(--pt-red) uppercase"
|
||||
>Ao vivo</span
|
||||
>
|
||||
<h3 class="font-display mt-1 text-lg leading-tight font-black">
|
||||
Rádio Jorge Solla 1313
|
||||
</h3>
|
||||
<p class="mt-1 flex items-center gap-2 text-sm font-bold">
|
||||
<span class="spinner"></span>Conectando à rádio…
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
class="play-button !size-12 opacity-60"
|
||||
aria-label="Conectando"
|
||||
aria-busy="true"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z" /></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-xs leading-5 text-zinc-400">
|
||||
Mesmo footprint do estado parado; nunca spinner infinito.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="rounded-2xl border border-zinc-800 bg-zinc-900 p-5">
|
||||
<p class="mb-3 text-[11px] font-black tracking-[0.1em] text-red-300 uppercase">
|
||||
Erro / fail-soft
|
||||
</p>
|
||||
<div class="radio-player p-4 text-black">
|
||||
<div class="flex items-start gap-3">
|
||||
<div
|
||||
class="grid size-10 flex-none place-items-center rounded-full bg-(--pt-red)/10 text-(--pt-red)"
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
class="size-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<circle cx="12" cy="12" r="9" />
|
||||
<path d="M12 7v6M12 17h.01" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-display text-lg font-black">A rádio não conectou</h3>
|
||||
<p class="mt-1 text-sm leading-5 text-(--campaign-muted)">
|
||||
Tente de novo ou ouça na página da rádio.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
class="inline-flex min-h-11 items-center rounded-lg bg-(--pt-red) px-4 font-display text-sm font-black text-white"
|
||||
>
|
||||
Tentar novamente</button
|
||||
><a
|
||||
class="inline-flex min-h-11 items-center rounded-lg px-2 text-sm font-bold text-(--pt-red) underline underline-offset-4"
|
||||
>Ouvir no Zeno</a
|
||||
><button class="share-button ml-auto">Compartilhar</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="rounded-2xl border border-zinc-800 bg-zinc-900 p-5">
|
||||
<p class="mb-3 text-[11px] font-black tracking-[0.1em] text-emerald-300 uppercase">
|
||||
Compartilhar · popover aberto
|
||||
</p>
|
||||
<div
|
||||
class="rounded-xl border border-(--campaign-line) bg-white p-4 text-black shadow-xl"
|
||||
>
|
||||
<h3 class="font-display text-base font-black">Compartilhar a rádio</h3>
|
||||
<p
|
||||
class="mt-2 rounded-lg bg-(--campaign-band) p-3 text-xs leading-5 text-(--campaign-muted)"
|
||||
>
|
||||
Ouça a Rádio Jorge Solla 1313 — https://zeno.fm/radio/jorge-solla-1313/
|
||||
</p>
|
||||
<div class="mt-3 grid gap-2">
|
||||
<button
|
||||
class="flex min-h-11 items-center justify-center rounded-lg bg-(--pt-red) px-4 font-display text-sm font-black text-white"
|
||||
>
|
||||
Compartilhar no WhatsApp</button
|
||||
><button class="share-button w-full">Copiar link</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-xs leading-5 text-zinc-400">
|
||||
Controle próprio e secundário no player; o popover oferece as duas saídas aprovadas.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16 grid gap-6 lg:grid-cols-2">
|
||||
<div class="rounded-2xl border border-zinc-800 bg-zinc-900/70 p-6">
|
||||
<p
|
||||
class="font-display text-[11px] font-black tracking-[0.12em] text-emerald-300 uppercase"
|
||||
>
|
||||
Decisão visual
|
||||
</p>
|
||||
<h2 class="font-display mt-2 text-lg font-black">Discreto, sem cromado de terceiro</h2>
|
||||
<ul class="mt-4 space-y-2 text-sm leading-6 text-zinc-300">
|
||||
<li>• Moldura de 14px, borda e sombra já usadas na seção.</li>
|
||||
<li>• Play amarelo é o único controle dominante.</li>
|
||||
<li>• “Ao vivo” identifica o stream sem inventar programação.</li>
|
||||
<li>• Compartilhar é outline/link, nunca segundo CTA primário.</li>
|
||||
<li>• Sem timeline: rádio ao vivo não promete duração.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="rounded-2xl border border-amber-400/30 bg-amber-400/5 p-6">
|
||||
<p class="font-display text-[11px] font-black tracking-[0.12em] text-amber-300 uppercase">
|
||||
NEEDS ASSET
|
||||
</p>
|
||||
<h2 class="font-display mt-2 text-lg font-black">
|
||||
Arte do player pede confirmação no gate
|
||||
</h2>
|
||||
<p class="mt-4 text-sm leading-6 text-zinc-300">
|
||||
A cena usa provisoriamente a <strong>estrela oficial</strong> do kit 1313 sobre disco
|
||||
branco, conforme o README. Se houver capa específica da rádio no kit, ela substitui
|
||||
somente esse quadrado. Não criar capa, ilustração ou banco de imagem.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
110
docs/plans/radio-player-proprio.md
Normal file
110
docs/plans/radio-player-proprio.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# Player próprio da Rádio 1313 na home (S25)
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-21
|
||||
Issue: #1239
|
||||
Priority: P2
|
||||
Impeccable: C — componente novo (player) dentro da seção de som existente da home
|
||||
Design UI: docs/plans/radio-player-proprio-ui-design.html
|
||||
Appetite: ~1 dia eng; um outcome verificável — a rádio toca num player próprio, discreto, sem marca zeno, com CTA de compartilhar
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
O embed oficial do zeno.fm que o S24 (#1235) montou na home ficou pequeno: o iframe de 150/168px corta título e capa e carrega a marca zeno. O humano quer um player próprio, mais discreto e com a cara da campanha, sobre o mesmo stream (`https://stream.zeno.fm/hys86kx6k16tv`), mais um CTA de compartilhar que manda o link público da rádio no Zeno.
|
||||
|
||||
Esta Issue é a **sucessora explícita** do S24: nova evidência de produto reverte os anti-goals dele ("não vira player custom", "não cria framework de consent/CSP"). Planos de Issues `done`/`in-prod` são imutáveis — `docs/plans/radio-embed-direto.md` não é editado nem reaberto; a reversão de propósito fica registrada aqui.
|
||||
|
||||
Ganho colateral a registrar com honestidade: o iframe do S24 traz GA `G-2T527NZWVM` + redes de anúncio em todo pageview da home (trade-off assumido lá). Com player próprio + `preload="none"`, nenhum request de terceiro sai antes do gesto de play; a conexão com o stream só acontece ali. Isso **reverte o trade-off para melhor**, mas não promete analytics nem contador — não há dado nosso novo.
|
||||
|
||||
## 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 num player que parece da campanha e poder mandar o link da rádio para alguém.
|
||||
- **Fluxo desejado:** abre a home → rola até a seção de som → vê o player discreto "Rádio Jorge Solla 1313" com indicador "Ao vivo" → dá play e ouve (a conexão com o stream começa só agora); se um jingle estiver tocando, ele pausa → toca o "Compartilhar" e escolhe WhatsApp (mensagem pronta) ou copiar link → se o play falhar, vê um estado honesto com link para ouvir no Zeno.
|
||||
- **Anti-goals de produto:** não redesenha a seção de som nem a grade/`/jingles`; não vira proxy nem player de streaming próprio; não autoplay com som; não busca "tocando agora" nem analytics/contador; não cria consent/CSP novo; não mexe em schema.
|
||||
|
||||
### Esboço de fluxo (C)
|
||||
|
||||
```text
|
||||
[visitante na home] → seção de som
|
||||
→ player próprio: "Rádio Jorge Solla 1313" · [Ao vivo] · [▶] · [Compartilhar]
|
||||
→ dá play → conecta no stream (sem request de terceiro antes) · toca
|
||||
[jingle tocando] → pausa o jingle · [play no jingle] → pausa a rádio
|
||||
→ "Compartilhar" → WhatsApp (mensagem pronta) | copiar link → feedback
|
||||
[play falha/estola] → estado de erro + "ouvir no Zeno" + compartilhar (nunca spinner infinito)
|
||||
[0 jingles] → rádio sozinha (compact) · [N jingles] → grade + "Ver todos" → /jingles
|
||||
```
|
||||
|
||||
### Design UI (C)
|
||||
|
||||
- Design UI (gate): `docs/plans/radio-player-proprio-ui-design.html` — cenas: 390 mobile, 1280 desktop, variante compacta (0 jingles) e estados do player (parado, carregando, ao vivo, erro). Capa/arte é NEEDS ASSET: ativo oficial do kit 1313 (`public/campaign-kit/README.md`) ou disco neutro — nunca inventar capa nem usar banco de imagens.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- O iframe zeno some da home; o player próprio é a única superfície de rádio da seção, com título fixo "Rádio Jorge Solla 1313" e indicador "Ao vivo" — sem corte de título/capa.
|
||||
- Só toca com gesto do visitante; com `preload="none"` nenhum request ao stream ou a terceiros acontece antes do play.
|
||||
- Um áudio por vez na seção de som: play na rádio pausa o jingle em reprodução e vice-versa.
|
||||
- Compartilhar envia a mensagem literal `Ouça a Rádio Jorge Solla 1313 — https://zeno.fm/radio/jorge-solla-1313/` (WhatsApp + copiar link com feedback), reusando o padrão público.
|
||||
- Fail-soft: play que falha ou estola vira estado de erro com alternativa honesta (ouvir no Zeno / compartilhar) — nunca spinner infinito.
|
||||
- Kill switch do S21 e variante compact preservados: 0 jingles → rádio sozinha; com jingles, grade e "Ver todos" seguem abaixo; `/jingles` e o player dos jingles ficam intocados além da exclusividade.
|
||||
- Home segue estática (leitura única de `getPublishedJingleItems()`, cache tag `jingles`); sem PII nova, sem Consent novo; MetaPixel da home intocado; sem overflow horizontal a 390px e operável por teclado com rótulos acessíveis.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — **N/A**: nenhum dado nosso é apresentado ou coletado; não há contador de ouvintes, analytics de reprodução nem metadados "tocando agora". A decisão do visitante é ouvir agora, não ler números.
|
||||
- **Decisões desbloqueadas:** N/A — sem métrica que desbloqueie escolha de ator.
|
||||
- **Forma:** N/A — sem dado agregado a definir.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- ID `S25`; slug `radio-player-proprio`; tipo `feature`; Priority `P2`; Impeccable `C`; rota: a home `/` (sem rota nova).
|
||||
- Stream a tocar: `https://stream.zeno.fm/hys86kx6k16tv` → 302 para CDN `stream-*.surfernetwork.com` com token assinado por request; resposta final `content-type: audio/mpeg`, `icy-name: Jorge Solla 1313`, 128 kbps, 44.1 kHz; **sem headers CORS/ACAO** (playback em `<audio>` funciona; Web Audio/`AnalyserNode` é impossível — fora de escopo).
|
||||
- Página pública da rádio (destino do compartilhar): `https://zeno.fm/radio/jorge-solla-1313/` (HTTP 200, título "Listen to Jorge Solla 1313 | Zeno.FM").
|
||||
- Nome exibido fixo: **"Rádio Jorge Solla 1313"** (confirmado pelo `icy-name` do stream). Sem metadado de "tocando agora".
|
||||
- Mensagem de compartilhamento literal: `Ouça a Rádio Jorge Solla 1313 — https://zeno.fm/radio/jorge-solla-1313/`.
|
||||
- iframe que sai: `https://zeno.fm/player/jorge-solla-1313/` (moldura 150/168px é o defeito); com ele sai o rastro de terceiros por pageview do S24 — GA `G-2T527NZWVM` + redes de anúncio.
|
||||
- Design UI (gate): `docs/plans/radio-player-proprio-ui-design.html`.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/components/jingles/` — `RadioEmbed.tsx` (iframe) é o que sai de cena; `JingleHomeSection.tsx:63` troca a composição; o player novo nasce ao lado, reusando o padrão de `<audio>` já existente em `JingleCards.tsx:92-140` (play exclusivo com `activeId`, `preload="none"`, revert do `play()` rejeitado). CSS: só `.campaign-sound-title` em `styles.css:1158-1164` é da seção; tokens `--campaign-line`/`--campaign-band` (`:184-185`) seguem.
|
||||
- **Precedente a olhar:** `ContentShareButton.tsx:44-108` + builders `src/lib/contentShare.ts:11-48` + `wa.me` sem destinatário (`src/lib/phone.ts:62-67`) + feedback de cópia (`src/lib/copyFeedback.ts:68`); S24 `docs/plans/radio-embed-direto.md` e S22 `docs/plans/jingles-radio-homepage.md` (histórico; não editar).
|
||||
- **Risco de acoplamento:** a exclusividade rádio↔jingle precisa de coordenação sem tocar em `/jingles`; os testes pinam o iframe e terão de ser reescritos (`tests/unit/radioEmbed.unit.spec.tsx`, `tests/unit/jingleHomeSection.unit.spec.tsx:42-53`, `tests/e2e/frontend.e2e.spec.ts:560-616`, `tests/e2e/frontendJingles.e2e.spec.ts:248-291`) e a fixture do e2e só stuba o player zeno (`tests/e2e/fixtures/e2eTest.ts:118-129`); `scripts/lib/e2e-affected-manifest.mjs:99-108` mapeia `src/components/jingles` → `frontendJingles`; home estática/cache `jingles`; sem CSP/middleware no caminho.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma dura. S24 = Issue #1235 (entregue 2026-09-20) — sucessora explícita; decisão revertida de propósito, plano imutável, não reabrir. Estação ativa no zeno.fm. Design hi-fi aprovado no gate.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Visualizador/Web Audio (sem CORS no stream); "tocando agora" via API do Zeno; analytics de reprodução/contador de ouvintes.
|
||||
- Proxy/stream próprio ou troca de provedor; download da rádio (é stream).
|
||||
- Consent/CSP/banner de terceiros; migration/schema; qualquer Consent novo.
|
||||
- Mudanças em `/jingles` e na grade além da coordenação de exclusividade.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **Virar proxy/CDN do áudio.** Se alguém "só completar": infra de streaming, tokens, cache, uptime. **Corte neste item:** `<audio>` apontando direto para o stream do Zeno.
|
||||
- **"Tocando agora" e programação.** Se alguém "só completar": API do Zeno, polling, metadado frágil. **Corte:** nome fixo + "Ao vivo".
|
||||
- **Analytics de ouvintes.** Se alguém "só completar": contador, dashboard, vaidade. **Corte:** a rádio é um play, não um painel.
|
||||
- **Redesenhar a seção de som inteira.** Se alguém "só completar": copy, headings, hero, grade. **Corte:** só o player e o CTA mudam.
|
||||
- **Capa inventada ou banco de imagens.** **Corte:** ativo oficial do kit 1313 ou disco neutro.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Acesso a "ouvir no Zeno" fora do erro?** **Opções:** A) só no estado de erro, mantendo o player discreto | B) link persistente ao lado do player. **Recomendação:** A — o CTA de compartilhar já expõe a página da rádio; validar no design.
|
||||
- **Escopo da exclusividade rádio↔jingle?** **Opções:** A) coordenação só na seção da home | B) coordenação global (inclui `/jingles`). **Recomendação:** A — `/jingles` fica intocado; o mecanismo é da implementação.
|
||||
- **Forma do controle de compartilhar?** **Opções:** A) popover com WhatsApp + copiar link (padrão dos cards) | B) botão único que abre o WhatsApp. **Recomendação:** A — reusa o padrão público com feedback; design decide a forma visual. _(assumido — validar com produto)_
|
||||
- **Capa/arte do player?** **Opções:** A) ativo oficial do kit 1313 (`public/campaign-kit/README.md`, ex.: `estrela.png`/`marca-*`) | B) disco neutro. **Recomendação:** A — asset oficial, sem inventar arte. Design resolve (NEEDS ASSET).
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue: a registrar (`S25`); S24 = Issue #1235 (entregue; decisão revertida de propósito, não reabrir).
|
||||
- Design UI (gate): `docs/plans/radio-player-proprio-ui-design.html` (+ assets em `docs/plans/radio-player-proprio-ui-design-assets/` se houver).
|
||||
- `docs/plans/radio-embed-direto.md`, `docs/plans/jingles-radio-homepage.md` — histórico do embed/facade (não editar).
|
||||
- `src/components/jingles/RadioEmbed.tsx`, `JingleHomeSection.tsx`, `JingleCards.tsx` — o que sai/encaixa/reusa.
|
||||
- `src/components/ContentShareButton.tsx`, `src/lib/contentShare.ts`, `src/lib/phone.ts`, `src/lib/copyFeedback.ts` — padrão público de compartilhar.
|
||||
- `public/campaign-kit/README.md` — dona da marca/ativos.
|
||||
- `tests/unit/radioEmbed.unit.spec.tsx`, `tests/unit/jingleHomeSection.unit.spec.tsx`, `tests/e2e/frontend.e2e.spec.ts`, `tests/e2e/frontendJingles.e2e.spec.ts`, `tests/e2e/fixtures/e2eTest.ts`, `scripts/lib/e2e-affected-manifest.mjs` — contratos que pinam o iframe.
|
||||
- `AGENTS.md` — home estática/cache tag `jingles` e postura LGPD.
|
||||
Loading…
Reference in a new issue