# Lettering: texto com ordem de leitura

Lettering é decisão de edição, não uma segunda legenda. Você escolhe a palavra ou a frase que muda a leitura do
vídeo, dá a ela o peso certo e faz o movimento reforçar o que ela diz. Serve para destaque de frase forte,
título animado, texto em camadas e chamada. Serve também para arrumar um lettering existente em que tudo pesa
igual.

Leia junto: `references/animacao.md` (tempo da palavra e cena própria) e `references/enquadramento.md` (rosto,
zona segura e texto atrás da pessoa).

## O estilo que o André já aprovou

O André tem um lettering aprovado, guardado na skill `lettering-reels` (quando ela está instalada). É um
ponto de partida bom para Reels e anúncio dele e da Vit:

- cada frase vira uma tela de 2 a 4 linhas, centralizada, com as palavras entrando no tempo da fala;
- a palavra que manda em Montserrat 900 grande, lilás (ou rosa; laranja para urgência), contorno escuro forte,
  levemente inclinada, entrando com uma batida;
- o miolo da frase em Montserrat 900 branca, caixa alta, contorno forte;
- conectivos e complementos à mão, em Caveat amarela, minúsculas;
- a frase sobe e some quando começa a próxima;
- "modo leve" (palavras só sobem e aparecem, sem batida) para vídeo mais emocional.

Nesse estilo o lettering escreve a própria fala, então a legenda não repete o que está escrito grande: ou sai
daquele trecho, ou (legenda `discreta`, com `legenda_junto`) continua só nas palavras que não estão grandes. A hierarquia continua
valendo: a palavra lilás é a principal, a branca é apoio, a amarela é ligação. Dentro do projeto HyperFrames, a
peça `lettering` (seção abaixo) faz esse trabalho; um visual que ela não faz vira cena própria. A skill
`lettering-reels` é outro caminho (gera arquivo transparente para o CapCut) e não precisa ser chamada aqui.

Se a pessoa tem outra marca, outro estilo pedido ou uma referência medida, siga isso. O estilo do André é
opção, não obrigação.

## O que escrever

- O pedaço exato da fala. Números, negações, condições, termos técnicos e acentos como foram ditos.
- Paráfrase curta só se não muda a afirmação. Cortar muleta ("né", "tipo") pode.
- Nunca benefício, resultado, oferta, número ou função que não foram ditos.
- Quantidade:
  - destaque de frases fortes: 2 a 4 expressões por trecho, formando um raciocínio completo (menos, se a
    gravação não oferece tantas);
  - anúncio com prova na tela: no máximo duas ideias escritas;
  - corte de conversa ou podcast: uma ou duas expressões.

## Três papéis

Todo texto na tela tem um papel. Classifique antes de desenhar.

| papel | o que é | como aparece |
|---|---|---|
| principal | a ideia que manda naquele instante | maior, mais peso, mais contraste, no lugar mais forte |
| apoio | um complemento curto e indispensável | menor, mais leve, ao lado do principal |
| chamada | o convite à ação | no fim, com o texto inteiro legível antes de sair |

- Só uma ideia principal na tela. Ao lado dela, no máximo um apoio breve.
- O olho chega primeiro no principal pela escala, pelo peso, pelo lugar e pelo contraste. Não por animação forte
  em tudo.
- A ordem também é de tempo: o principal termina de chegar antes de o apoio começar. Enquanto o principal muda,
  o apoio fica parado.
- Tempo de leitura depois que o texto está completo: pelo menos 1 s para até 4 palavras e uns 0,3 s por palavra
  a mais. Se não dá para ler sem pausar o vídeo, aumente a permanência ou diminua o texto.
- No fim do vídeo o tempo de leitura vence o corte seco: quando a frase escrita termina na última palavra, o
  `segura_fim` do `projeto.json` segura a tela depois da fala (nunca um respiro deixado no corte). A última
  expressão fica legível até o último quadro.
- Em fala rápida, conte o tempo antes de escolher as expressões: cada uma ocupa uns 2 s (chegar, 1 s de leitura e
  sair) e a próxima entra na palavra dela. Em 10 s de fala rápida cabem 3. Quando não cabe, tire uma ou junte duas
  numa peça só (a segunda vira o apoio); o build avisa qual expressão fica sem tempo.

## A peça `lettering` do projeto

No `projeto.json`, em `animacoes`, uma peça por tela de texto grande:

```json
{"id": "sozinho", "tipo": "lettering", "principal": "Editou *sozinho*", "apoio": "enquanto eu gravava o próximo",
 "chamada": "Veja como", "em": "editou", "sai": "próximo", "posicao": "topo", "estilo": "bloco"}
```

`principal` é obrigatório; `apoio` e `chamada` são opcionais; `em` e `sai` são a palavra ou o segundo; `posicao`
é `topo`, `meio` ou `base` (sem ela, a primeira que não cobre o rosto, nessa ordem); `estilo` é `bloco` (Montserrat
900, caixa alta, contorno forte) ou `manuscrito` (Caveat, à mão). Os outros campos e o código estão no
`references/animacao-catalogo.md`, peça 12.

O que a peça garante, sem você escrever nada:

- a ordem de leitura: o principal chega primeiro e maior, o apoio só depois que ele terminou, a chamada por último;
- cada palavra na hora em que é dita: o principal e o apoio entram palavra por palavra, no tempo medido na onda
  quando existe o `palavras_onda.json` do corte (`helpers/palavras_na_onda.py`, e não no do Whisper), antecipando no
  máximo 0,15 s; as letras de cada palavra aparecem dentro do tempo em que ela é dita;
- a letra por letra por grafema (o acento junto da letra), com a linha já montada no lugar final;
- nenhum quadro que mude o sentido: número inteiro de uma vez (com "R$", "mil", "%"), negação solta junto da palavra
  de antes;
- o encaixe na ordem desta página: largura medida com a fonte de verdade no peso usado
  (`modelo-projeto/assets/fontes/larguras.json`), até 3 palavras grandes por vez, quebra por sentido em até 3
  linhas, dois momentos (duas telas) quando passa de 3 palavras, e a letra menor só por último, até caber sem
  cobrir o rosto;
- a fonte carregada antes de medir, também na página (a timeline é montada depois do `document.fonts.ready`);
- a legenda escondida no trecho, ou, com `legenda_junto` (o padrão quando a legenda é `discreta`), a legenda
  continuando nas palavras que não estão escritas grandes naquele instante;
- a última expressão legível até o último quadro, quando o `sai` é o fim do corte (também no `segura_fim`);
- o aviso quando o texto completo não fica tempo suficiente para ser lido, dizendo se dá para atrasar o `sai` ou se
  é preciso tirar uma expressão ou juntar duas;
- o som de cada entrada: pop suave na batida do principal (um pouco mais forte na conclusão, a última expressão do
  vídeo), pop baixo no pouso do apoio, pop na chamada;
- uma linha `nota:` com o tamanho da letra e por que não foi maior (a largura ou o rosto).

O que continua com você: escolher as expressões (o pedaço exato da fala, 2 a 4 por trecho), o papel de cada
texto, o momento e o estilo. Um movimento que ela não faz (trocar uma palavra por outra no mesmo lugar, duas
opções frente a frente) é cena própria, com as regras desta página.

## Legenda e lettering

- A legenda fica na região dela (no peito) e acompanha a fala, com até 3 palavras por vez numa linha: é o
  `legenda.max_palavras` 3 do projeto (o `max_letras` quebra antes quando as palavras são longas). Mais que
  isso já é lettering, e vira decisão de hierarquia, não legenda.
- Lettering só nas palavras que mudam o jeito de entender a frase.
- Uma frase nunca aparece escrita grande duas vezes (lettering e legenda juntos). Onde o lettering escreve a fala, a
  legenda sai daquele trecho, ou continua sem as palavras escritas grandes. Na peça `lettering` o build faz isso
  sozinho: com a legenda `discreta`, o padrão é `"legenda_junto": true` (a legenda segue nas palavras que não estão
  grandes, e a fala não fica sem texto enquanto a letra grande é lida); com a legenda `padrao` (grande), a legenda
  sai do trecho. Numa cena própria: `"esconde_legenda": true` ou `"legenda": {"esconder": [[de, ate]]}`.
- Nenhuma palavra dita some da legenda: a frase é dividida por sentido ("Eu gravei" / "esse vídeo" / "uma vez só,")
  e a palavra que ficaria piscando sozinha junta com a vizinha.
- Rosto livre (olhos e boca) e zona segura do Reels: texto entre y 230 e 1530 e entre x 140 e 940 no 9:16.

## Fonte

- Escolha pela identidade da pessoa, pelo tamanho da frase e pelo tamanho na tela. Condensada (Anton, Bebas
  Neue) serve a título curto, não a tudo. Nunca comprima a letra na horizontal para caber.
- Fonte local em arquivo, com licença que cubra o uso. As do modelo (Montserrat, Caveat, JetBrains Mono) são
  OFL e estão em `modelo-projeto/assets/fontes/`.
- Confira se a fonte tem os caracteres do português antes de usar:

  ```python
  # uv run --directory "<SKILL>" python checar_fonte.py '<caminho completo da fonte>'
  import sys
  from PIL import ImageFont
  f = ImageFont.truetype(sys.argv[1], 80)
  vazio = bytes(f.getmask("￿"))            # desenho de caractere que não existe
  faltam = [c for c in "ãõçáéíóúâêôàÃÕÇÁÉÍÓÚÂÊÔÀ" if bytes(f.getmask(c)) == vazio]
  print("faltam:", "".join(faltam) or "nada")
  ```

- Cada peso usado precisa existir em arquivo (ou a fonte ser variável com esse peso).
- Carregue antes de medir e antes do render: `@font-face` com o arquivo. Fonte do sistema não carrega no
  navegador do render.
- Faltou a fonte pedida: escolha uma substituta pela função (mesma largura, mesmo peso), confira as quebras de
  novo e diga a troca na entrega.

## Movimento pelo que a frase quer dizer

Escolha o movimento pelo sentido:

- **revelar uma conclusão:** a frase monta e a última palavra chega com mais peso;
- **montar uma ideia:** pedaços que se juntam numa frase só;
- **trocar uma palavra por outra:** a palavra velha sai inteira e a nova entra no lugar;
- **pôr duas opções frente a frente:** os dois lados na mesma escala, a diferença em destaque.

Fases: um preparo curto, a transformação que dá para entender, uma pausa para ler e a saída, que libera a tela
para o próximo. Às vezes uma fase é tão curta que nem se nota. Entradas que funcionam: crescer, surgir aos poucos,
deslizar um pouco. Sem ricochete forte (`elastic`, `back` exagerado) em frase longa ou em informação que precisa
ser lida na hora.

## Sincronia

- Pela fala real, com a transcrição do corte (`python3 build.py palavras`). Pode antecipar até 0,15 s. A
  transcrição adianta o começo da palavra até 0,3 s: a palavra que manda (a batida da palavra lilás, o pouso
  de uma palavra grande) entra no tempo medido na onda, com `helpers/palavras_na_onda.py` (`references/corte.md`,
  passo 6), posto em segundos no `projeto.json` ou na cena.
- Com várias palavras, cada uma entra no tempo dela, não a expressão inteira de uma vez no começo: "GAGUEJEI"
  escrito inteiro 0,36 s antes de ser dito é texto adiantado. A peça `lettering` faz isso sozinha; numa cena
  própria, use o tempo de cada palavra das `palavras` do trecho.
- Nunca escreva antes o que a pessoa ainda vai desmentir no fim da frase.
- A negação entra junto ou antes da palavra que ela nega. "PRECISA" sozinho na tela por meio segundo, antes do
  "NÃO", diz o contrário do que ela falou.
- Efeito de digitação: o tempo de leitura só começa quando a frase está completa.

## Encaixe de frase longa

Desça a lista de cima para baixo e pare no primeiro passo que fizer a frase caber:

1. A conta da largura só vale feita com a letra que vai aparecer: o mesmo arquivo de fonte e o mesmo peso do
   vídeo. Em Python, `ImageFont.truetype(fonte, px).getlength(texto)`. A Montserrat do modelo engana: é variável
   e, se ninguém mexer, é medida no peso 100, bem mais fina que a 900 da tela. Chame antes
   `set_variation_by_axes([900])`; sem isso, uma linha como "EDITA SOZINHO EM 5 MINUTOS" cabe na conta e passa do
   x 940 no render. No navegador, a medida só acontece depois que `document.fonts.ready` resolve, e a timeline é
   montada por último (regra da `hyperframes-core`).
2. Dê largura ao bloco: no 9:16 são até 800 px (x 140 a 940).
3. Quebre por unidade de sentido. Não separe artigo do nome, número da unidade, "não" do verbo.
4. Redistribua as linhas ou divida a frase em dois momentos (duas telas).
5. Encurte só preservando o conteúdo autorizado. Nome, valor dito, negação e condição nunca somem.
6. Só então diminua a letra. Abaixo do tamanho da legenda (60 px no 9:16) já não funciona como lettering.
7. Confira máscara, contorno e sombra com a linha mais alta, inclusive com acento em cima (Á, É, Ã) e cedilha
   embaixo (Ç). Nada mordido.

## Animação letra por letra

- Separe por caractere que se vê, não por código. Normalize e use o `Intl.Segmenter`. `[...texto]` separa o til
  do A quando o texto veio decomposto, e o acento some ou pula:

  ```js
  const seg = new Intl.Segmenter("pt", { granularity: "grapheme" });
  const letras = [...seg.segment(texto.normalize("NFC"))].map(s => s.segment);   // "NÃO" vira N, Ã, O
  ```

- Espaços e quebras não podem sumir. Ponha cada palavra num `<span>` com `white-space: nowrap` e as letras dentro
  dela; entre as palavras, o espaço normal.
- Ancoragem: monte a linha inteira com todas as letras já no lugar final, invisíveis (`opacity: 0`), e só revele.
  Linha que se recentraliza a cada letra nova faz o título andar de lado.
- Troca de palavra: nenhum quadro no meio da troca pode formar outra palavra, esconder uma negação ou mostrar um
  valor errado. Na dúvida, troque a palavra inteira.

## Texto atrás do corpo

Letra passando por trás da pessoa só com o recorte aprovado no teste (`references/enquadramento.md`, "Portão do
recorte") e alinhado com o vídeo. Sem esse recorte, ponha o texto num espaço vazio ao lado da pessoa ou encostado
em algo que já está no cenário, e não diga na entrega que tirou o fundo. A palavra escondida em parte tem que continuar
legível.

## Teste de fundo

Confira o texto em cima da parte mais clara e da parte mais cheia de detalhe que passam de verdade naquele
trecho, não num quadro qualquer. Se some em alguma, mais contorno, sombra ou outro lugar.

## Revisão de hierarquia

A queixa costuma vir assim: "tá tudo do mesmo tamanho", "tá pesado", "não sei pra onde olhar". O conserto é por
papel, não por gosto:

- Todo texto da tela ganha um papel: é a legenda da fala, o título que manda naquela tela, um apoio menor ou a
  chamada do fim. O que não tem papel sai, e o que só repete a legenda também.
- Palavra nova não entra nessa revisão. Na tela fica o que a pessoa falou ou o que ela já aprovou por escrito.
- Cada papel tem um tamanho, um peso e um lugar, e isso vale do primeiro ao último segundo. Título enorme no gancho
  e miúdo no meio do vídeo é justamente o "tudo igual" ao contrário.
- Fonte e cores aprovadas ficam, a não ser que atrapalhem a leitura. Fala, cortes e oferta nem entram na conversa.
- Para ela decidir, mande o mesmo trecho duas vezes, como estava e como ficou, com três ou quatro linhas do que
  mudou. Por exemplo: "o 'EDITADO COM IA' agora é o único texto grande; o 'sem abrir o CapCut' desceu para apoio,
  menor, embaixo dele".

## Conferir

No arquivo exportado, olhe três coisas: a frase mais comprida, toda a acentuação e a animação mais trabalhosa.
Está certo quando:

- dá para perceber o que manda numa tela de celular;
- o texto inteiro se lê sem pausar o vídeo;
- nenhuma letra sai cortada por máscara, borda ou outra peça;
- o texto diz o que a pessoa disse, na hora em que ela disse.

## Na entrega

Registre as fontes usadas: família, peso, arquivo (caminho relativo ao projeto), origem e licença, e qualquer
substituição. A fonte só vai junto com os arquivos entregues se a licença deixar redistribuir; fonte comercial
instalada no computador não vai.
