mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
docs(S33,S34,S35): planos + designs hi-fi — ajuste da foto sem limite, colinha com a arte exata e header do modal (Related #1297, #1298, #1299)
This commit is contained in:
parent
3864a823ff
commit
d3e092e36d
6 changed files with 772 additions and 0 deletions
140
docs/plans/cards-colinha-arte-exata-ui-design.html
Normal file
140
docs/plans/cards-colinha-arte-exata-ui-design.html
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<!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 S34 · Colinha com a arte exata</title>
|
||||
<style type="text/tailwindcss">
|
||||
:root {
|
||||
--background: #fff; --foreground: #000; --pt-red: #a21c1c; --pt-red-dark: #47130e;
|
||||
--pt-yellow: #ffe607; --campaign-cream: #fff8f2; --campaign-ink: #000;
|
||||
--campaign-muted: #6c615e; --campaign-band: #ebe9e9; --campaign-line: rgb(0 0 0 / 12%);
|
||||
--field-border: rgb(0 0 0 / 18%); --brand-red: #e4102f; --brand-blue: #184e92;
|
||||
--confirm: #009647;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: Arial, Helvetica, sans-serif; }
|
||||
button, input { font: inherit; }
|
||||
button:focus-visible, input:focus-visible { outline: 2px solid var(--pt-red); outline-offset: 2px; }
|
||||
.stage-shadow { box-shadow: 0 26px 80px rgb(0 0 0 / 32%); }
|
||||
.colinha {
|
||||
position: relative; aspect-ratio: 9 / 16; overflow: hidden; background: #fff;
|
||||
container-type: inline-size;
|
||||
}
|
||||
.colinha > img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
||||
.state-mask {
|
||||
position: absolute; z-index: 2; top: 55.9%; left: 24.5%; width: 57.4%; height: 2.9%;
|
||||
background: #fff;
|
||||
}
|
||||
.state-copy {
|
||||
position: absolute; z-index: 3; top: 56.46%; left: 26.9%; width: 52.8%; display: flex;
|
||||
align-items: baseline; justify-content: flex-end; gap: 1.5cqw; white-space: nowrap;
|
||||
font-family: Arial, Helvetica, sans-serif; line-height: 1;
|
||||
}
|
||||
.state-office { font-size: 2.15cqw; font-weight: 400; color: #202020; }
|
||||
.state-name { font-size: 3.4cqw; font-weight: 900; letter-spacing: -0.04em; color: #e4102f; }
|
||||
.state-name-b {
|
||||
position: absolute; z-index: 3; top: 56.46%; right: 56.5%; max-width: 31%;
|
||||
overflow: hidden; white-space: nowrap; text-align: right; font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 3.1cqw; line-height: 1; font-weight: 900; letter-spacing: -0.04em; color: #e4102f;
|
||||
}
|
||||
.digit-overlay {
|
||||
position: absolute; z-index: 3; top: 58.4%; display: grid; width: 6.1%; height: 4.35%;
|
||||
place-items: center; font-family: Arial Black, Arial, Helvetica, sans-serif; font-size: 4.25cqw;
|
||||
line-height: 1; font-weight: 900; color: #171717;
|
||||
}
|
||||
.d1 { left: 25.9%; } .d2 { left: 32.8%; } .d3 { left: 39.7%; } .d4 { left: 46.6%; } .d5 { left: 53.5%; }
|
||||
.primary, .secondary {
|
||||
display: inline-flex; min-height: 44px; flex: 1; align-items: center; justify-content: center;
|
||||
border-radius: 8px; padding: 0 20px; font-size: 14px; font-weight: 800;
|
||||
}
|
||||
.primary { border: 0; background: var(--pt-red); color: #fff; }
|
||||
.primary:disabled { cursor: not-allowed; opacity: .5; }
|
||||
.secondary { border: 2px solid var(--campaign-line); background: #fff; color: var(--pt-red); }
|
||||
.select {
|
||||
display: flex; min-height: 44px; width: 100%; align-items: center; border: 1px solid var(--field-border);
|
||||
border-radius: 8px; background: #fff; padding: 0 12px; text-align: left; font-size: 14px;
|
||||
}
|
||||
.line-crop { position: relative; height: 150px; overflow: hidden; background: #fff; }
|
||||
.line-crop > img, .line-crop > .colinha { position: absolute; left: 0; width: 620px; max-width: 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-[.14em] text-emerald-300 uppercase">Design tier: openai/gpt-5.6-sol · frontier · 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="text-xs font-black tracking-[.12em] text-red-400 uppercase">Gate visual · S34</p>
|
||||
<h1 class="mt-2 text-3xl font-black tracking-tight">A colinha é a arte entregue — não uma recriação</h1>
|
||||
<p class="mt-3 max-w-3xl text-sm leading-6 text-zinc-400">A imagem 900×1600 permanece inteira e intocada. Sem estadual, ela aparece exatamente como foi entregue. Com JULIO PINHEIRO 13999, somente a segunda linha recebe nome e dígitos. O gate escolhe entre A e B.</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">arte exata · 900×1600</span><span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2">saída · 1080×1920</span><span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2">desktop 1280 + mobile 390</span><span class="rounded-full border border-amber-500/40 bg-amber-400/10 px-3 py-2 text-amber-300">NEEDS ASSET (fonte)</span></div>
|
||||
</header>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-sky-300 uppercase">Cena 01 · desktop 1280 × 850 · vazio</p>
|
||||
<h2 class="mt-1 text-xl font-black">A arte como está · CTA desabilitado</h2>
|
||||
<p class="mt-1 max-w-4xl text-xs leading-5 text-zinc-500">Caixas vazias e o selo CONFIRMA pleno já pertencem ao JPEG. Nenhum pixel é acrescentado no estado vazio.</p>
|
||||
<div class="stage-shadow relative mt-5 mx-auto h-[850px] w-[1280px] max-w-full overflow-hidden rounded-2xl bg-[var(--campaign-cream)] text-black"><div class="absolute inset-0 bg-black/48"></div>
|
||||
<article role="dialog" class="absolute top-1/2 left-1/2 flex max-h-[800px] w-[512px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl bg-white shadow-2xl">
|
||||
<header class="flex items-start gap-3 px-5 pt-5"><div class="min-w-0 flex-1"><p class="text-xs font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Minha colinha</p><h3 class="mt-1 text-xl font-black">Escolha seu estadual</h3><p class="mt-1 text-sm text-[var(--campaign-muted)]">A linha de deputado estadual será preenchida na hora.</p></div><button aria-label="Fechar" class="size-11 text-2xl text-[var(--campaign-muted)]">×</button></header>
|
||||
<div class="min-h-0 flex-1 overflow-y-auto px-5 pt-4 pb-5"><div class="mx-auto w-[236px] overflow-hidden rounded-lg border border-[var(--campaign-line)] shadow"><div class="colinha"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Colinha oficial com a linha de deputado estadual vazia" /></div></div><label class="mt-4 block text-sm font-bold">Seu estadual</label><button class="select mt-2"><span class="text-stone-500">Escolha um nome</span><span class="ml-auto">⌄</span></button><p class="mt-4 rounded-lg bg-[var(--campaign-cream)] p-3 text-xs leading-5 text-[var(--campaign-muted)]"><strong class="block text-black">Escolha um estadual para baixar.</strong>A linha vazia será preenchida com o nome e os cinco dígitos.</p><p class="mt-3 text-xs leading-5 text-[var(--campaign-muted)]">A escolha é processada neste aparelho. Nenhum nome, foto ou cadastro é solicitado.</p></div>
|
||||
<footer class="flex gap-3 border-t border-[var(--campaign-line)] px-5 py-4"><button class="secondary">Cancelar</button><button class="primary" disabled>Baixar minha colinha</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-emerald-300 uppercase">Cena 02 · mobile 390 × 844 · vazio</p>
|
||||
<h2 class="mt-1 text-xl font-black">Drawer · arte inteira, sem preenchimento</h2>
|
||||
<div class="stage-shadow relative mt-5 h-[844px] w-[390px] max-w-full overflow-hidden rounded-[24px] bg-[var(--campaign-cream)] text-black"><div class="absolute inset-0 bg-black/50"></div>
|
||||
<article class="absolute inset-0 flex flex-col overflow-hidden rounded-t-xl bg-white"><div class="flex h-3 shrink-0 items-end justify-center"><span class="h-1 w-24 rounded-full bg-[var(--campaign-band)]"></span></div><header class="flex shrink-0 items-start gap-3 px-5 pt-5"><div class="min-w-0 flex-1"><p class="text-[10px] font-black text-[var(--pt-red)] uppercase">Minha colinha</p><h3 class="mt-1 text-lg font-black">Escolha seu estadual</h3></div><button class="size-11 text-2xl text-[var(--campaign-muted)]">×</button></header>
|
||||
<div class="min-h-0 flex-1 overflow-hidden px-5 pt-3 pb-4"><div class="mx-auto w-[248px] overflow-hidden rounded-lg border border-[var(--campaign-line)] shadow"><div class="colinha"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Colinha oficial vazia" /></div></div><label class="mt-3 block text-sm font-bold">Seu estadual</label><button class="select mt-2"><span class="text-stone-500">Escolha um nome</span><span class="ml-auto">⌄</span></button><p class="mt-3 rounded-lg bg-[var(--campaign-cream)] p-3 text-xs leading-5 text-[var(--campaign-muted)]"><strong class="block text-black">Escolha um estadual para baixar.</strong>A linha vazia será preenchida com o nome e os cinco dígitos.</p></div>
|
||||
<footer class="border-t border-[var(--campaign-line)] px-5 py-4"><button class="primary w-full" disabled>Baixar minha colinha</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-red-300 uppercase">Cena 03 · opção A recomendada · desktop 1280</p>
|
||||
<h2 class="mt-1 text-xl font-black">Linha no mesmo idioma visual das linhas fixas</h2>
|
||||
<p class="mt-1 max-w-4xl text-xs leading-5 text-zinc-500">A base continua sendo o JPEG. Na faixa branca da segunda linha, o rótulo é reposto à esquerda e JULIO PINHEIRO entra à direita; os cinco dígitos pousam nas caixas existentes.</p>
|
||||
<div class="stage-shadow mt-5 grid max-w-[1280px] gap-8 rounded-2xl bg-[var(--campaign-cream)] p-8 text-black lg:grid-cols-[430px_1fr]">
|
||||
<div class="mx-auto w-[405px] max-w-full overflow-hidden rounded-xl border border-black/10 shadow-2xl"><div class="colinha"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Colinha oficial preenchida com Julio Pinheiro 13999" /><span class="state-mask"></span><span class="state-copy"><span class="state-office">DEPUTADO ESTADUAL</span><span class="state-name">JULIO PINHEIRO</span></span><span class="digit-overlay d1">1</span><span class="digit-overlay d2">3</span><span class="digit-overlay d3">9</span><span class="digit-overlay d4">9</span><span class="digit-overlay d5">9</span></div></div>
|
||||
<div class="flex flex-col justify-center"><p class="text-xs font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Minha colinha · opção A</p><h3 class="mt-1 text-2xl font-black">Pronta para levar com você</h3><p class="mt-2 max-w-lg text-sm leading-6 text-[var(--campaign-muted)]">Confira o estadual escolhido. As demais escolhas já vêm preenchidas na imagem oficial — sem retexto, sem novo topo e sem novos selos.</p><button class="select mt-5 max-w-md font-bold"><span>Julio Pinheiro</span><span class="ml-auto text-xs text-[var(--campaign-muted)]">13999 · Trocar</span></button><div class="mt-5 max-w-md rounded-lg bg-white p-4 ring-1 ring-[var(--campaign-line)]"><p class="text-sm font-bold">Linha conferida</p><p class="mt-1 text-sm text-[var(--campaign-muted)]">DEPUTADO ESTADUAL · JULIO PINHEIRO · 13999</p></div><button class="primary mt-5 max-w-md">Baixar minha colinha</button><p class="mt-3 max-w-md text-xs leading-5 text-[var(--campaign-muted)]">A escolha é processada neste aparelho. Nenhum nome, foto ou cadastro é solicitado.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-red-300 uppercase">Cena 04 · opção A · mobile 390 × 844</p>
|
||||
<h2 class="mt-1 text-xl font-black">Preenchida e pronta para baixar</h2>
|
||||
<div class="stage-shadow relative mt-5 h-[844px] w-[390px] max-w-full overflow-hidden rounded-[24px] bg-[var(--campaign-cream)] text-black"><div class="absolute inset-0 bg-black/50"></div><article class="absolute inset-0 flex flex-col overflow-hidden bg-white"><div class="flex h-3 shrink-0 items-end justify-center"><span class="h-1 w-24 rounded-full bg-[var(--campaign-band)]"></span></div><header class="flex shrink-0 items-start gap-3 px-5 pt-5"><div class="min-w-0 flex-1"><p class="text-[10px] font-black text-[var(--pt-red)] uppercase">Minha colinha</p><h3 class="mt-1 text-lg font-black">Pronta para baixar</h3></div><button class="size-11 text-2xl text-[var(--campaign-muted)]">×</button></header><div class="min-h-0 flex-1 overflow-y-auto px-5 pt-3 pb-4"><div class="mx-auto w-[300px] overflow-hidden rounded-lg border border-[var(--campaign-line)] shadow"><div class="colinha"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Colinha oficial preenchida com Julio Pinheiro 13999" /><span class="state-mask"></span><span class="state-copy"><span class="state-office">DEPUTADO ESTADUAL</span><span class="state-name">JULIO PINHEIRO</span></span><span class="digit-overlay d1">1</span><span class="digit-overlay d2">3</span><span class="digit-overlay d3">9</span><span class="digit-overlay d4">9</span><span class="digit-overlay d5">9</span></div></div><button class="select mt-4 font-bold"><span>Julio Pinheiro</span><span class="ml-auto text-xs text-[var(--campaign-muted)]">13999 · Trocar</span></button><div class="mt-3 rounded-lg bg-white p-3 ring-1 ring-[var(--campaign-line)]"><p class="text-sm font-bold">Linha conferida</p><p class="mt-1 text-xs text-[var(--campaign-muted)]">DEPUTADO ESTADUAL · JULIO PINHEIRO · 13999</p></div></div><footer class="border-t border-[var(--campaign-line)] px-5 py-4"><button class="primary w-full">Baixar minha colinha</button></footer></article></div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-amber-300 uppercase">Cena 05 · escolha do gate · A × B</p>
|
||||
<h2 class="mt-1 text-xl font-black">Duas leituras para a única linha nova</h2>
|
||||
<p class="mt-1 max-w-4xl text-xs leading-5 text-zinc-500">Recomendação: A. A variante B conserva o rótulo original, mas força a leitura “JULIO PINHEIRO DEPUTADO ESTADUAL”.</p>
|
||||
<div class="mt-5 grid gap-6 lg:grid-cols-2">
|
||||
<article class="rounded-2xl border-2 border-emerald-500 bg-white p-5 text-black shadow-xl"><div class="flex items-start justify-between gap-3"><div><p class="text-[11px] font-black text-emerald-800 uppercase">Opção A · recomendada</p><h3 class="mt-1 text-lg font-black">Rótulo à esquerda + nome à direita</h3></div><span class="rounded-full bg-emerald-700 px-3 py-1 text-[10px] font-black text-white">RECOMENDADA</span></div><div class="mx-auto mt-5 w-[360px] max-w-full overflow-hidden rounded-lg border"><div class="colinha"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Opção A" /><span class="state-mask"></span><span class="state-copy"><span class="state-office">DEPUTADO ESTADUAL</span><span class="state-name">JULIO PINHEIRO</span></span><span class="digit-overlay d1">1</span><span class="digit-overlay d2">3</span><span class="digit-overlay d3">9</span><span class="digit-overlay d4">9</span><span class="digit-overlay d5">9</span></div></div><p class="mt-4 text-sm leading-6 text-[var(--campaign-muted)]">Repete a sintaxe de “DEPUTADO FEDERAL Jorge Solla” e das demais linhas: cargo primeiro, nome em vermelho depois.</p></article>
|
||||
<article class="rounded-2xl border border-zinc-700 bg-white p-5 text-black shadow-xl"><div><p class="text-[11px] font-black text-stone-500 uppercase">Variante B · secundária</p><h3 class="mt-1 text-lg font-black">Nome no vão à esquerda do rótulo original</h3></div><div class="mx-auto mt-5 w-[360px] max-w-full overflow-hidden rounded-lg border"><div class="colinha"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Variante B" /><span class="state-name-b">JULIO PINHEIRO</span><span class="digit-overlay d1">1</span><span class="digit-overlay d2">3</span><span class="digit-overlay d3">9</span><span class="digit-overlay d4">9</span><span class="digit-overlay d5">9</span></div></div><p class="mt-4 text-sm leading-6 text-[var(--campaign-muted)]">Preserva cada pixel do rótulo já impresso, porém inverte a ordem visual e aperta o nome.</p></article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14 rounded-2xl border border-zinc-800 bg-zinc-900 p-6">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-sky-300 uppercase">Cena 06 · detalhe tipográfico · conferência</p>
|
||||
<h2 class="mt-1 text-xl font-black">Linha fixa da arte × linha preenchida</h2>
|
||||
<p class="mt-2 max-w-3xl text-sm leading-6 text-zinc-400">O alvo é equivalência de cor, peso, tamanho e linha de base — não uma aproximação “parecida”. A face pesada exata não está disponível no navegador deste artefato.</p>
|
||||
<div class="mt-6 grid gap-5 lg:grid-cols-2">
|
||||
<figure class="m-0 min-w-0 rounded-xl bg-white p-4 text-black"><figcaption class="mb-3 text-[11px] font-black tracking-wide text-stone-500 uppercase">Referência fixa · pixels do JPEG</figcaption><div class="line-crop rounded-lg border"><img style="top:-520px" src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Linha fixa Deputado Federal Jorge Solla" /></div><p class="mt-3 text-xs text-stone-500">DEPUTADO FEDERAL · Jorge Solla · 1313</p></figure>
|
||||
<figure class="m-0 min-w-0 rounded-xl border-2 border-amber-500 bg-white p-4 text-black"><figcaption class="mb-3 flex items-center justify-between gap-2 text-[11px] font-black tracking-wide text-amber-800 uppercase"><span>Alvo novo · opção A</span><span class="rounded-full bg-amber-100 px-2 py-1">NEEDS ASSET (fonte)</span></figcaption><div class="line-crop rounded-lg border"><div class="colinha" style="top:-590px"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Linha preenchida Deputado Estadual Julio Pinheiro" /><span class="state-mask"></span><span class="state-copy"><span class="state-office">DEPUTADO ESTADUAL</span><span class="state-name">JULIO PINHEIRO</span></span><span class="digit-overlay d1">1</span><span class="digit-overlay d2">3</span><span class="digit-overlay d3">9</span><span class="digit-overlay d4">9</span><span class="digit-overlay d5">9</span></div></div><p class="mt-3 text-xs text-stone-500">DEPUTADO ESTADUAL · JULIO PINHEIRO · 13999</p></figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside class="mt-14 border-t border-zinc-800 pt-8 text-xs leading-5 text-zinc-500">
|
||||
<p><strong class="text-zinc-300">Base única:</strong> <code>cards-colinha-ui-design-assets/modelo-colinha.jpeg</code>, o JPEG 900×1600 entregue e aprovado. Topo, linhas fixas, linha legal, caixas e selos vêm somente dele.</p>
|
||||
<p class="mt-2"><strong class="text-amber-300">NEEDS ASSET (fonte):</strong> a face pesada exata usada nos nomes e dígitos da arte não existe no navegador do artefato. O port deve provar a equivalência lado a lado; este gate decide composição e geometria.</p>
|
||||
<p class="mt-2"><strong class="text-zinc-300">Decisão humana:</strong> A (recomendada) redesenha apenas a faixa branca do rótulo da segunda linha; B mantém o rótulo impresso e põe o nome à esquerda. Nada além dessa linha muda.</p>
|
||||
</aside>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
98
docs/plans/cards-colinha-arte-exata.md
Normal file
98
docs/plans/cards-colinha-arte-exata.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# S34 — Minha colinha: a arte exata entregue pelo humano + a linha do estadual preenchida
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-23
|
||||
Issue: #1298
|
||||
Priority: P1
|
||||
Impeccable: C — ajuste visual num modelo existente do funil público (sem superfície nova)
|
||||
Design UI: docs/plans/cards-colinha-arte-exata-ui-design.html
|
||||
Appetite: ~0,5–1 dia eng; a arte aprovada vira a base e só a linha do estadual é preenchida
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
O humano aprovou uma arte exata para a colinha (o arquivo dele, `modelo-colinha.jpeg`) e o que chegou ao ar foi uma recriação do zero — parecida, mas lida como outro card. O verbatim: «E na criação da colinha parece que você gerou uma nova colinha do zero em vez de usar a imagem de colinha que eu te forneci. Era pra usar exatamente a imagem que eu forneci, apenas adicionando o preenchimento da linha de deputado estadual.»
|
||||
|
||||
A correção é de premissa, não de polimento: a arte aprovada passa a ser a base da prévia e do download, e o único desenho novo é o preenchimento da linha `DEPUTADO ESTADUAL` (2ª linha) com o nome de urna e os cinco dígitos. Nada mais é redesenhado — topo, cinco linhas fixas, linha legal e selos vêm da imagem, intocados.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** militante/eleitor no celular, prestes a pedir voto na rua ou no grupo; quer a colinha exata que a coordenação aprovou, com o estadual dele preenchido.
|
||||
- **Job principal:** baixar a colinha oficial com a linha do estadual preenchida, sem que a arte mude em nada.
|
||||
- **Fluxo desejado:** home (`#cards`) ou `/cards` → escolhe `Minha colinha` → escolhe o estadual na lista da dobradinha (S30) → vê a prévia 9:16 igual à arte aprovada, com a linha preenchida → baixa o PNG 1080×1920.
|
||||
- **Anti-goals de produto:** segundo editor/estúdio; redesenhar ou re-digitar o conteúdo fixo da arte; editar o arquivo de imagem; CMS/migration; PDF/A4; nome/foto do visitante; analytics novo.
|
||||
|
||||
### Design UI (C)
|
||||
|
||||
- Design UI (gate): `docs/plans/cards-colinha-arte-exata-ui-design.html`
|
||||
- Cenas: prévia vazia (a arte como está), prévia com a linha do estadual preenchida e o detalhe da linha lado a lado com uma linha fixa da própria arte (tipografia, peso e tamanho).
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- A prévia e o PNG baixado (1080×1920) são a imagem fornecida — o asset aprovado, sem recriação, ampliado exatamente 1,2× (900×1600 → 1080×1920) — com SÓ a linha `DEPUTADO ESTADUAL` preenchida: nome de urna em caixa alta + os cinco dígitos, um por caixa existente.
|
||||
- O topo, as cinco linhas fixas, a linha legal e os selos `CONFIRMA` vêm da arte, intocados; nenhum outro pixel é redesenhado.
|
||||
- Sem estadual escolhido, a prévia mostra a linha em branco como está na arte e o download fica desabilitado.
|
||||
- A linha preenchida lê como parte da arte: mesma tipografia/peso/cor/tamanho das linhas fixas, mesma linha de base, dígitos centrados nas caixas e nome cabendo sem colidir com o rótulo nem com a borda do desenho.
|
||||
- O asset continua sendo o tile da galeria; um só editor/fluxo, 100% no aparelho, sem superfície nova de seleção; o analytics de S32 fica intocado.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não.
|
||||
- **Decisões desbloqueadas:** N/A — nenhuma métrica; o catálogo de estaduais é conteúdo (arte + número), não análise.
|
||||
- **Forma:** _adiada ao plano de implementação_ — a escolha do estadual segue insumo local da imagem; medir uso é S32.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- Model id `minha-colinha`; rótulo `Minha colinha`.
|
||||
- Base aprovada: `public/cards/modelo-colinha.jpeg` — cópia byte a byte do arquivo entregue (`docs/plans/cards-colinha-ui-design-assets/modelo-colinha.jpeg`), 900×1600, sha256 `76505492fb243c67313d237e58926afbd4d0847c00ab3bb43c090859cbdf18c8`; segue o tile da galeria.
|
||||
- Saída PNG 1080×1920: a arte ampliada exatamente 1,2×, sem recorte e sem reescala parcial.
|
||||
- Linha preenchida: `DEPUTADO ESTADUAL` (2ª linha do card) — nome de urna em caixa alta + os 5 dígitos do catálogo compartilhado com S30 (`stateDeputyCatalog`), um dígito por caixa existente.
|
||||
- Estado vazio: a arte como está (caixas vazias e selo `CONFIRMA` pleno, como na arte) e download desabilitado.
|
||||
- Sem nome/foto do visitante; topo e linhas fixas vêm da arte.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/lib/cardRender.ts` (`renderColinhaCard` → base + preenchimento da linha), `src/lib/cardColinha.ts` (geometria/linhas — a maior parte do layout do zero morre; fica só o que o preenchimento precisa), `src/lib/cardModels.ts` (`assetSrc`/`lockupSrc` do modelo), `src/components/cards/CardComposer.tsx` (o branch da colinha carrega a base), testes.
|
||||
- **Precedente a olhar:** S31 (#1272) e S30 (#1271) — modelo, catálogo e seletor já existem.
|
||||
- **Risco de acoplamento:** a composição do zero deve ser REMOVIDA, não duplicada (sem segunda via morta); os pins de unit/e2e da composição antiga precisam ser reescritos; `#1277` (fatiar o `CardComposer`) mexe no mesmo arquivo — coordenar/rebasear.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma dura (S30/S31 entregues). Soft: `#1277` (mesmo arquivo — fatiar o `CardComposer`).
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Redesenhar/editar a arte; mexer no topo, nas linhas fixas, na linha legal ou nos selos.
|
||||
- PDF/A4 ou impressão; nome/foto do visitante; analytics novo (S32 intocado); segundo editor/rota.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **Reconstruir a arte em vetor por cima do raster.** Se alguém "só completar": vira redesenho tipográfico infinito e o resultado deixa de ser a arte aprovada. **Corte neste item:** a arte exata é a base.
|
||||
- **Melhorar a arte do humano.** Se alguém "só completar": reposiciona elementos, "corrige" cores e o humano deixa de reconhecer o próprio arquivo. **Corte neste item:** só a linha do estadual é tocada.
|
||||
- **A4 no mesmo item.** Se alguém "só completar": entra diagramação de impressão e margem de impressora. **Corte neste item:** só PNG 9:16.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Onde entra o nome, já que a arte em branco tem o rótulo `DEPUTADO ESTADUAL` no fim da linha (alinhado à direita) e o espaço vago à esquerda dele?** **Opções:** A) redesenhar a linha no padrão das linhas fixas — rótulo à esquerda + nome à direita, alinhados à direita (edição invisível sobre o fundo branco) | B) preencher só o vão à esquerda do rótulo, base intocada (leitura "NOME DEPUTADO ESTADUAL") | C) só os dígitos, sem nome. **Recomendação:** A — casa com as outras cinco linhas e é o que faz a linha ler como preenchida. _(assumido — validar com produto)_
|
||||
- **Fonte da linha preenchida?** **Opções:** A) aceitar a face mais próxima e provar lado a lado no PR | B) carregar uma face Black só para o preenchimento. **Recomendação:** A — menor custo; a conferência lado a lado é o aceite. _(assumido — validar com produto)_
|
||||
- **O rótulo pode ser reescrito por cima do fundo?** **Opções:** A) sim, é o que faz a linha ler como as outras | B) não tocar no que já está na arte. **Recomendação:** A. _(assumido — validar com produto)_
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue #1272 (S31 — modelo `Minha colinha` entregue)
|
||||
- `docs/plans/cards-colinha.md` e `docs/plans/cards-colinha-impl.md` — S31 e a Decisão 2 (recusou usar a arte como base)
|
||||
- `docs/plans/cards-estadual-dobradinha.md` — S30 (catálogo `stateDeputyCatalog`)
|
||||
- `docs/plans/cards-analytics.md` — S32 (intocado)
|
||||
- Arte aprovada: `docs/plans/cards-colinha-ui-design-assets/modelo-colinha.jpeg` (= `public/cards/modelo-colinha.jpeg`)
|
||||
- Design UI (gate): `docs/plans/cards-colinha-arte-exata-ui-design.html`
|
||||
- Arquivos úteis: `src/lib/cardColinha.ts`, `src/lib/cardRender.ts`, `src/components/cards/CardComposer.tsx`, `tests/unit/cardColinha.unit.spec.ts`, `tests/e2e/frontend.e2e.spec.ts`
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
**5/5.**
|
||||
|
||||
- Fatia = um outcome verificável (colinha baixada = arte aprovada com a linha do estadual preenchida) e nada além.
|
||||
- Appetite (~0,5–1 dia) declarado e a intenção cabe: a arte já existe; só a linha do estadual é preenchida.
|
||||
- Persona, job e aceite em linguagem de produto; anti-goals e rabbit holes nomeados.
|
||||
- Direção no codebase é hipótese revisável; nenhuma signature, schema ou migration prescrita.
|
||||
- As três questões abertas têm opções e recomendação; a fidelidade da fonte é provada lado a lado no PR, não presumida.
|
||||
141
docs/plans/cards-header-modal-largura-ui-design.html
Normal file
141
docs/plans/cards-header-modal-largura-ui-design.html
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
<!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 · Header do modal na largura do card</title>
|
||||
<style type="text/tailwindcss">
|
||||
:root {
|
||||
--background: #fff;
|
||||
--foreground: #000;
|
||||
--pt-red: #a21c1c;
|
||||
--campaign-cream: #fff8f2;
|
||||
--campaign-ink: #000;
|
||||
--campaign-muted: #6c615e;
|
||||
--campaign-band: #ebe9e9;
|
||||
--campaign-line: rgb(0 0 0 / 12%);
|
||||
--field-border: rgb(0 0 0 / 18%);
|
||||
--gate: #0f766e;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: Arial, Helvetica, sans-serif; }
|
||||
button { font: inherit; }
|
||||
button:focus-visible { outline: 2px solid var(--pt-red); outline-offset: 2px; }
|
||||
.stage-shadow { box-shadow: 0 26px 80px rgb(0 0 0 / 32%); }
|
||||
.primary, .secondary {
|
||||
display: inline-flex; min-height: 44px; flex: 1; align-items: center; justify-content: center;
|
||||
border-radius: 8px; padding: 0 16px; font-size: 14px; font-weight: 800;
|
||||
}
|
||||
.primary { border: 0; background: var(--pt-red); color: white; }
|
||||
.secondary { border: 2px solid var(--campaign-line); background: white; color: var(--pt-red); }
|
||||
.measure-line { position: absolute; height: 2px; background: var(--gate); pointer-events: none; }
|
||||
.measure-line::before, .measure-line::after {
|
||||
content: ''; position: absolute; top: -4px; width: 2px; height: 10px; background: var(--gate);
|
||||
}
|
||||
.measure-line::before { left: 0; } .measure-line::after { right: 0; }
|
||||
</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-[.14em] text-emerald-300 uppercase">
|
||||
Design tier: openai/gpt-5.6-sol · frontier · 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="text-xs font-black tracking-[.12em] text-red-400 uppercase">Gate visual · S35</p>
|
||||
<h1 class="mt-2 text-3xl font-black tracking-tight">O header volta a pertencer ao modal inteiro</h1>
|
||||
<p class="mt-3 max-w-3xl text-sm leading-6 text-zinc-400">
|
||||
Correção de fidelidade: no dialog desktop, a coluna de título ocupa toda a largura disponível e o × encosta na borda direita do conteúdo. Copy, tipografia, hierarquia, prévia e ações permanecem exatamente no idioma já aprovado.
|
||||
</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 · antes × depois</span>
|
||||
<span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2">390px · referência inalterada</span>
|
||||
<span class="rounded-full border border-emerald-700 bg-emerald-950 px-3 py-2 text-emerald-200">Paridade com o gate aprovado</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-sky-300 uppercase">Cena 01 · desktop 1280 × 800</p>
|
||||
<h2 class="mt-1 text-xl font-black">Mesmo modal, mesma prévia — só a largura do header muda</h2>
|
||||
<p class="mt-1 max-w-4xl text-xs leading-5 text-zinc-500">Contornos e medidas verdes são anotações do gate; não entram na interface.</p>
|
||||
<div class="stage-shadow relative mx-auto mt-5 h-[800px] w-[1280px] max-w-full overflow-hidden rounded-2xl bg-[var(--campaign-cream)] text-black">
|
||||
<div class="absolute inset-0 bg-black/58"></div>
|
||||
<div class="absolute inset-x-10 top-1/2 grid -translate-y-1/2 grid-cols-2 gap-8">
|
||||
<div>
|
||||
<div class="mb-3 flex items-center justify-between"><p class="text-[11px] font-black tracking-[.12em] text-red-200 uppercase">Antes · cluster estreito à esquerda</p><span class="rounded-full bg-red-950/80 px-3 py-1 text-[10px] font-black text-red-200">Quebrado</span></div>
|
||||
<article role="dialog" aria-label="Minha colinha antes" class="relative mx-auto flex h-[672px] w-[512px] flex-col overflow-hidden rounded-xl bg-white shadow-2xl">
|
||||
<header class="relative flex shrink-0 items-start gap-3 px-5 pt-5">
|
||||
<div class="w-[228px] shrink-0 rounded-sm outline-2 outline-dashed outline-red-600/70"><p class="text-xs font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Minha colinha</p><h3 class="mt-1 text-xl font-black tracking-[-.01em]">Pronta para levar com você</h3><p class="mt-1 text-sm leading-5 text-[var(--campaign-muted)]">Confira o estadual escolhido. As demais escolhas já vêm preenchidas no modelo oficial.</p></div>
|
||||
<button aria-label="Fechar" class="inline-flex size-11 shrink-0 items-center justify-center rounded-lg text-2xl text-[var(--campaign-muted)]">×</button>
|
||||
<span class="absolute top-[74px] right-5 rounded bg-red-100 px-2 py-1 text-[9px] font-black text-red-800">vazio sem função</span>
|
||||
</header>
|
||||
<div class="min-h-0 flex-1 overflow-hidden px-5 pt-4 pb-5">
|
||||
<img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Modelo real da colinha" class="mx-auto block h-[390px] w-auto rounded-lg border border-[var(--campaign-line)] object-cover shadow-sm" />
|
||||
<button class="mt-4 flex h-11 w-full items-center rounded-lg border border-[var(--field-border)] bg-white px-3 text-left text-sm font-bold"><span>Julio Pinheiro</span><span class="ml-auto text-xs text-[var(--campaign-muted)]">13999 · Trocar</span></button>
|
||||
</div>
|
||||
<footer class="flex shrink-0 gap-3 border-t border-[var(--campaign-line)] px-5 py-4"><button class="secondary">Cancelar</button><button class="primary">Baixar minha colinha</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-3 flex items-center justify-between"><p class="text-[11px] font-black tracking-[.12em] text-emerald-200 uppercase">Depois · header de ponta a ponta</p><span class="rounded-full bg-emerald-900 px-3 py-1 text-[10px] font-black text-emerald-100">Alvo aprovado</span></div>
|
||||
<article role="dialog" aria-label="Minha colinha depois" class="relative mx-auto flex h-[672px] w-[512px] flex-col overflow-hidden rounded-xl bg-white shadow-2xl">
|
||||
<header class="relative flex w-full shrink-0 items-start gap-3 px-5 pt-5 outline-2 outline-offset-[-2px] outline-dashed outline-teal-700/70">
|
||||
<div class="min-w-0 flex-1"><p class="text-xs font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Minha colinha</p><h3 class="mt-1 text-xl font-black tracking-[-.01em]">Pronta para levar com você</h3><p class="mt-1 max-w-[390px] text-sm leading-5 text-[var(--campaign-muted)]">Confira o estadual escolhido. As demais escolhas já vêm preenchidas no modelo oficial.</p></div>
|
||||
<button aria-label="Fechar" class="inline-flex size-11 shrink-0 items-center justify-center rounded-lg text-2xl text-[var(--campaign-muted)]">×</button>
|
||||
<span class="measure-line right-5 bottom-[-10px] left-5"></span>
|
||||
<span class="absolute right-1 bottom-[-29px] rounded bg-teal-100 px-2 py-1 text-[9px] font-black text-teal-900">largura útil completa</span>
|
||||
</header>
|
||||
<div class="min-h-0 flex-1 overflow-hidden px-5 pt-4 pb-5">
|
||||
<img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Modelo real da colinha" class="mx-auto block h-[390px] w-auto rounded-lg border border-[var(--campaign-line)] object-cover shadow-sm" />
|
||||
<button class="mt-4 flex h-11 w-full items-center rounded-lg border border-[var(--field-border)] bg-white px-3 text-left text-sm font-bold"><span>Julio Pinheiro</span><span class="ml-auto text-xs text-[var(--campaign-muted)]">13999 · Trocar</span></button>
|
||||
</div>
|
||||
<footer class="flex shrink-0 gap-3 border-t border-[var(--campaign-line)] px-5 py-4"><button class="secondary">Cancelar</button><button class="primary">Baixar minha colinha</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-emerald-300 uppercase">Cena 02 · mobile 390 × 844</p>
|
||||
<h2 class="mt-1 text-xl font-black">Drawer · referência já correta, sem mudança</h2>
|
||||
<p class="mt-1 max-w-3xl text-xs leading-5 text-zinc-500">No celular, título e fechar já ocupam as extremidades do drawer. Esta cena documenta paridade, não propõe ajuste.</p>
|
||||
<div class="mt-5 grid items-start gap-6 lg:grid-cols-[390px_1fr]">
|
||||
<div class="stage-shadow relative mx-auto h-[844px] w-[390px] max-w-full overflow-hidden rounded-[24px] bg-[var(--campaign-cream)] text-black lg:mx-0">
|
||||
<div class="absolute inset-0 bg-black/50"></div>
|
||||
<article role="dialog" aria-label="Minha colinha no celular" class="absolute inset-0 flex flex-col overflow-hidden rounded-t-xl bg-white">
|
||||
<div class="flex h-3 shrink-0 items-end justify-center"><span class="h-1 w-24 rounded-full bg-[var(--campaign-band)]"></span></div>
|
||||
<header class="flex w-full shrink-0 items-start gap-3 px-5 pt-5">
|
||||
<div class="min-w-0 flex-1"><p class="text-[10px] font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Minha colinha</p><h3 class="mt-1 text-lg font-black tracking-[-.01em]">Pronta para baixar</h3></div>
|
||||
<button aria-label="Fechar" class="inline-flex size-11 shrink-0 items-center justify-center rounded-lg text-2xl text-[var(--campaign-muted)]">×</button>
|
||||
</header>
|
||||
<div class="min-h-0 flex-1 overflow-hidden px-5 pt-3 pb-4"><img src="cards-colinha-ui-design-assets/modelo-colinha.jpeg" alt="Modelo real da colinha" class="mx-auto block h-[600px] w-auto max-w-full rounded-lg border border-[var(--campaign-line)] object-cover shadow-sm" /></div>
|
||||
<footer class="shrink-0 border-t border-[var(--campaign-line)] px-5 py-4"><button class="primary w-full">Baixar minha colinha</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
<aside class="rounded-2xl border border-emerald-400/30 bg-emerald-400/10 p-5">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-emerald-300 uppercase">Regra de paridade</p>
|
||||
<ul class="mt-3 space-y-3 text-sm leading-6 text-zinc-300">
|
||||
<li><strong class="text-white">Esquerda:</strong> eyebrow e título reais, sem alterar tamanho, peso ou quebra.</li>
|
||||
<li><strong class="text-white">Direita:</strong> × no alvo de 44px junto à borda útil.</li>
|
||||
<li><strong class="text-white">Mobile:</strong> drawer já correto; nenhuma mudança visível.</li>
|
||||
<li><strong class="text-white">Escopo:</strong> sem copy, tipografia, hierarquia ou controle novos.</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14 rounded-2xl border border-zinc-800 bg-zinc-900 p-6">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-amber-300 uppercase">Anotação do gate · não portar para a tela</p>
|
||||
<h2 class="mt-1 text-xl font-black">Alvo literal</h2>
|
||||
<p class="mt-3 max-w-4xl text-sm leading-6 text-zinc-300">O bloco de texto permanece à esquerda e usa o espaço necessário; o × permanece isolado no extremo direito. O eixo visual do header coincide com a largura do conteúdo e do card abaixo — exatamente como nos dialogs aprovados de “Time de você”, “Time do estadual” e “Minha colinha”.</p>
|
||||
</section>
|
||||
|
||||
<aside class="mt-14 border-t border-zinc-800 pt-8 text-xs leading-5 text-zinc-500">
|
||||
<p><strong class="text-zinc-300">Ativo real:</strong> <code>cards-colinha-ui-design-assets/modelo-colinha.jpeg</code>, reutilizado sem recomposição para manter idêntica a comparação.</p>
|
||||
<p class="mt-2"><strong class="text-zinc-300">NEEDS ASSET:</strong> nenhum.</p>
|
||||
<p class="mt-2"><strong class="text-zinc-300">Paridade, não redesign:</strong> o contorno verde e as medidas existem só neste gate; copy, tipografia e hierarquia são as já aprovadas.</p>
|
||||
</aside>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
97
docs/plans/cards-header-modal-largura.md
Normal file
97
docs/plans/cards-header-modal-largura.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# S35 — Header do modal de criação de card: largura do card e fechar na borda
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-24
|
||||
Issue: #1299
|
||||
Priority: P2
|
||||
Impeccable: C — ajuste visual num funil público existente (sem superfície nova)
|
||||
Design UI: docs/plans/cards-header-modal-largura-ui-design.html
|
||||
Appetite: ~0,3–0,5 dia eng; um ajuste visual verificável com prova no browser
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
O modal de criação de card abre com o header com cara de quebrado: o título e o botão de fechar ficam agrupados à esquerda, ocupando menos largura que o próprio card. O design aprovado sempre mostrou o header atravessando o modal, com o × colado na borda direita. O relato é do humano testando o funil ao vivo («o header do modal da criação de card está quebrado. Ele fica menor que a largura do card.»). É um bug de fidelidade ao que foi aprovado, não um redesign: o desenho certo já existe nos artefatos do gate; a implementação é que divergiu (presente desde S13, 2026-09-12 — não é regressão).
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** visitante/coordenador no funil de cards (home `#cards` ou `/cards`), no desktop, depois de escolher um modelo e abrir o compositor.
|
||||
- **Job principal:** ler o título do passo e fechar o modal sem estranhar a moldura — o header precisa parecer a barra superior do card, de ponta a ponta.
|
||||
- **Fluxo desejado:** abre o modelo → o modal aparece com o título do passo à esquerda e o × na borda direita, alinhados à largura do card → lê o passo → fecha pelo × (ou segue o fluxo). No celular, o mesmo compositor vive no drawer, que já está correto.
|
||||
- **Anti-goals de produto:** redesenhar o shell ou o header; mexer nos primitivos de dialog/drawer usados por outras telas; mudar copy, hierarquia ou tipografia; criar controles novos.
|
||||
|
||||
### Esboço de fluxo (C)
|
||||
|
||||
```text
|
||||
[home #cards ou /cards] → escolhe modelo → modal abre (header full-width, × na borda)
|
||||
→ lê o título do passo → fecha pelo × | segue o fluxo
|
||||
(mobile: drawer — inalterado)
|
||||
```
|
||||
|
||||
### Design UI (C)
|
||||
|
||||
- Design UI (gate): `docs/plans/cards-header-modal-largura-ui-design.html`
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- No modal de criação de card no desktop, o header ocupa a largura do modal: bloco do título alinhado à esquerda e × na borda direita, exatamente como nas cenas de dialog dos artefatos aprovados.
|
||||
- Títulos longos e curtos se comportam igual — o header não encolhe nem "flutua" à esquerda.
|
||||
- O drawer mobile mantém o layout atual (já correto) — sem mudança visível.
|
||||
- Nada mais no estúdio muda: sem copy nova, sem tipografia nova, sem outros diálogos afetados.
|
||||
- A correção é paridade com o artefato aprovado — nenhuma invenção visual.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — nenhuma métrica.
|
||||
- **Decisões desbloqueadas:** N/A — o alvo é visual e já está aprovado no gate.
|
||||
- **Forma:** _adiada ao plano de implementação_ — aqui só a restrição de produto: paridade com as cenas de dialog aprovadas.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- Modelos/entradas do funil intocados: `#cards`, `/cards`, `?model=`.
|
||||
- Modal desktop = dialog do `CardsStudio`; drawer mobile inalterado.
|
||||
- Alvo visual = paridade com as cenas de dialog dos artefatos aprovados (`cards-time-de-voce-ui-design.html` e correlatos): header ocupando a largura, `×` na borda direita.
|
||||
- Sem copy nova.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/components/cards/CardComposer.tsx` (a linha do header) e `src/components/cards/CardsStudio.tsx` (o shell do dialog).
|
||||
- **Precedente a olhar:** artefatos aprovados de S15/S23/S30/S31 (cenas de dialog) e os e2e do funil (`tests/e2e/frontend.e2e.spec.ts`).
|
||||
- **Risco de acoplamento:** o header é o mesmo para os seis modelos; os primitivos em `src/components/ui/` são compartilhados por 13+ telas — a correção fica no ponto de uso do composer, nunca na primitiva.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma. Soft: `#1277` (fatiar o `CardComposer`) e S33/S34 tocam o mesmo arquivo — coordenar/rebase.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Mudar o drawer mobile.
|
||||
- Mexer nas primitivas de UI (dialog/drawer).
|
||||
- Redesenhar o header (hierarquia, tipografia, copy).
|
||||
- Qualquer outra tela.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Aproveitar e redesenhar o header".** Se alguém "só completar": vira redesign do compositor e do funil. **Corte neste item:** só a largura/posição já aprovadas.
|
||||
- **"Corrigir a primitiva para todos".** Se alguém "só completar": 13+ telas mudam de comportamento sem pedido. **Corte neste item:** o ajuste fica no composer.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- N/A — o alvo já está aprovado nos artefatos do gate; sem decisão nova.
|
||||
|
||||
## Referências
|
||||
|
||||
- Design UI (gate): `docs/plans/cards-header-modal-largura-ui-design.html`
|
||||
- Artefatos aprovados (cenas de dialog): `cards-time-de-voce-ui-design.html`, `cards-estadual-dobradinha-ui-design.html`, `cards-colinha-ui-design.html`
|
||||
- `src/components/cards/CardComposer.tsx`, `src/components/cards/CardsStudio.tsx`
|
||||
- `tests/e2e/frontend.e2e.spec.ts`
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
**5/5.**
|
||||
|
||||
- Um outcome verificável: header do modal na largura do card com × na borda, nada mais.
|
||||
- Appetite declarado (~0,3–0,5 dia) e a intenção cabe nele — ajuste visual localizado.
|
||||
- Persona, job e aceite em linguagem de produto, sem jargão de stack.
|
||||
- Direção no codebase é hipótese (arquivos prováveis), não contrato técnico.
|
||||
- Zero decisões duras de engenharia; o alvo visual já está aprovado no gate.
|
||||
193
docs/plans/cards-time-ajuste-sem-limite-ui-design.html
Normal file
193
docs/plans/cards-time-ajuste-sem-limite-ui-design.html
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
<!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 · Ajuste da foto livre, sem limite</title>
|
||||
<style type="text/tailwindcss">
|
||||
:root {
|
||||
--background: #fff;
|
||||
--foreground: #000;
|
||||
--pt-red: #a21c1c;
|
||||
--campaign-cream: #fff8f2;
|
||||
--campaign-ink: #000;
|
||||
--campaign-muted: #6c615e;
|
||||
--campaign-surface: #f9faff;
|
||||
--campaign-band: #ebe9e9;
|
||||
--campaign-line: rgb(0 0 0 / 12%);
|
||||
--team-blue: #0061a5;
|
||||
--gate: #0f766e;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: Arial, Helvetica, sans-serif; }
|
||||
button, input { font: inherit; }
|
||||
button:focus-visible, input:focus-visible, [tabindex]:focus-visible {
|
||||
outline: 2px solid var(--pt-red); outline-offset: 2px;
|
||||
}
|
||||
.stage-shadow { box-shadow: 0 26px 80px rgb(0 0 0 / 32%); }
|
||||
.team-card {
|
||||
position: relative; aspect-ratio: 3 / 4; overflow: hidden; background: #0b8fc3;
|
||||
}
|
||||
.team-card > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
|
||||
.team-photo { z-index: 1; }
|
||||
.team-overlay { z-index: 4; }
|
||||
.silhouette {
|
||||
position: absolute; z-index: 2; top: var(--y, 29%); left: var(--x, 54%);
|
||||
width: 36%; height: 45%; transform: translate(-50%, -10%); color: #061d40;
|
||||
filter: drop-shadow(0 2px 2px rgb(0 0 0 / 18%));
|
||||
}
|
||||
.silhouette::before {
|
||||
content: ''; position: absolute; top: 0; left: 50%; width: 36%; aspect-ratio: .82;
|
||||
transform: translateX(-50%); border-radius: 48% 48% 45% 45%; background: currentColor;
|
||||
}
|
||||
.silhouette::after {
|
||||
content: ''; position: absolute; right: 0; bottom: 0; left: 0; height: 77%;
|
||||
border-radius: 49% 49% 8% 8% / 30% 30% 6% 6%; background: currentColor;
|
||||
}
|
||||
.drag-badge {
|
||||
position: absolute; right: 8px; bottom: 8px; z-index: 8; border-radius: 4px;
|
||||
background: rgb(0 0 0 / 72%); padding: 4px 7px; color: #fff; font-size: 9px; font-weight: 700;
|
||||
}
|
||||
.gate-vector {
|
||||
position: absolute; z-index: 9; border-top: 2px dashed rgb(15 118 110 / 90%);
|
||||
transform-origin: left center; pointer-events: none;
|
||||
}
|
||||
.gate-vector::after {
|
||||
content: ''; position: absolute; top: -5px; right: -1px; width: 8px; height: 8px;
|
||||
border-top: 2px solid var(--gate); border-right: 2px solid var(--gate); transform: rotate(45deg);
|
||||
}
|
||||
.control-button {
|
||||
display: inline-flex; width: 44px; height: 44px; flex: none; align-items: center;
|
||||
justify-content: center; border: 1px solid var(--campaign-line); border-radius: 8px;
|
||||
background: #fff; color: var(--campaign-ink); font-size: 17px;
|
||||
}
|
||||
.range {
|
||||
appearance: none; height: 4px; min-width: 0; border-radius: 999px;
|
||||
background: linear-gradient(90deg, var(--pt-red) 0 46%, #d6d3d1 46% 100%);
|
||||
}
|
||||
.range::-webkit-slider-thumb {
|
||||
appearance: none; width: 20px; height: 20px; border: 3px solid #fff; border-radius: 999px;
|
||||
background: var(--pt-red); box-shadow: 0 0 0 1px rgb(0 0 0 / 18%);
|
||||
}
|
||||
.primary, .secondary {
|
||||
display: inline-flex; min-height: 44px; flex: 1; align-items: center; justify-content: center;
|
||||
border-radius: 8px; padding: 0 20px; font-size: 14px; font-weight: 800;
|
||||
}
|
||||
.primary { border: 0; background: var(--pt-red); color: #fff; }
|
||||
.secondary { border: 2px solid var(--campaign-line); background: #fff; color: var(--pt-red); }
|
||||
.switch { position: relative; width: 44px; height: 26px; flex: none; border-radius: 999px; background: var(--pt-red); }
|
||||
.switch::after {
|
||||
content: ''; position: absolute; top: 3px; left: 21px; width: 20px; height: 20px;
|
||||
border-radius: 999px; background: #fff; box-shadow: 0 1px 2px rgb(0 0 0 / 25%);
|
||||
}
|
||||
</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-[.14em] text-emerald-300 uppercase">
|
||||
Design tier: openai/gpt-5.6-sol · frontier · 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="text-xs font-black tracking-[.12em] text-red-400 uppercase">Gate visual · S33 · decisão revisada em 24/09/2026</p>
|
||||
<h1 class="mt-2 text-3xl font-black tracking-tight">A foto vai a qualquer ponto — inclusive para fora</h1>
|
||||
<p class="mt-3 max-w-3xl text-sm leading-6 text-zinc-400">
|
||||
O enquadramento automático S15 continua sendo o ponto de partida. Depois dele, arrastar, setas e teclado deixam a posição livre nos dois eixos. A pessoa pode esconder parte ou toda a própria foto e revelar a arte do time ao fundo; para voltar, arrasta de volta na mesma área ativa.
|
||||
</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 · dialog</span>
|
||||
<span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2">390px · drawer</span>
|
||||
<span class="rounded-full border border-emerald-700 bg-emerald-950 px-3 py-2 text-emerald-200">X + Y: sem limite</span>
|
||||
<span class="rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2">Zoom [1,4] · inalterado</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-sky-300 uppercase">Cena 01 · desktop 1280 × 800</p>
|
||||
<h2 class="mt-1 text-xl font-black">Dialog de ajuste · do limite atual à posição livre</h2>
|
||||
<p class="mt-1 max-w-4xl text-xs leading-5 text-zinc-500">Setas tracejadas, rótulos e silhueta são anotações do gate. O compositor não ganha controles nem copy.</p>
|
||||
<div class="stage-shadow relative mx-auto mt-5 h-[800px] w-[1280px] max-w-full overflow-hidden rounded-2xl bg-[var(--campaign-cream)] text-black">
|
||||
<div class="absolute inset-0 bg-black/58"></div>
|
||||
<article role="dialog" aria-label="Time do estadual" class="absolute top-1/2 left-1/2 flex max-h-[744px] w-[760px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl bg-white shadow-2xl">
|
||||
<header class="flex shrink-0 items-start gap-3 px-5 pt-5">
|
||||
<div class="min-w-0 flex-1"><p class="text-xs font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Time do estadual</p><h3 class="mt-1 text-xl font-black">Confira seu card</h3></div>
|
||||
<button aria-label="Fechar" class="inline-flex size-11 items-center justify-center rounded-lg text-2xl text-[var(--campaign-muted)]">×</button>
|
||||
</header>
|
||||
<div class="min-h-0 flex-1 overflow-y-auto px-5 pt-4 pb-5">
|
||||
<p class="mx-auto mb-4 max-w-[620px] text-sm leading-5 text-[var(--campaign-muted)]">O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles.</p>
|
||||
<div class="grid grid-cols-2 gap-5">
|
||||
<figure class="m-0 rounded-xl bg-stone-50 p-3 ring-1 ring-black/10">
|
||||
<div class="flex items-center justify-between gap-2"><figcaption class="text-[11px] font-black tracking-wide text-stone-600 uppercase">Hoje · gesto para cedo</figcaption><span class="rounded-full bg-stone-200 px-2 py-1 text-[10px] font-black text-stone-600">±33px típico</span></div>
|
||||
<div class="relative mx-auto mt-3 w-[210px] overflow-hidden rounded-lg border border-black/10 shadow-sm" tabindex="0">
|
||||
<div class="team-card"><img class="team-photo" src="../../public/cards/estaduais/julio-fotos.webp" alt="Arte do time de Julio Pinheiro" /><span class="silhouette" style="--x:57%;--y:29%"></span><img class="team-overlay" src="../../public/cards/estaduais/julio-base.webp" alt="Faixas da arte de Julio Pinheiro" /></div><span class="drag-badge">Arraste para ajustar</span>
|
||||
</div>
|
||||
<p class="mt-2 text-center text-[11px] leading-4 text-stone-600">O arquivo transparente trava enquanto a pessoa ainda aparece perto do centro.</p>
|
||||
</figure>
|
||||
<figure class="m-0 rounded-xl bg-teal-50 p-3 ring-2 ring-teal-700">
|
||||
<div class="flex items-center justify-between gap-2"><figcaption class="text-[11px] font-black tracking-wide text-teal-900 uppercase">Novo · além do quadro</figcaption><span class="rounded-full bg-teal-700 px-2 py-1 text-[10px] font-black text-white">X + Y livres</span></div>
|
||||
<div class="relative mx-auto mt-3 w-[210px] overflow-hidden rounded-lg border border-teal-700/30 shadow-sm" tabindex="0">
|
||||
<div class="team-card"><img class="team-photo" src="../../public/cards/estaduais/julio-fotos.webp" alt="Arte do time revelada ao fundo" /><span class="silhouette" style="--x:110%;--y:-16%"></span><img class="team-overlay" src="../../public/cards/estaduais/julio-base.webp" alt="Faixas da arte de Julio Pinheiro" /><span class="gate-vector top-[31%] left-[49%] w-[48%] -rotate-[36deg]"></span></div><span class="drag-badge">Arraste para ajustar</span>
|
||||
</div>
|
||||
<p class="mt-2 text-center text-[11px] leading-4 text-teal-900/75">A pessoa já saiu quase toda pelo alto e pela direita. A arte de trás reaparece.</p>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="mx-auto mt-5 max-w-[620px]">
|
||||
<div class="flex items-center gap-3"><label class="text-sm font-bold">Zoom</label><button class="control-button" aria-label="Diminuir zoom">−</button><input class="range h-11 flex-1" type="range" value="46" aria-label="Zoom" /><button class="control-button" aria-label="Aumentar zoom">+</button></div>
|
||||
<p class="mt-4 text-sm font-bold">Ajuste fino</p><div class="mt-2 grid grid-cols-4 gap-2"><button class="control-button w-full" aria-label="Mover foto para a esquerda">←</button><button class="control-button w-full" aria-label="Mover foto para cima">↑</button><button class="control-button w-full" aria-label="Mover foto para baixo">↓</button><button class="control-button w-full" aria-label="Mover foto para a direita">→</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="flex shrink-0 gap-3 border-t border-[var(--campaign-line)] px-5 py-4"><button class="secondary">Cancelar</button><button class="primary">Criar meu card</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-emerald-300 uppercase">Cena 02 · mobile 390 × 844</p>
|
||||
<h2 class="mt-1 text-xl font-black">Drawer · foto totalmente fora, área ainda ativa</h2>
|
||||
<p class="mt-1 max-w-3xl text-xs leading-5 text-zinc-500">A prévia mostra a escolha extrema permitida: só a arte do time fica visível. O quadro inteiro continua sendo a área de arrasto para trazer a foto de volta.</p>
|
||||
<div class="mt-5 grid items-start gap-6 lg:grid-cols-[390px_1fr]">
|
||||
<div class="stage-shadow relative mx-auto h-[844px] w-[390px] max-w-full overflow-hidden rounded-[24px] bg-[var(--campaign-cream)] text-black lg:mx-0">
|
||||
<div class="absolute inset-0 bg-black/50"></div>
|
||||
<article role="dialog" class="absolute inset-0 flex flex-col overflow-hidden rounded-t-xl bg-white">
|
||||
<div class="flex h-3 shrink-0 items-end justify-center"><span class="h-1 w-24 rounded-full bg-[var(--campaign-band)]"></span></div>
|
||||
<header class="flex shrink-0 items-start gap-3 px-5 pt-5"><div class="min-w-0 flex-1"><p class="text-[10px] font-black tracking-[.1em] text-[var(--pt-red)] uppercase">Time do estadual</p><h3 class="mt-1 text-lg font-black">Confira seu card</h3></div><button aria-label="Fechar" class="inline-flex size-11 items-center justify-center text-2xl text-[var(--campaign-muted)]">×</button></header>
|
||||
<div class="min-h-0 flex-1 overflow-hidden px-5 pt-3 pb-4">
|
||||
<p class="mb-3 text-sm leading-5 text-[var(--campaign-muted)]">O recorte já foi centralizado. Se precisar, arraste a foto ou use os controles.</p>
|
||||
<figure class="m-0"><div class="relative mx-auto w-[184px] overflow-hidden rounded-lg border-2 border-teal-700 shadow-sm" tabindex="0" aria-label="Ajuste da foto"><div class="team-card"><img class="team-photo" src="../../public/cards/estaduais/julio-fotos.webp" alt="Arte do time visível porque a foto do visitante está fora do quadro" /><span class="silhouette" style="--x:-75%;--y:118%"></span><img class="team-overlay" src="../../public/cards/estaduais/julio-base.webp" alt="Faixas da arte de Julio Pinheiro" /></div><span class="drag-badge">Arraste para ajustar</span></div><figcaption class="mt-1.5 text-center text-[9px] font-black text-teal-800 uppercase">Foto fora do quadro · arrasto segue ativo</figcaption></figure>
|
||||
<div class="mt-4 flex items-center gap-3"><label class="text-sm font-bold">Zoom</label><button class="control-button">−</button><input class="range h-11 flex-1" type="range" value="46" aria-label="Zoom" /><button class="control-button">+</button></div>
|
||||
<p class="mt-3 text-sm font-bold">Ajuste fino</p><div class="mt-2 grid grid-cols-4 gap-2"><button class="control-button w-full">←</button><button class="control-button w-full">↑</button><button class="control-button w-full">↓</button><button class="control-button w-full">→</button></div>
|
||||
<button role="switch" aria-checked="true" class="mt-3 flex min-h-11 w-full items-start gap-3 rounded-lg border border-[var(--campaign-line)] bg-white p-3 text-left"><span class="switch mt-1.5"></span><span><span class="block text-sm font-bold">Harmonizar cores</span><span class="block text-xs leading-5 text-[var(--campaign-muted)]">Ajusta o brilho e as cores da sua foto para combinar com as fotos do card.</span></span></button>
|
||||
<button class="secondary mt-3 w-full">Trocar foto</button>
|
||||
</div>
|
||||
<footer class="flex shrink-0 gap-3 border-t border-[var(--campaign-line)] px-5 py-4"><button class="secondary">Cancelar</button><button class="primary">Criar meu card</button></footer>
|
||||
</article>
|
||||
</div>
|
||||
<aside class="rounded-2xl border border-emerald-400/30 bg-emerald-400/10 p-5">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-emerald-300 uppercase">Leitura do gesto</p>
|
||||
<ul class="mt-3 space-y-3 text-sm leading-6 text-zinc-300">
|
||||
<li><strong class="text-white">Hoje:</strong> o gesto para cedo (±33px típico).</li>
|
||||
<li><strong class="text-white">Novo:</strong> sem limite — posição livre nos dois eixos, inclusive fora do quadro.</li>
|
||||
<li><strong class="text-white">Voltar:</strong> arrastar na prévia, que continua ativa mesmo sem a pessoa visível.</li>
|
||||
<li><strong class="text-white">Ponto de partida:</strong> enquadramento automático S15, aplicado como hoje.</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-14 rounded-2xl border border-zinc-800 bg-zinc-900 p-6">
|
||||
<p class="text-[11px] font-black tracking-[.12em] text-amber-300 uppercase">Anotação do gate · não portar para a tela</p>
|
||||
<h2 class="mt-1 text-xl font-black">O que muda — e o que não muda</h2>
|
||||
<div class="mt-5 grid gap-4 md:grid-cols-2">
|
||||
<article class="rounded-xl border border-emerald-700 bg-emerald-950/40 p-5"><p class="text-xs font-black tracking-wide text-emerald-300 uppercase">Posição</p><p class="mt-2 text-sm leading-6 text-zinc-200">Sem clamp em X ou Y. Pode passar da janela, ficar parcialmente fora ou desaparecer por completo do quadro.</p></article>
|
||||
<article class="rounded-xl border border-zinc-700 bg-zinc-950/50 p-5"><p class="text-xs font-black tracking-wide text-zinc-300 uppercase">Todo o resto</p><p class="mt-2 text-sm leading-6 text-zinc-300">S15 como início; zoom na faixa [1,4]; mesmos controles, copy e área de arrasto; nenhuma telemetria.</p></article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside class="mt-14 border-t border-zinc-800 pt-8 text-xs leading-5 text-zinc-500">
|
||||
<p><strong class="text-zinc-300">Ativos:</strong> arte real de JULIO em <code>../../public/cards/estaduais/julio-fotos.webp</code> + <code>julio-base.webp</code>. A silhueta abstrata representa o recorte do visitante.</p>
|
||||
<p class="mt-2"><strong class="text-zinc-300">NEEDS ASSET:</strong> nenhum.</p>
|
||||
<p class="mt-2"><strong class="text-zinc-300">Sem novidade de interface:</strong> anotações verdes existem só neste gate; não há controle, copy ou telemetria novos.</p>
|
||||
</aside>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
103
docs/plans/cards-time-ajuste-sem-limite.md
Normal file
103
docs/plans/cards-time-ajuste-sem-limite.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# S33 — Card do time (você e estadual): ajuste da foto livre, sem limite
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-09-24
|
||||
Issue: #1297
|
||||
Priority: P1
|
||||
Impeccable: C — ajuste de comportamento num funil público existente (sem controle novo)
|
||||
Design UI: docs/plans/cards-time-ajuste-sem-limite-ui-design.html
|
||||
Appetite: ~0,5 dia eng; um comportamento verificável no funil de cards
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
No teste do card com estadual, o humano reencontrou o mesmo atrito: «No teste da criação do card "time de você" com estadual, encontrei novamente a limitação no ajuste, não consigo ajustar corretamente porque tem limite da movimentação pros lados.» A S20 já tinha corrigido exatamente isso no "Time de você" (Issue #1216), mas a correção foi revertida por uma razão de engenharia que continua válida: o detector de rosto saiu e o enquadramento automático voltou ao S15 (commit 48e08bf7, 2026-09-20). O limite que sobrou não vem da pessoa — vem do espaço transparente que o recorte deixa em volta dela, e é o mesmo nos dois modelos do time.
|
||||
|
||||
Numa foto realista (1200×1600), um busto que preenche a moldura anda ~66px no total (±33); um busto menor, ~423px (±211); um busto fora do centro anda bem mais para um lado (+1036) que para o outro (−148). Quem trava é sempre a borda do arquivo da foto, nunca a borda visível da pessoa — que costuma estar bem dentro da janela quando o gesto para.
|
||||
|
||||
A decisão do humano no gate (2026-09-24) é **liberar totalmente, sem limite**: o ajuste não é mais restringido em nenhum eixo — o que resolve o atrito pela raiz e dispensa âncora de silhueta, caixa medida ou união de alcances. O enquadramento automático S15 continua sendo só o ponto de partida.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** visitante no celular, no funil público dos cards de time (você e estadual), logo depois do recorte da foto; quer se encaixar na composição antes de baixar.
|
||||
- **Job principal:** posicionar a própria foto — principalmente para os lados — onde ela fica boa no card.
|
||||
- **Fluxo desejado:** escolhe a foto → recorte → enquadramento automático S15 (inalterado) → arrasta ou usa setas/teclado → a foto vai a qualquer posição → baixa o PNG.
|
||||
- **Anti-goals de produto:** não vira editor de imagem; não ganha controle nem texto novo; não libera os limites do zoom; não muda o enquadramento automático nem os outros modelos.
|
||||
|
||||
### Esboço de fluxo (C)
|
||||
|
||||
```text
|
||||
[foto escolhida] → [recorte] → [enquadramento automático S15] → [prévia: arrastar/setas/teclado — posição livre] → [PNG]
|
||||
```
|
||||
|
||||
### Design UI (C)
|
||||
|
||||
- Design UI (gate): `docs/plans/cards-time-ajuste-sem-limite-ui-design.html`
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- A foto pode ser movimentada livremente nos dois eixos: nenhum limite artificial — o arrasto, as setas e o teclado nunca são barrados pelo espaço transparente do recorte.
|
||||
- A foto pode passar além da janela, sair do quadro e deixar a arte de trás aparecer — escolha do visitante; o retorno é arrastar de volta (a área de arrasto continua ativa).
|
||||
- Arrastar, setas e teclado seguem iguais; os limites do zoom seguem iguais (a liberdade é da posição, não do zoom); o enquadramento automático S15 continua sendo o ponto de partida.
|
||||
- Prévia e PNG baixado mostram a mesma posição — sem "voltar sozinho" ao soltar.
|
||||
- Tudo no aparelho, sem telemetria de foto ou posição; os demais modelos (os 3 anteriores) ficam intocados.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — nenhuma métrica de produto nesta tela.
|
||||
- **Decisões desbloqueadas:** nenhuma — a posição é geometria efêmera no aparelho, não vira dado de campanha.
|
||||
- **Forma:** _adiada ao plano de implementação_ — restrição de produto: nada de telemetria de foto/posição.
|
||||
|
||||
## Dados da decisão (literais)
|
||||
|
||||
- Modelos do time: `time-de-voce` e `time-do-estadual`.
|
||||
- Decisão do humano no gate (2026-09-24): **liberar totalmente, sem limite** — o ajuste (arrasto, setas, teclado) não tem limite em nenhum eixo; sem âncora de silhueta e sem clamp do ajuste (o padding transparente do recorte deixa de importar).
|
||||
- Enquadramento automático S15 `frameCardPhotoOnBbox` continua sendo o ponto de partida, aplicado uma vez ao carregar a foto.
|
||||
- Zoom inalterado (faixa `[1,4]` de hoje): a liberação é da posição.
|
||||
- Composer e renderizador: o ajuste do visitante não é re-limitado no desenho nem no PNG (sem snap-back); o limite de hoje deixa de valer para o ajuste.
|
||||
- Sem controles, textos ou telemetria novos.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/lib/cardPhotoTransform.ts` (o limite do ajuste/zoom), `src/components/cards/CardComposer.tsx` (os controles), `src/lib/cardRender.ts` (desenho do time — não re-limitar o ajuste do visitante), testes.
|
||||
- **Precedente a olhar:** S20 — Issue #1216, commit e652f0ae e o revert 48e08bf7 (`docs/plans/cards-time-de-voce-ajuste-lateral.md` e `-impl.md`; `docs/changelog/2026-09-20-card-time-recorte-e-enquadramento.md`).
|
||||
- **Risco de acoplamento:** o enquadramento inicial S15 e os 3 modelos anteriores (S13/S14) precisam ficar idênticos; `#1277` (S30-FOLLOWUP-DRY) mexe no mesmo arquivo — coordenar/rebase.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma dura. Suave: `#1277` (mesmo arquivo do composer).
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Mudar os limites do zoom.
|
||||
- Mudar o enquadramento automático (S15/S18 — decisão humana de 2026-09-20).
|
||||
- Trazer o detector de rosto de volta, controles novos (slider lateral, "centralizar"/"re-enquadrar") e telemetria.
|
||||
- Os 3 modelos anteriores.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Proteger a composição com um limite novo".** Se alguém "só completar": reintroduz o atrito que o humano acabou de mandar remover. **Corte neste item:** sem limite, decisão do gate.
|
||||
- **"Botão de voltar ao enquadramento".** Se alguém "só completar": novo controle e novo estado. **Corte neste item:** a área de arrasto continua ativa; voltar é arrastar.
|
||||
- **"Re-detectar/rastrear a silhueta durante o arrasto".** Se alguém "só completar": custo por quadro e comportamento instável. **Corte neste item:** não há âncora.
|
||||
- **"Reabrir o enquadramento".** Se alguém "só completar": rediscute a decisão humana de 2026-09-20. **Corte neste item:** S15 intocado.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- **Até onde liberar o ajuste?** **Decidido no gate (2026-09-24): sem limite** — o ajuste é livre nos dois eixos.
|
||||
- **Mudar o enquadramento inicial?** **Opções:** A) manter S15 (recomendado) | B) reabrir. **Recomendação:** A — decisão humana de 2026-09-20. _(assumido — validar com produto no gate)_
|
||||
- **Mexer nos limites do zoom?** **Opções:** A) manter `[1,4]` (recomendado) | B) liberar também. **Recomendação:** A — o relato é de posição. _(assumido — validar com produto no gate)_
|
||||
|
||||
## Referências
|
||||
|
||||
- Issue #1216 (S20) + commit e652f0ae — mediu 248px de curso lateral total (≈±124); commit 48e08bf7 + `docs/changelog/2026-09-20-card-time-recorte-e-enquadramento.md` (o revert).
|
||||
- `docs/plans/cards-time-de-voce-ajuste-lateral.md` e `-impl.md`; `docs/plans/cards-estadual-dobradinha.md`.
|
||||
- Design UI (gate): `docs/plans/cards-time-ajuste-sem-limite-ui-design.html`; arquivos úteis: `src/lib/cardPhotoTransform.ts`, `src/components/cards/CardComposer.tsx`, `src/lib/cardRender.ts`, `tests/unit/cardPhotoTransform.unit.spec.ts`.
|
||||
|
||||
## Self-score (shaping)
|
||||
|
||||
**5/5.**
|
||||
|
||||
- Um outcome verificável — o ajuste da foto não tem limite — e nada além.
|
||||
- Appetite declarado (~0,5 dia) e a intenção cabe: remover o limite do ajuste é menor do que a âncora que ele substitui.
|
||||
- Persona, job e aceite em linguagem de produto, ancorados no relato humano no funil e na decisão do gate.
|
||||
- Direção no codebase é hipótese, com precedente e risco de acoplamento nomeados; nenhuma decisão dura de engenharia (schema, migration, assinatura) no plano.
|
||||
Loading…
Reference in a new issue