Commit graph

54 commits

Author SHA1 Message Date
Francisco Solla
999de98295 feat(site): mapeia os permalinks do WordPress legado para o domínio novo (OPS131)
Os 43 posts publicados no WordPress (último em 2026-08-17) ganham redirect permanente do permalink /<ano>/<mês>/<dia>/<slug>/ para o caminho canônico do Teqo, com destino derivado do type/category atuais de produção. Categoria, tag, author, feeds, paginação e arquivos de data vão para /artigos; /home vai para /; wp-admin/wp-login.php para /. O mapa fica em scripts/lib/legacyWordPressRedirects.mjs (43 entradas) e é consumido pelo next.config.mjs; unit pina contagem/forma/unicidade e o e2e do frontend cobre os redirects. Sem migration, sem Consent e sem mudança de conteúdo no CMS.
2026-11-08 20:30:49 -03:00
Francisco Solla
a4c2ab226a fix(site): limita o título do board e remove text-balance dos cards (S47)
O card em destaque perdeu o line-clamp-3 na reescrita da S47: com o feed do Instagram na frente, a legenda inteira (889 caracteres no caso real) era renderizada a 31px e esticava o board. Restaura o clamp de 3 linhas no destaque, mantém o clamp do compacto, troca text-balance por break-words (balance quebra o line-clamp em alguns browsers) e adiciona min-w-0 às colunas do grid. O e2e passa a pinar o clamp do card em destaque, não só o do compacto.
2026-11-05 17:06:44 -03:00
Francisco Solla
5635e6522c feat(site): vira o site público para o mandato pós-eleição (S47)
Home abre no agradecimento pelos 152.049 votos com board 1+3, trajetória, bandeiras do mandato, galeria de fotos e rodapé institucional; chrome novo (header home/interno, lockup de nome, menu mobile acessível) e /artigos//fotos com título compacto.

As superfícies de campanha saem do ar (308 de /conteudos, /jingles e /cards), junto com newsletter, estúdio público de cards e UI da Central/jingles; download de foto e .ics perdem o 1313. Sem migration, sem Consent novo e sem apagar dados do CMS.
2026-10-22 02:16:08 -03:00
Francisco Solla
0a8b0774d3 feat(S44): home divulga a Plenária da Vitória (agenda pré-live, embed ao vivo e kill switch)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-10-01 17:47:30 -03:00
Francisco Solla
dbe77f08cc feat(C226): frame estático nos vídeos da Central antes do play
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
Peça de vídeo publicada e com arquivo passa a mostrar um frame estático
leve no card público antes do play, sem nenhum request do arquivo antes
do gesto (`preload="none"` do S27 intacto).

O frame é um derivado privado em `contentMedia` (nome determinístico),
gerado por um dono só — `ensureContentPieceFrame` — chamado pelo job
C211 (que já tem o arquivo em disco: a extração sai de graça) e pela
rota `GET /conteudos/<slug>/frame` em miss, que cura o acervo anterior
sem backfill, fila, collection nova ou migration.

A porta reusa o gate de slug publicado e o proxy de mídia privada do
`/midia`: o kill switch fecha as duas de uma vez. Sem frame possível, o
slot mostra o estado neutro honesto com play e o marcador — nunca
imagem quebrada, nunca retry.

A projeção declara o frame por elegibilidade (vídeo com arquivo), não
pela existência do derivado, então a cura é invisível para o cache da
listagem e não há tag para bustar. O frame também aparece na página da
peça e no card da home (variante compacta de 124px, cena 05).

A passagem de design (tier primário) achou dois bugs que só o browser
mostra: o glyph de imagem quebrada numa requisição que falha, e — ao
esconder a imagem até decodificar — o frame sumindo para sempre no
caminho mais rápido (uma imagem que carrega antes da hidratação não
dispara `load` nem `error` de novo; o `ref` decide os dois desfechos).

Também: o guard de falha de e2e aceita `RegExp` e confere os paths
declarados antes do caso do favicon (todo 404 do browser traz a mesma
mensagem), o manifest de e2e mapeia os módulos novos, e o job C211
passa o arquivo que já tem em disco em vez de rebaixar o vídeo.

Design tier: central-conteudos-preview-frame-video
Closes #1352
2026-09-25 14:56:06 -03:00
Francisco Solla
f750084c41 fix(cards): tiles da home usam espaçador de proporção (WebKit #265243)
No Orion/Safari os seis tiles de modelos colapsavam (só os rótulos
ficavam): a caixa do CardModelTile tirava a altura de um `aspect-ratio`
inline sendo filha de um flex com `overflow: hidden` — o construto do
bug WebKit #265243 (fix só no WebKit main 2026-05), invisível para o CI
Chromium-only.

O tile passa a tirar a altura de um espaçador em fluxo com
padding-bottom percentual (data-card-tile-ratio). Guardas: unit por
modelo (RED sem o fix), sweep de convenção nos cards e e2e de geometria
após relayout forçado. Post-mortem + changelog na mesma entrega.
2026-09-24 16:41:18 -03:00
Francisco Solla
02ca466469 feat(S40): arte genérica do Time do estadual e janela vazia sem silhueta (Closes #1316) 2026-09-24 16:23:44 -03:00
Francisco Solla
11de48f726 feat(S39): seção da Central de Conteúdos na home (Closes #1305) 2026-09-24 14:53:36 -03:00
Francisco Solla
2c8b38f2be feat(S34): colinha usa a arte exata com a linha do estadual preenchida (Closes #1298) 2026-09-24 02:20:44 -03:00
Francisco Solla
9069d23d88 feat(S33): ajuste da foto do card do time sem limite (Closes #1297) 2026-09-24 01:38:06 -03:00
Francisco Solla
e8a190005a feat(S32): contadores anônimos de download dos cards na home staff (Closes #1273) 2026-09-23 18:12:42 -03:00
Francisco Solla
b0bac78090 feat(S31): colinha de voto — 6º modelo com o estadual escolhido (Closes #1272) 2026-09-23 12:33:04 -03:00
Francisco Solla
6480768926 feat(S30): card Time do estadual — 5º modelo com as 53 dobradinhas (Closes #1271) 2026-09-23 10:06:17 -03:00
Francisco Solla
bb550cebff feat(S25): player próprio da Rádio 1313 na home — exclusividade, share e fail-soft (Closes #1239) 2026-09-21 13:39:42 -03:00
Francisco Solla
5aefb2f3ba feat(S24): rádio na home — embed direto do zeno.fm, sem facade (Closes #1235)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-20 22:36:25 -03:00
Francisco Solla
908a31eea4 feat(S23): card Time de você no celular — drawer até o topo e nada sobre a imagem (Closes #1234) 2026-09-20 21:54:41 -03:00
Francisco Solla
d86b3aa0a1 feat(S22): jingles e rádio na home — a seção de som (Closes #1228)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-20 18:29:47 -03:00
Francisco Solla
48e08bf7f5 fix(cards): recorte no celular (WASM/WebGL) e volta do enquadramento S15
O recorte do card 'Time de você' falhava em navegadores endurecidos (IronFox/Tor
desligam WebAssembly e WebGL por padrão) com a copy errada de 'tente outra foto';
o motor MediaPipe exige ambos (o grafo pede kGpuService mesmo com delegate CPU).
Agora o adapter sonda WASM/WebGL antes do download e devolve 'unsupported' com
mensagem acionável; a entrada de inferência é capada em 1600 e a foto passa pelo
loadCardPhoto (foto de 61MP que falhava agora conclui).

O enquadramento automático volta ao S15 (bbox cobre a janela): o S18 mirava a
caixa do rosto em 103px e deixava o busto inteiro pequeno na janela. Saem o
detector de rosto (asset removido), frameCardPhotoOnFace, a referência 103px, o
piso 0.2 e a âncora S20 (inerte sob o cover). S16/S17 intactos.
2026-09-20 17:33:29 -03:00
Francisco Solla
cde96b26d0 feat(S18): cabeça do visitante proporcional à dos candidatos no card Time de você
- FaceDetector (blaze_face_full_range, Apache-2.0, lazy/on-device) mede o maior rosto no canvas do recorte; math pura frameCardPhotoOnFace escala a face à referência TEAM_CARD_FACE_REFERENCE_SIZE=103 (mediana das 5 caixas da arte-mestre).
- Piso do time CARD_TEAM_PHOTO_MIN_ZOOM=0.2 com clamp contain/cover por eixo (minZoom opcional preserva os 3 modelos S13/S14); fallback silencioso ao enquadramento S15 sem rosto/falha.
- Stub e2e estendido ('noface'); unit novo da math e da seleção do rosto; craft com retrato real 86-98px vs 103 (±20%); crítica Tier 1 certificada.

Closes #1197
2026-09-19 13:42:22 -03:00
Francisco Solla
dbd9ecdfd4 feat(S16): banner azul dinâmico no card "Time de você" — nomes longos cabendo (Closes #1195) 2026-09-19 13:05:52 -03:00
Francisco Solla
d7d4258cd7 feat(S17): controle "Harmonizar cores" no ready do card Time de você
Ajuste local de brilho/contraste/saturação (clamps fixos ≤12%, alpha byte-a-byte) para aproximar a selfie do tom da arte-mestre; variante gerada 1× no ready do useCardCutout e escolhida pelo toggle no mesmo canvas da prévia e do PNG. Sem migration/Consent/rede/persistência; os 3 modelos e o recorte intocados. Crítica do designer certificada no tier primário (artefato revalidado sem DEGRADED).
2026-09-19 10:55:18 -03:00
Francisco Solla
560f2e494a feat(S15): card "Time de você" — quarto modelo auto-serviço no funil público (Closes #1161) 2026-09-18 22:17:52 -03:00
Francisco Solla
8e0366d3ba feat(S14): cards personalizados — ajustes de fidelidade e experiência
A home abre o mesmo compositor do /cards ali mesmo (dialog no desktop,
drawer no mobile) e perde o CTA: os três modelos viram botões e nada
navega. A seção sobe para imediatamente antes da captura de novidades.
O nome no card e no tile alinha à esquerda com o SOU (x=213) via leftX
+ drawCardName extraído; o tile passa a desenhar SEU NOME com o próprio
pipeline real (canvas transparente sobre a base). Modal sem o vão
interno (p-0 sm:p-0) e ajuda legível no tema campaign-site
(--muted-foreground). Remove a variante link e o cardModelHref sem call
site. Unit atualizado (+ drawCardName) e e2e com alinhamento por pixel;
sem migration, sem PII em rede.
2026-09-12 21:01:15 -03:00
Francisco Solla
b03cec7c7b refactor(S13): endurece o compositor após review
- font: espera a família primária (check falhava pela fallback do next/font)
- load de assets/fonte separado do redraw (sem flicker/live-region por tecla)
- pan/zoom com updates funcionais; photoSize memoizado
- foco volta ao tile do catálogo ao fechar (trigger da home desmonta)
- copy de privacidade centralizada; tile deriva dims/cor do modelo
- aria do input de arquivo sem colidir com o botão; +2 unit tests
2026-09-12 03:25:43 -03:00
Francisco Solla
681f3bb566 feat(S13): cards personalizados da campanha no site público
Home ganha a seção Faça parte com os três modelos e a rota /cards
concentra catálogo + compositor client-side (dialog desktop, bottom
drawer mobile): nome no slot medido do mestre com Brexter 700 e foto
full-bleed sob o overlay oficial (pan/zoom clampados), download PNG
sem conta e sem enviar nome/foto. Núcleo puro em src/lib/card* com
unit tests; e2e cobre home→deep-link, nome→PNG real, erro fail-closed,
foto e drawer mobile. Sem migration/PII.
2026-09-12 03:25:43 -03:00
Francisco Solla
8983abc3f5 fix(social-feed): capas do Instagram voltam a carregar e legendas longas não esticam o card
As mídias da Graph API passaram a vir de *.fbcdn.net
(instagram.<pop>.fna.fbcdn.net), host fora do images.remotePatterns — o
otimizador respondia 400 e toda capa do Instagram quebrava. O pattern em
new URL() também pina search:'' e rejeitaria as URLs assinadas mesmo com o
host certo; agora são objetos planos (cdninstagram + fbcdn).

O título do card ganha line-clamp-3 (subtítulo, line-clamp-2) para a
legenda do Instagram não esticar o bento.

Testes: guard unitário do allowlist com URLs assinadas reais casadas pelo
matcher do próprio Next + seam parser→allowlist; e2e com legenda longa no
stub e asserção de -webkit-line-clamp; manifest de e2e afetado passa a
mapear o board de conteúdos para o spec frontend.
2026-09-11 18:09:03 -03:00
Francisco Solla
7259193060 S2-FOLLOWUP (#775) — validate do itemId YouTube deixa de ser código morto
O validate de itemId em social-feed-settings lia data.platform (doc inteiro,
sempre undefined) e nunca validava ID de vídeo em produção. Agora lê
siblingData.platform via helper validateExcludedItemId. Stub YouTube ganha
ids de 11 chars e o spec acompanha, destravando o e2e do describe
'Campaign home content section'. Sem migration.
2026-08-24 23:46:57 -03:00
Francisco Solla
d0161f6d69 test(e2e): unificar logins do usuário de teste no helper adminHeaders com advisory lock (Closes #767) 2026-08-24 18:42:03 -03:00
Francisco Solla
10e0c17078 fix(e2e): OPS83 — polish after review: rename expectSectionCount, toBeOK, settle helper reuse 2026-08-24 07:27:49 -03:00
Francisco Solla
e4cb8d1006 fix(e2e): OPS83 — estabilizar os e2e do verify sem reduzir cobertura; AgendaFeed roda em prod (Closes #824) 2026-08-24 07:27:49 -03:00
Francisco Solla
9467e0f292 fix(campaign): C140 — manual dispatch in 18 forms prevents React 19 form reset on error
Fix manual dispatch em 18 formulários de /campanha que usavam <form action={submitAction}>: campos não controlados voltavam ao defaultValue após qualquer action assentada (sucesso ou erro) do React 19.

- WizardStepFormChrome alterado uma vez (cobre 3 wizard steps)
- 15 forms recebem dispatch manual arquivo a arquivo
- AdvisorPasswordResetButton (2 micro-forms sem campo digitável) ficou como está
- Unit spec novo campaignWizardStepFormChrome.unit.spec.tsx
- CHANGELOG-AGENTS.md cleaned (98 duplicates removed)

Also fixes:
- campaignPageActor writable gate only blocks advisors (was blocking coordinators too)
- campaignLeaderships e2e stability (waitForLoadState before attribute assertion)
2026-08-23 17:54:19 -03:00
Francisco Solla
5b7448832b ops(OPS73-FOLLOWUP): fecha #760 — resíduos da race do usuário compartilhado no e2e (lock único de login) + docs drift 2026-08-23 15:54:49 -03:00
Francisco Solla
3ce5a69555 feat(S11): feed do Instagram configurado não aparece na home — painel de status da sincronização no admin
O fail-closed silencioso da S3 deixava a assessoria cega: token errado não deixava
rastro além do picker vazio. Fim da caixa-preta:

- `instagramSyncStatus` (jsonb hidden) na global `social-feed-settings`, escrito pelo
  render, pelo afterChange (sync awaited quando a credencial IG muda) e pela rota
  `POST /api/social-feed/sync` (botão, auth admin + same-origin).
- `InstagramApiError` + `describeInstagramError`: o fetch parseia o body de erro da
  Graph API e o mapeia para copy pt-BR com a correção (OAuthException/expired →
  "token inválido/expirado ou emitido via Facebook Login — gere pelo Instagram Login";
  "Invalid user id" → confira o ID; 5xx → indisponível; TypeError → rede; AbortError →
  demorou demais). O ID só casa com "user" E "id" juntos (token rejections real falam
  "the user must be logged in" — não podem virar a branch de ID).
- `InstagramSyncStatusPanel` (campo ui irmão do picker): 5 estados fiéis ao rascunho;
  gate respeita o master `enabled`; `outcome` transiente limpo ao editar credencial;
  aria-live nos boxes interativos. Home inalterada (fail-closed intacto).
- Bug real: `afterChange` roda dentro da transação do save (row lock até os hooks
  retornarem); persistir o status via pool numa 2ª conexão deadlockava no lock da
  própria linha (~80-230s/save). Fix: persists do sync-hook na MESMA transação via
  `getPostgresTransactionDatabase` (C6); render/rota sem transação seguem no pool.
  Diagrama: UPDATE transactionid Lock vs idle in transaction; fix verificado 45ms vs 232s.
- Stub IG ganha estado `invalid-token`; runbook docs/ops/instagram-feed-token-runbook.md;
  migration add_instagram_sync_status (jsonb nullable).
- Débitos registrados: #124 (janela de lock) e #125 (polish P3).
- Gates: unit 2463 + int 791; lint/format/tsc/cycles; build; e2e admin 5/5 + frontend serial 19/19.
2026-08-20 00:54:58 -03:00
Francisco Solla
eebe81cd1e feat(S8): seção 'Nossa história' na home — vídeo da trajetória embutido do YouTube (Closes #91) 2026-08-20 02:19:58 +00:00
Francisco Solla
398a91e54a feat(S9): captura de novidades da campanha na home pública (form + CTA do hero)
Seção 'Receba as novidades da campanha' acima do rodapé: nome + WhatsApp
obrigatórios, e-mail/estado/cidade/comentário opcionais, toggle pré-selecionado
'Quero fazer parte do time' gravado como subscription.campaignLevel
(time|esporadico). CTA secundário do hero vira o atalho (#novidades, scroll
suave). Contact + Subscription em withPayloadTransaction com consentimento
novo fail-closed por chave estável 'campanha-novidades' — nada é gravado sem o
texto aprovado no admin. Migration 20260819_192605 (state de contact nullable
+ coluna campaign_level). Impl plan, changelog, int + e2e.
2026-08-20 02:19:58 +00:00
Francisco Solla
cd3f3e2a06 test(S7): pins e2e endurecidos — contrato de borda completo e capa de borda a borda medida 2026-08-19 19:39:09 +00:00
Francisco Solla
4a3c3b709c feat(S7): cards 'Acompanhe de perto' sem raio, borda, sombra ou chip; capa de borda a borda (Closes #90) 2026-08-19 19:39:09 +00:00
Francisco Solla
8bc8900e9d feat(S4): compartilhar conteúdos da home no WhatsApp 2026-08-19 12:50:19 -03:00
Francisco Solla
46038d5a6a fix(e2e S3): goto da home com URL cache-busting no describe da seção de conteúdos
O poll (request.get) convergia no HTML fresco, mas o page.goto servia a
cópia stale do cache heurístico do Chromium (ISR s-maxage sem max-age)
quando a regeneração pós-bust ainda não tinha completado — flake medido no
CI (YT snapshot da S2, 2 flaky) e no prod-mode local (IG snapshot 3/3
retries). cache:'no-cache' não existe nos tipos do Playwright 1.58 e reload
reduz mas não elimina a janela. URL única (?e2e=<ts>) erra todas as
entradas de cache (HTTP + router do Next) e a página sempre vem fresca do
servidor; prod-mode local 9/9 × 2.
2026-08-18 20:30:10 -03:00
Francisco Solla
a638a8acae feat(S3): seção de conteúdos da home de campanha inclui os posts do Instagram
Board "Acompanhe de perto" (S1+S2) ganha o feed automático do perfil oficial:
loader irmão src/utilities/socialFeed/instagramFeed.ts (Graph API /media com
children p/ carrossel + username, unstable_cache tag social-feed + revalidate
300, snapshot cru pré-exclusão persistido via SQL direto, refresh de token
automático com retry 1x — refresh endpoint só renova tokens de Instagram
Login, page tokens caem no fail-closed), global SocialFeedSettings estendida
(instagramEnabled/AccessToken/UserId/MaxItems + snapshot hidden; excludedItems
já cobria a plataforma desde a S2). Requisito nº 1 — picker de exclusão no
admin (primeiro componente custom do repo, campo ui + importmap): lista os
posts do snapshot com thumbnail e toggle "Não exibir" que escreve em
excludedItems. Card com coverAspect square (1:1 do rascunho), badge
Instagram, título = legenda com fallback para post sem legenda, clique no
permalink (noopener), link "Seguir no Instagram →" derivado do username.
Os feeds externos mudam para o subfolder socialFeed/ (pin da S2 previa).
Migration 20260818_192948_add_instagram_social_feed_fields (não destrutiva).
Stub IG no webServer (porta dev+2000, helper socialStub.ts) + 3 e2e novos no
describe serial + kill switch estendido + smoke do picker no admin.
Closes #20
2026-08-18 20:29:50 -03:00
Francisco Solla
cacb6165ad feat(S6): home de campanha sem carrossel no desktop — grade estática em ≥1024px, mobile preservado 2026-08-18 19:32:50 +00:00
Francisco Solla
fe5b11cf24 feat(S2): seção de conteúdos da home de campanha inclui os vídeos do YouTube
Board "Acompanhe de perto" (S1) ganha o feed automático do canal oficial:
global SocialFeedSettings (admin-only, kill switch + toggle + maxItems +
exclusões por item), loader src/utilities/youtubeFeed.ts (Data API v3
search→statistics, unstable_cache tag social-feed + revalidate 300,
fail-closed com snapshot persistido via SQL direto — revalidateTag dentro
de unstable_cache lança no Next 15.4), card generalizado
(CampaignArticleCard → CampaignContentCard, external com noopener) e merge
por recência com o grande = mais recente elegível. Stub HTTP do YouTube no
webServer do Playwright (porta dev+1000) + 4 e2e novos no describe serial.
Migration 20260818_111748_add_social_feed_settings (não destrutiva).
Closes #18
2026-08-18 15:23:50 -03:00
Francisco Solla
a60b3880ca feat(S5): banda visual própria para a seção 'Acompanhe de perto' na home 2026-08-18 13:35:53 -03:00
Francisco Solla
beea467816 fix(S1): revert revalidate=300 — trava o bust por tag no Next 15.4 prod
Medido em probe: com export const revalidate, revalidateTag('posts') para
de regenerar a home (a rota /artigos, sem o export, convergia; a home
ficava stale para sempre). Remove o export e resolve o congelamento da
label relativa por threshold: relativa < 48h, data absoluta além (nunca
mente congelada). Spec: polling positivo do HTML da home pós-revalidate
(ISR serve stale uma vez sob carga) e about:blank antes do cleanup
(prefetch prod de links apagados = 404 no guard).
2026-08-18 05:07:26 +00:00
Francisco Solla
8e18e27c20 fix(e2e S1): poll positivo do HTML da home até convergir pós-revalidate
O warm-up único ainda deixava uma janela de stale-serve sob carga (a
regeneração ISR não completava entre o GET e o goto, e o DOM carregado
nunca refrescava — flake no cleanup sob a suíte paralela). Polling do
estado esperado no HTML do servidor (12x1s) antes do goto torna o
empty-state, o full-state e o cleanup determinísticos.
2026-08-18 05:07:26 +00:00
Francisco Solla
5c48329011 fix(e2e S1): warm-up na home após revalidateTag (ISR pode servir stale uma vez)
Sob a suíte completa em paralelo, a regeneração pós-revalidate às vezes
servia a página velha uma vez; o DOM carregado nunca refrescava e o assert
de cleanup falhava (1 flaky no gate). Requisição GET de warm-up entre o
revalidate e o goto torna o estado determinístico.
2026-08-18 05:07:26 +00:00
Francisco Solla
41dbb564c6 feat(S1): seção de conteúdos na home de campanha (artigos)
Bento 1+4 no desktop e carrossel 1/tela no mobile (~390px) lendo o post
collection com isPostVisible fail-closed; seção some inteira sem posts
visíveis. Zero migration/Consent; home vira ISR com tag posts +
revalidate=300 (label relativa não congela).
2026-08-18 05:07:26 +00:00
Francisco Solla
0aec0d5040 feat(PUB5): slogan 'Mais saúde mais futuro' no hero e rodapé 2026-08-18 01:31:28 +00:00
Francisco Solla
665157a0c0 feat(site): hero da campanha responsivo aos boards do Penpot
A primeira dobra da home pública agora acompanha as referências do Penpot
em 393, 768, 1024, 1280, 1366 e 1920 px. No desktop, a escala e a posição
horizontal das fotos dependem somente da largura: Solla, Lula e Wagner
ficam ancorados ao rodapé real do hero mesmo quando o conteúdo aumenta a
seção, e um palco centralizado de 1920 px preserva a proximidade entre
retrato e texto em monitores ultrawide. E2E fixa a geometria das seis
referências, transições de proporção, desktops baixos, ultrawide e os
overrides da WCAG 1.4.12; o caso de regressão também roda no Firefox.
2026-08-16 20:33:00 -03:00
Francisco Solla
b6be493cdf test(site): assenta navegação do cenário mobile 2026-08-16 00:51:38 -03:00