🎨 A Paleta
Oito variáveis CSS. Uma por papel. Zero improvisação.
O house style não é uma lista de cores bonitas — é um sistema com papel definido para cada tom. Fundo de noite (#0D1321), painéis ligeiramente mais claros, borda sutil, texto creme quente, muted para hierarquia, e âmbar como accent único dominante. O ciano (#2EC4B6) é reservado exclusivamente para código e valores técnicos.
:root {
--bg: #0D1321; /* azul-noite – NUNCA preto puro */
--bg2: #1D2D44; /* painéis e cards */
--bg3: #3E5C76; /* bordas e divisores */
--fg: #F0EBD8; /* texto creme quente */
--muted: #748CAB; /* secundário / hierarquia */
--accent: #FFC300; /* âmbar — destaque ÚNICO */
--accent2: #FCA311; /* âmbar quente p/ gradientes */
--code: #2EC4B6; /* verde-água — só código/valores */
}
- ✓Usar
#0D1321como fundo em todas as cenas - ✓Âmbar só para o accent dominante (CTAs, destaques)
- ✓Ciano só para código, URLs e valores técnicos
- ✓Fundo idêntico em todas as cenas do vídeo
- ✗Usar
#000000como fundo (parece vídeo de YouTuber noob) - ✗Misturar dois accents na mesma cena (verde + âmbar)
- ✗Usar ciano para texto decorativo
- ✗Mudar a paleta de cena para cena
🔤 Tipografia
Três fontes. Três papéis. Nenhuma ambiguidade.
O sistema usa Sora para headlines (peso 700–800, escala vídeo 72–172px em 16:9), Inter para corpo e interface (28–42px), e JetBrains Mono para código, URLs e labels técnicos. As três fontes têm .woff2 locais — o gerador nunca faz request para CDN em runtime.
dark premium.
Legível em tela grande, sem distração.
Durante a renderização com Chrome headless, a página não pode fazer requests externos. Se a fonte vier de CDN, o Chrome renderiza com fallback — e o vídeo some no render. O script fetch-fonts.mjs baixa as .woff2 (subset latin) e gera assets/fonts/fonts.css com @font-face local antes de qualquer renderização.
@font-face{font-family:'Sora';font-style:normal;font-weight:700;
font-display:block;src:url('./fonts/Sora-700.woff2') format('woff2');}
@font-face{font-family:'Sora';font-style:normal;font-weight:800;
font-display:block;src:url('./fonts/Sora-800.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;
font-display:block;src:url('./fonts/Inter-400.woff2') format('woff2');}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400;
font-display:block;src:url('./fonts/JetBrainsMono-400.woff2') format('woff2');}
/* subset: latin — cobre PT-BR: á à â ã é ê í ó ô õ ú ç */
node fetch-fonts.mjs — baixa .woff2, gera fonts.css
build-index.mjs — injeta readFileSync("fonts.css") no HTML
🌌 Camada de Fundo Persistente
O fundo que respira — sempre presente, nunca competindo.
Cada cena tem uma camada de fundo persistente marcada com data-layout-ignore. Ela nunca é reposicionada pelo layout engine. Contém quatro elementos: glow radial âmbar respirando, ghost text gigante driftando, grid hairline e grão (ruído SVG). Juntos criam profundidade sem distrair.
O atributo data-layout-ignore sinaliza ao gerador que esse elemento fica em position:absolute; z-index:-1 e não entra no flow do layout. Sem ele, o ghost text ou o glow deslocam o conteúdo real da cena.
<!-- FUNDO PERSISTENTE — data-layout-ignore -->
<div data-layout-ignore class="bg-layer">
<!-- glow radial âmbar respirando -->
<div class="glow-amber"></div>
<!-- ghost text gigante driftando -->
<div class="ghost-text">DARK</div>
<!-- grid hairline -->
<svg class="grid-lines" ...></svg>
<!-- grão (SVG feTurbulence) -->
<canvas class="grain"></canvas>
</div>
.bg-layer {
position: absolute; inset: 0; z-index: -1; overflow: hidden;
}
.glow-amber {
position: absolute; top: 40%; left: 50%;
transform: translate(-50%, -50%);
width: 60%; height: 40%;
background: radial-gradient(ellipse, #FFC300 0%, transparent 70%);
opacity: 0.06;
animation: breathe 4s ease-in-out infinite;
}
.ghost-text {
position: absolute; font-family: 'Sora', sans-serif;
font-size: 172px; font-weight: 800;
color: #F0EBD8; opacity: 0.035;
animation: drift 8s ease-in-out infinite;
}
@keyframes breathe {
0%,100% { opacity:.04; transform: translate(-50%,-50%) scale(1); }
50% { opacity:.08; transform: translate(-50%,-50%) scale(1.08); }
}
@keyframes drift {
0% { transform: translateX(0px) translateY(0px); }
33% { transform: translateX(12px) translateY(-6px); }
66% { transform: translateX(-8px) translateY(4px); }
100% { transform: translateX(0px) translateY(0px); }
}
Decorativos devem ficar entre 12–25% de opacidade. Abaixo de 12% some na compressão H.264. Acima de 25% compete com o conteúdo e parece amador. O ghost text fica em ~3.5% (quase invisível, só sensação de profundidade).
💾 Fontes Locais .woff2
Subset latin. @font-face local. Zero CDN em render.
O script fetch-fonts.mjs usa o User-Agent do Chrome 131 para simular browser, faz request à API do Google Fonts, filtra apenas o subset latin (unicode-range U+0000-00FF cobre todo PT-BR: á à â ã é ê í ó ô õ ú ç), baixa os .woff2 e gera assets/fonts/fonts.css.
- ✓Rodar
node fetch-fonts.mjsuma vez por projeto - ✓Usar
font-display:block(sem flash) - ✓Commitar
assets/fonts/no repositório - ✓Verificar subset latin com
unicode-range
- ✗Link para Google Fonts CDN no HTML de cena
- ✗Usar
font-display:swap(causa flash no render) - ✗Baixar todos os subsets (aumenta tamanho sem ganho PT-BR)
- ✗Ignorar o .gitignore — fonts devem ser commitadas
🎬 Escala de Vídeo, Não Web
8–10 elementos por cena. Headlines em 64–172px. Movimento ambiente em tudo.
O maior erro ao criar vídeos com HTML é usar escala web. Em 1920×1080 com zoom 1:1, texto de 16px some. O house style define headline mínima de 64px, corpo 28–42px, e decorativos com 12–25% de opacidade para criar camadas sem poluir. 8–10 elementos por cena é o limite — mais que isso cria caos visual na compressão.
Toda decoração tem motion ambiente: entradas 0.4–0.6s, eases variados, combinando transform + opacity, stagger de 0.08–0.14s entre elementos. A regra é: se é decorativo, ele respira. Se é conteúdo, ele aparece uma vez e para.
#0D1321CC
🏁 A CTA INEMA.CLUB
A última cena. A assinatura padrão. Não remover jamais.
A scene9 (última cena de todo vídeo HyperFrames) é a CTA INEMA.CLUB: texto "CONTINUA EM" em muted, INEMA em creme (--fg), .CLUB em âmbar com drop-shadow glow, e 🌐 inema.club em JetBrains Mono. É a assinatura do canal — todos os vídeos terminam igual.
function scene9() {
return `
<div class="cta-wrap">
<div class="cta-pre">CONTINUA EM</div>
<div class="cta-brand">
<span class="cta-inema">INEMA</span>
<span class="cta-club">.CLUB</span>
</div>
<div class="cta-url">🌐 inema.club</div>
</div>`;
}
/* CSS correspondente */
.cta-pre { font-family:'Inter'; color:var(--muted); letter-spacing:.2em; }
.cta-brand{ font-family:'Sora'; font-weight:800; font-size:clamp(72px,8vw,120px); }
.cta-inema{ color:var(--fg); } /* INEMA — creme */
.cta-club { color:var(--accent); /* .CLUB — âmbar */
filter:drop-shadow(0 0 16px #FFC300aa); }
.cta-url { font-family:'JetBrains Mono'; color:var(--code); } /* 🌐 inema.club */
A narração padrão da scene9 é: "Isso é conteúdo do INEMA ponto CLUB. Acesse: inema ponto club." — gerada com pf_dora --speed 0.98. Duração típica: ~3.84s. LEAD: 0.5s, TAIL: 0.9s.
- ✓Manter scene9 como última cena de todo vídeo
- ✓INEMA em
--fg(creme), .CLUB em--accent(âmbar) - ✓Drop-shadow glow no .CLUB
- ✓URL em JetBrains Mono + ciano
- ✗Remover ou pular a scene9
- ✗Mudar a cor de .CLUB para outra cor da trilha
- ✗Usar fonte diferente na CTA
- ✗Omitir o 🌐 na URL
📋 Resumo do Módulo 3.2
- ✓A paleta de 8 variáveis CSS com papéis fixos
- ✓âmbar como accent ÚNICO dominante (
#FFC300) - ✓Três fontes: Sora / Inter / JetBrains Mono com papéis distintos
- ✓Por que
.woff2local e nunca CDN em render - ✓Camada de fundo persistente com
data-layout-ignore - ✓Escala de vídeo: 64–172px headlines, 8–10 elementos/cena
- ✓CTA INEMA.CLUB: INEMA creme + .CLUB âmbar + glow + 🌐
-
📄
references/house-style.md -
📄
scripts/composition-template.mjs -
📄
scripts/fetch-fonts.mjs - 🔑 Regra âmbar: 1 accent. Fundo idêntico. NUNCA CDN.