// Base do kit campos-de-cor: cores, fontes, curvas e medidas. Todo número visual sai daqui. // Os elementos importam só este arquivo, 'react' e 'remotion'. Nada de fora da pasta do kit. import {continueRender, delayRender} from 'remotion'; import f0Url from './fontes/archivo-black.woff2'; import f1Url from './fontes/dm-mono.woff2'; import f2Url from './fontes/playfair-italic.woff2'; // ---------- tela ---------- export const LARGURA = 1080, ALTURA = 1920, FPS = 30; // área segura (Reels/TikTok): o que se lê fica entre estas linhas // v2: margem lateral de 108 px (10%) pra nenhuma palavra encostar na borda. export const SEGURA = {topo: 168, base: 1330, lado: 108}; export const LARGURA_UTIL = LARGURA - SEGURA.lado * 2; // 864 px /** largura máxima do herói (~70%): o campo de cor precisa sobrar em volta da palavra. */ export const MAX_HEROI = 760; // ---------- cor ---------- export const COR = { fundo: '#101010', tinta: '#101010', creme: '#F1EDE4', vermelho: '#F0442A', azul: '#2B3BF0', lima: '#DDFF3A', cortina: '#F1EDE4', }; // ---------- fonte ---------- // Famílias com o prefixo do kit (CC), pra não colidir com outro kit no mesmo estúdio. export const FONTE_D = '"CC Archivo Black", "Archivo Black", Impact, sans-serif'; export const FONTE_T = '"CC DM Mono", "DM Mono", ui-monospace, monospace'; export const FONTE_S = '"CC Playfair Display", "Playfair Display", Georgia, serif'; const LISTA = [ {fam: 'CC Archivo Black', url: f0Url, peso: '400', estilo: 'normal'}, {fam: 'CC DM Mono', url: f1Url, peso: '500', estilo: 'normal'}, {fam: 'CC Playfair Display', url: f2Url, peso: '500 900', estilo: 'italic'}, ]; if (typeof document !== 'undefined' && !(globalThis as Record).__kit_CC) { (globalThis as Record).__kit_CC = true; for (const f of LISTA) { const h = delayRender('campos-de-cor: ' + f.fam); new FontFace(f.fam, `url(${f.url}) format('woff2')`, {weight: f.peso, style: f.estilo}).load() .then((ff) => {document.fonts.add(ff); continueRender(h);}) .catch(() => continueRender(h)); } } // ---------- tempo e curva ---------- export const c01 = (t: number) => Math.max(0, Math.min(1, t)); /** progresso 0..1 de f entre a e b */ export const seg = (f: number, a: number, b: number) => c01((f - a) / (b - a)); /** saída rápida e pouso longo: cubic-bezier(.2,.8,.2,1) aproximado */ export const e5 = (t: number) => 1 - Math.pow(1 - c01(t), 5); /** entrada com overshoot de ~10% (easeOutBack, c1 = 2.2) */ export const eb = (t: number) => {const x = c01(t) - 1, c = 2.2; return 1 + (c + 1) * x * x * x + c * x * x;}; /** entra e sai suave */ export const e3 = (t: number) => {const x = c01(t); return x * x * (3 - 2 * x);}; export const lerp = (a: number, b: number, t: number) => a + (b - a) * t; /** uma batida da trilha do kit em quadros */ export const BATIDA = 14.29; // ---------- texto ---------- /** "Usar *IA* já" -> [{t:'Usar ', d:false}, {t:'IA', d:true}, {t:' já', d:false}] */ export const partes = (texto: string) => texto.split('*').map((t, i) => ({t, d: i % 2 === 1})).filter((p) => p.t.length > 0); export const textoLimpo = (t: string) => t.replace(/\*/g, ''); let canvas: HTMLCanvasElement | null = null; const cache = new Map(); export const larguraTexto = (texto: string, tamanho: number, peso = 800, trackingEm = -0.03, familia = FONTE_D): number => { const chave = `${texto}|${tamanho}|${peso}|${trackingEm}|${familia}`; const c = cache.get(chave); if (c !== undefined) return c; if (typeof document === 'undefined') return texto.length * tamanho * 0.56; canvas = canvas || document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) return texto.length * tamanho * 0.56; const fonte = `${peso} ${tamanho}px ${familia}`; ctx.font = fonte; const w = ctx.measureText(texto).width + texto.length * trackingEm * tamanho; if (document.fonts.check(fonte)) cache.set(chave, w); return w; }; /** o maior tamanho até `tamanho` em que o texto cabe em `largura`. Nunca palavra cortada. */ export const caber = (texto: string, tamanho: number, largura = LARGURA_UTIL, peso = 800, trackingEm = -0.03, familia = FONTE_D) => { const w = larguraTexto(textoLimpo(texto), tamanho, peso, trackingEm, familia); return w > largura ? Math.floor(tamanho * (largura / w)) : tamanho; }; // ---------- câmera ---------- export const CAMERA = {"z": 1.04, "zOsc": 0.015, "push": 0.0005, "dx": 12, "dy": 10, "rot": 0.008, "soco": 0.05};