Aprovado integralmente pelo Flavio em 01/09/2026 ("Aprovado - documentar tudo com detalhes!"). Estende — não substitui — o v0.1 congelado (
07-design-system.md+tokens.css). Os tokens novos deste documento estão anexados aotokens.css(bloco "v0.2"). Os comandos de geração de assets estão consolidados em11-build-assets.md— este documento diz O QUÊ e POR QUÊ; o 11 diz COMO GERAR.
D-A · As ideias-assinatura#
A1 · O fio da vida — ESPECIFICAÇÃO COMPLETA#
O que é. Uma linha SVG contínua que atravessa toda a Jornada, sob as trilhas, cuja espessura em cada ponto é o número de pessoas vivas da família nuclear dele naquele momento. É o argumento do site em forma de linha: de 7 em Kalisz ao fio de 1 em 1945, ao leque de 23.
A métrica (regra fechada — não rediscutir). Contam no fio: o núcleo de origem (pais + os 5 filhos) até 1942; depois, o núcleo que ele formou (Clara + filhos + netos — descendentes diretos e Clara). Cônjuges de filhos/netos não engrossam o fio (manteria de fora a leitura "a família que saiu dele"); eles aparecem no leque do epílogo, onde a frase do slide 14 manda: "1 → 23".
A série de dados (todas as datas de fontes/dados-biograficos.md, a autoridade; o build gera fio-da-vida.json a partir dela — nunca hardcodar no front):
| Data | Δ | Espessura | Evento |
|---|---|---|---|
| 12/12/1914 | +1 | 3 | nasce Mojsie (Hersz 1886 + Regina + ele) |
| 03/02/1917 | +1 | 4 | nasce Frania |
| 04/05/1919 | +1 | 5 | nasce Marjem "Marisha" |
| 06/03/1922 | +1 | 6 | nasce Szyja |
| 16/01/1929 | +1 | 7 | nasce Majer — o pico de Kalisz |
| ago/1930 | −1 | 6 | †Frania, aos 13 (doença) — o primeiro afinamento, antes da guerra |
| jul/1938 | · | 6 | a foto — marcador visual, sem mudança de espessura |
| dez/1939 | split | 1 ∥ 5 | a separação: o fio DELE se aparta do feixe da família (pais + Marisha + Szyja + Majer), que corre paralelo, acima, até 1942 |
| mai–nov/1942 | — | 1 | o feixe da família termina em FADE (não em corte seco): a data exata é incerta; o desvanecimento de ~3 meses de largura é a incerteza desenhada. Legenda usa a fórmula de Majdanek ("segundo o próprio Mojsie, [55:43]") |
| — | — | — | exceção Marisha: o fio dela NÃO termina — vira pontilhado e desvanece até transparência, sem ponto final (destino jamais confirmado). Um fiapo pontilhado dela reaparece na seção "a busca continua" |
| 1942–1950 | · | 1 | o vale — o fio mínimo; ancorar a citação "eu me senti no mundo sozinho" [119:22] |
| 03/06/1950 | +1 | 2 | casamento com Clara |
| 1952 | +1 | 3 | 1ª filha · 1953 +1=4 o filho · 1958 +1=5 2ª filha |
| 1977 | +1 | 6 | Flavio · 1979 =7 · 1982 =8 · 1983 =9 · 1984 =10 · 1985 =11 · 1987 =12 (os sete netos) |
| 18/10/2000 | split | 11+Clara | o fio central termina num ponto marcado (a única terminação seca e digna do gráfico); os fios da descendência seguem até a borda direita |
| epílogo | leque | 23 | o feixe abre no "quinto milagre": 23 vidas (slide 14) — aqui entram todos, bisnetos e cônjuges |
Geometria e comportamento.
- Path SVG por capítulo (a Jornada tem escala distorcida — decisão 7; o fio respeita a régua de cada capítulo),
vector-effect: non-scaling-strokedesligado (a espessura É o dado). - Espessura:
stroke-width = contagem × var(--thread-unit)(token: 1.2px), interpolada em rampas de ~90 dias entre degraus (nascimentos/mortes não são degraus de pixel, são curvas curtas). - Cor
var(--thread); o feixe 1939–42 são linhas paralelas com 2px de vão (legível que são pessoas); o fade de 1942 =strokepara gradiente comstop-opacity1→0 em ~3 meses de eixo. - Desenho progressivo pelo scroll horizontal:
stroke-dasharray/dashoffsetvia scroll-driven animation (B2); comprefers-reduced-motion, o fio já aparece desenhado. - Acessibilidade: o SVG leva
role="img"+aria-labelnarrando a série ("A família dele: sete pessoas em 1929; ele só, de 1942 a 1950; doze em 1987; vinte e três hoje"); os dados também existem como tabela na página "Pessoas" (mesma fonte JSON). - Interação: hover/focus em qualquer ponto do fio → tooltip com contagem + quem ("1945: ele só"); clique → evento mais próximo na timeline.
- Nas telas de morte do capítulo Shoá o fio está presente mas estático (regra congelada: sem motion lúdico ali).
Formato fio-da-vida.json (gerado no build):
{ "unit_px": 1.2,
"points": [
{"date":"1914-12-12","count":3,"event":"nasce-mojsie"},
{"date":"1942-08-15","count":1,"fade_months":3,"event":"familia-majdanek","formula":"majdanek"},
{"date":"2000-10-18","count":12,"terminus":"mojsie","event":"falecimento"}
],
"marisha": {"from":"1939-12-01","style":"dotted-fadeout","never_confirmed":true} }
A2 · O site feito da fita — ESPECIFICAÇÃO#
O vídeo (768×576, 4:3, 25fps, 2h17min14s = 8.237s) é a fonte visual de tudo. Quatro derivados, todos gerados no build (comandos prontos no 11-build-assets.md §3):
- Fundos de capítulo — 1 frame representativo por capítulo (timestamp no campo
bgFramedotimeline.json), blur pesado + dessaturação parcial no ffmpeg; o duotone é CSS (overlay--bgcommix-blend-mode), para respeitar tema claro/escuro sem gerar 2× assets. - Posters de evento — para todo evento com timestamp: frame exato, 640×480, mostrado no hover/focus do dot e como imagem OG do deep-link daquele momento.
- Sprite de scrubbing — 1 frame/10s = 824 miniaturas 160×120, paginadas em sprites 10×10 (9 arquivos JPG ~150–250 KB cada) +
thumbnails.vttcomxywh. O player mostra a miniatura sob o cursor ao arrastar a barra — o gesto de "folhear a fita". - Waveform da voz —
waveform.json(2.000 picos normalizados 0–1 do áudio inteiro). Usos: (a) progresso do player desenhado como onda (o trecho já visto em--accent, o resto em--line-strong); (b) mini-onda estática nosz-audio-chip(o trecho A1–A12 correspondente); (c) ornamento do Memorial: a onda da frase-título [72:33] como linha divisória. Regra: a onda é sempre DELE falando — nunca decoração genérica; cada uso aponta um trecho real com timestamp.
D-B · Técnicas modernas (nativas, zero lib)#
B1 · View Transitions — ESPECIFICAÇÃO#
O site é MPA estático → usar cross-document View Transitions, declarativas:
@view-transition { navigation: auto; } /* crossfade padrão entre páginas */
Elementos com continuidade nomeada (view-transition-name):
| Nome | Elemento | Efeito |
|---|---|---|
vt-pip | o player | o vídeo "viaja" entre páginas sem piscar, do PiP ao player cheio |
vt-photo-{eventId} | foto do evento | "voa" do dot da timeline ao topo do painel |
vt-doc-{docId} | scan no Arquivo | do card à visualização grande |
vt-person-{personId} | retrato em Pessoas | do card à página da pessoa |
vt-hero | a foto de 1938 na home | da home ao capítulo Kalisz |
Duração/easing dos tokens (--t-base, --ease). Progressive enhancement: sem suporte, navegação normal (nada quebra). Com prefers-reduced-motion: só crossfade, sem movimento.
B2 · Scroll-driven animations (CSS animation-timeline) — ESPECIFICAÇÃO#
Sempre dentro de @supports (animation-timeline: view()); fallback = estado final estático.
- Reveal de fotos/cartões:
animation-timeline: view(); animation-range: entry 0% entry 60%;— opacidade 0→1 + translateY 12px→0. NUNCA em documentos de morte (seletor exclui.z-cw). - Parallax do Memorial: 3 camadas (
scroll(root)vertical), deslocamentos 0.9×/1×/1.06× — sutil; o teto de deslocamento é 6% da viewport. - Régua da Jornada + fio da vida: timeline do scroll HORIZONTAL do container (
scroll(nearest inline)) — a régua avança e o fio se desenha conforme se navega. - Anos-fantasma: parallax horizontal leve (0.85×) atrás das trilhas — profundidade.
B3 · Micro-interações — TABELA NORMATIVA#
| Gatilho | Efeito | Duração |
|---|---|---|
| vídeo cruza timestamp de um dot | dot pulsa 1× (scale 1→1.35→1, --c-entrevista) | 450ms |
| turno ativo na transcrição sincronizada | fundo --accent-soft acende e apaga suave | 250ms |
| chip de filtro on/off | fundo desliza, ícone confirma | 150ms |
| painel de evento abre | desliza da direita + sombra "assenta" (--shadow-2→--shadow-3) | 250ms |
hover em z-audio-chip | a mini-onda "respira" (opacity .7→1) | 150ms |
| copiar link de momento | toast discreto "link copiado · [12:34]" | 2s visível |
Regras: nada em loop infinito; nada com som; tudo morre sob prefers-reduced-motion (o reset global do tokens.css já garante).
D-C · Imagem e tipografia#
C1 · Estética do arquivo — ESPECIFICAÇÃO#
- Grão: SVG
feTurbulenceinline (data-URI no CSS, ~600 bytes),opacity: var(--grain-opacity)(token: .025), aplicado aobody::aftercompointer-events:noneeposition:fixed. No tema escuro,--grain-opacity: .035(grão lê mais no escuro). - Duotone/sépia nos heroes: filtro CSS (
sepia(.35) contrast(1.05)) + overlay de gradiente--accenta 8% — nunca gravado no asset (tema-dependente). - Vinheta nas fotos de época:
box-shadow: inset 0 0 48px rgba(0,0,0,.18)via wrapper. - Blur-up (LQIP): cada imagem do build ganha placeholder 24px inline (base64 no JSON, ~300 bytes), exibido com
filter: blur(12px)até o carregamento; transição 250ms. - Formatos: AVIF + WebP + JPEG fallback via
<picture>; larguras 480/960/1600;width/heightsempre declarados (CLS 0);loading="lazy"exceto o LCP da página. - LINHA ÉTICA (inegociável): documentos e fotos históricas nunca passam por IA generativa, "restauração", colorização ou upscale além do interpolador do browser. O grão, o amarelado e o desfoque são evidência da jornada do documento — tratá-los como linguagem. Único retoque permitido: recorte, rotação de alinhamento e ajuste global de níveis, sempre com o original intocado no repositório.
C2 · Tipografia editorial — ESPECIFICAÇÃO#
- Fontes variáveis self-hosted:
SourceSerif4Variable(eixos wght 200–900 + ital) eSourceSans3Variable(wght 200–900) — 1 arquivo WOFF2 por família+ital, subset latin+latin-ext (o polonês precisa: ą ć ę ł ń ó ś ź ż),font-display: swap, preload dos 2 principais. - Números: corpo de texto
font-variant-numeric: oldstyle-nums proportional-nums; timestamps, régua e tabelastabular-nums lining-nums(token utilitário.u-tabular). - Hifenização:
hyphens: autonos blocos longos, comlang="pt-BR"/lang="en"corretos por elemento (nomes/termos poloneses e iídiche marcadoslang="pl"/lang="yi"— também é correto para leitores de tela). - Anos-fantasma: número do capítulo em
--fs-ghost(clamp 6–12rem),font-weight: 200, corvar(--ghost-year-ink)(ink a 6%),font-variant-numeric: oldstyle-nums, atrás das trilhas (z-indexabaixo,aria-hidden="true"), parallax leve (B2). - Aspas tipográficas reais nas citações („ " nos trechos poloneses; " " no português) e travessão — nunca hífen — nos diálogos.
D-D · Performance — METAS NORMATIVAS (medidas no CI do build)#
| Métrica | Meta | Como medir |
|---|---|---|
| Lighthouse (4 colunas) | 100/100/100/100 | lighthouse-ci no build, budget falha o deploy |
| LCP (4G simulado) | < 1,5s | idem |
| JS por página | < 30 KB gzip | du no build com limite |
| CLS | 0 | dimensões declaradas em toda mídia |
| Fontes | 2 preloads, subset, swap | checklist |
Meios já decididos: site estático; prefetch de rotas on hover/viewport (<script> de 1 KB ou Speculation Rules API); vídeo preload="none" + poster; zero third-party no caminho crítico (GA async no fim, ausente na área família); sprites/waveform carregam sob demanda (primeira interação com a barra), nunca no load.
D-E · Alma nos detalhes — ESPECIFICAÇÃO#
::selection { background: var(--accent-soft); }(token no v0.2).- Scrollbar fina nas áreas internas:
scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;. - Favicon: monograma "Z" em Source Serif 4 peso 600 sobre fundo
--bg, SVG comprefers-color-schemeembutido (o SVG pronto está no11-build-assets.md§6) + PNG 180px paraapple-touch-icon. É o mesmo "Z" do logotipo do header — uma identidade só. - OG images por template no build (1200×630): foto do contexto + título serif + a linha "Zeide — eu sobrevivi só para contar" no rodapé; template SVG→PNG no build (11 §7). Cada evento/pessoa/documento tem a sua; o link colado no WhatsApp da família mostra a foto certa (fecha B3 do backlog).
- 404: "Esta página se perdeu — como quase se perdeu esta história. Volte ao começo." + busca + link para a home. Mesma arte da home (a foto de 1938, esmaecida).
- Busca vazia: "nada com esse termo — tente: Kalisz, Groix, Majer, carroça, Majdanek…" (sugestões rotativas vindas do índice real).
- Sem som de UI em lugar nenhum (decisão 11) — só a voz dele, sempre opt-in.
D-F · Ritual de qualidade antes de cada lançamento (v1, v2, v3)#
- Teste com a família real: a pessoa mais velha e a mais nova disponíveis usam o site sem ajuda; observar sem intervir; anotar onde travam; corrigir antes do ar.
- Device-lab mínimo: um iPhone antigo da família + um Android médio + desktop grande.
- Checklist de acessibilidade do
07(teclado completo, leitor de tela na home/entrevista, contraste AA nos dois temas,prefers-reduced-motionde ponta a ponta). - Os 3 fluxos sagrados, cronometrados: home → ouvir a voz dele (< 15s) · achar "Majdanek" na transcrição (< 20s) · abrir um documento do arquivo no celular (< 15s).
- Verificação de conteúdo: fórmula de Majdanek presente onde manda; nenhum dado de vivo na área pública;
pedidos-prontos.mdfora do build (o compilador tem denylist explícita).
Critérios de aceitação por versão#
v1 (Entrevista) — C2 completo · D-D no CI · B3 do player (dot-pulse não se aplica; turno ativo sim) · scrubbing com sprite+VTT · waveform no progresso · favicon+404+OG (páginas de momento ?t=) · grão+seleção+scrollbar · LQIP no que houver de imagem. v2 (Jornada) — A1 integral (fio com dados do JSON, split 1939, fade 1942, Marisha pontilhada, tooltip, tabela-espelho) · B1 (vt-pip, vt-photo, vt-hero) · B2 (régua, reveals, anos-fantasma) · A2 fundos+posters · B3 dot-pulse. v3 (Memorial/Mapa) — parallax B2 · waveform-ornamento com a frase [72:33] · leque do epílogo (A1) · D-F completo com a família antes do ar.