/*
 * Modelos ANIMADOS (out/2026): já vêm com a animação de cada peça, a duração
 * de cada cena, o movimento do fundo e as transições, prontos para virar
 * vídeo (reels, story, status) ou post animado. A pessoa só troca o texto, a
 * foto e as cores; o tempo de cada peça fica na linha do tempo do editor.
 *
 * Fotos e recortes do depósito da Ktalogu (os mesmos dos modelos dos ramos e
 * das canecas: Unsplash e Pexels, uso comercial livre), figurinhas Fluent
 * Emoji (MIT).
 */
import { animacaoNova, type AnimacaoDaPeca, type EfeitoDaAnimacao, type MovimentoDoFundo, type TransicaoDaPagina } from "./animacao";
import { documentoDasPaginas, novoId, type DocumentoDoBanner, type Peca, type PecaDeImagem } from "./documento";
import { documento, fundoDoBanner, type PedidoDoModelo } from "./modelos-base";
import { DEPOSITO_DAS_FIGURINHAS } from "./pecas-novas";
import { comAlfa, contato, f, foto, foto$, html, ic, linear, marca, nada, radial, sombraDe, t, tex, trecho } from "./modelos-ramos";
import type { ModeloDoEditor } from "./modelos";

const caneca$ = (nome: string) => `https://ptpstwltddugnnlewvbw.supabase.co/storage/v1/object/public/products/editor-modelos/canecas/${nome}.webp`;
const W = 1080;
const STORY = 1920;
const POST = 1350;

/* --------------------------------------------------------- a animação */

type Extra = Partial<AnimacaoDaPeca>;
/** A peça (ou as peças, que viram um grupo e entram juntas) com a entrada em `inicio`. */
function anima<T extends Peca>(pecas: T | T[], entrada: EfeitoDaAnimacao | null, inicio: number, extra: Extra = {}): T[] {
  const lista = Array.isArray(pecas) ? pecas : [pecas];
  const grupo = lista.length > 1 ? novoId("g") : undefined;
  const a = animacaoNova(entrada, { inicio, ...extra });
  return lista.map((p) => ({ ...p, animacao: a, ...(grupo ? { grupo } : {}) }));
}
const pulsar = (ritmo = 1.4): Extra => ({ enfase: "pulsar", ritmo });
const flutuar = (ritmo = 2.2): Extra => ({ enfase: "flutuar", ritmo });

function cena(doc: DocumentoDoBanner, duracao: number, fundo: MovimentoDoFundo = "parado", transicao: TransicaoDaPagina | null = null): DocumentoDoBanner {
  return { ...doc, animacao: { duracao, fundo }, ...(transicao ? { transicao } : {}) };
}
const fig = (nome: string, chave: string, x: number, y: number, lado: number, rot = 0): PecaDeImagem => foto(nome, `${DEPOSITO_DAS_FIGURINHAS}/${chave}.webp`, { x, y, w: lado, h: lado, rot }, { ajuste: "conter" });

/* =============================================================== STORY */

/* Contagem da Black Friday: o BLACK entra da esquerda, o FRIDAY vazado da direita, o selo bate e pulsa, a seta flutua. */
function contagemBlackFriday(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFD400";
  const pecas: Peca[] = [
    ...anima(f("Brilho", "circulo", { x: -260, y: 260, w: 1600, h: 1600 }, radial("#7C3AED", "#07060B", 0.85, 0)), "surgir", 0, { duracao: 1.2, ...pulsar(3) }),
    tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: STORY }, "#FFFFFF", { opacidade: 0.06, quantidade: 34 }),
    ...anima(marca(p, 60, 120, 64, "#FFFFFF"), "surgir", 0.1),
    ...anima(t("Black", { x: 40, y: 470, w: 1000, h: 340 }, { texto: "BLACK", fonte: "anton", peso: 400, tamanho: 300, linha: 0.95, cor: "#FFFFFF", alinhamento: "centro" }), "deslizar", 0.25, { direcao: "direita", duracao: 0.6 }),
    ...anima(
      t("Friday", { x: 40, y: 790, w: 1000, h: 340 }, { texto: "FRIDAY", html: html(trecho("FRIDAY", { vazado: { cor: AMARELO, largura: 5 } })), fonte: "anton", peso: 400, tamanho: 300, linha: 0.95, cor: AMARELO, alinhamento: "centro" }),
      "deslizar",
      0.4,
      { direcao: "esquerda", duracao: 0.6 },
    ),
    ...anima(
      [
        f("Selo", "explosao", { x: 720, y: 150, w: 300, h: 300, rot: -10 }, AMARELO, { pontas: 16, profundidade: 0.16 }),
        t("Desconto", { x: 745, y: 205, w: 250, h: 190, rot: -10 }, { texto: "ATÉ\n70%", fonte: "anton", peso: 400, tamanho: 76, linha: 0.92, cor: "#07060B", alinhamento: "centro" }),
      ],
      "carimbo",
      1.1,
      { duracao: 0.5, ...pulsar(1.3) },
    ),
    ...anima(t("Faltam", { x: 250, y: 1180, w: 580, h: 96 }, { texto: "FALTAM 3 DIAS", fonte: "montserrat", peso: 800, tamanho: 44, espaco: 0.12, cor: "#07060B", alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF" } }), "subir", 1.6),
    ...anima(t("Detalhe", { x: 110, y: 1310, w: 860, h: 130 }, { texto: "Os menores preços do ano em canecas, camisetas e brindes", fonte: "manrope", peso: 600, tamanho: 40, linha: 1.25, cor: "#D9D3EA", alinhamento: "centro" }), "surgir", 1.9),
    ...anima(
      [
        ic("Seta", "seta-direita", 505, 1600, 70, "#FFFFFF", { rot: -90, espessura: 2.6 }),
        t("Arraste", { x: 240, y: 1690, w: 600, h: 70 }, { texto: "ARRASTE PARA CIMA", fonte: "montserrat", peso: 800, tamanho: 30, espaco: 0.14, cor: "#FFFFFF", alinhamento: "centro" }),
      ],
      "subir",
      2.3,
      flutuar(1.2),
    ),
  ];
  return cena(documento(W, STORY, fundoDoBanner({ cor: "#07060B", textura: "nenhuma" }), pecas), 6, "aproximar");
}

/* Lançamento em três cenas: "VEM AÍ" escrito, o produto que pula (zoom), "JÁ DISPONÍVEL" carimbado (empurra). */
function lancamentoEmTresCenas(p: PedidoDoModelo): DocumentoDoBanner {
  const ROXO = "#3B1FE0";
  const LIMA = "#C8FF3D";
  const TINTA = "#140C3A";
  const fundo = fundoDoBanner({ cor: ROXO, cor2: "#7C3AED", angulo: 160, textura: "nenhuma" });
  const um = cena(
    documento(W, STORY, fundo, [
      tex("Raios", "raios", { x: 0, y: 0, w: W, h: STORY }, "#FFFFFF", { opacidade: 0.06, quantidade: 30 }),
      ...anima(marca(p, 330, 140, 64, "#FFFFFF", "centro"), "surgir", 0),
      ...anima(t("Vem aí", { x: 60, y: 580, w: 960, h: 600 }, { texto: "VEM\nAÍ", fonte: "anton", peso: 400, tamanho: 250, linha: 1.08, cor: "#FFFFFF", alinhamento: "centro" }), "maquina", 0.3, { duracao: 0.9 }),
      ...anima(t("Algo novo", { x: 120, y: 1150, w: 840, h: 110 }, { texto: "algo novo está chegando…", fonte: "caveat", peso: 700, tamanho: 70, cor: LIMA, alinhamento: "centro" }), "desfocar", 1.3),
    ]),
    2.8,
    "aproximar",
  );
  const dois = cena(
    documento(W, STORY, fundo, [
      ...anima(f("Halo", "circulo", { x: 90, y: 360, w: 900, h: 900 }, radial("#8E7BFF", ROXO, 0.95, 0)), "aproximar", 0, pulsar(2.4)),
      ...anima(foto("Produto", foto$("caneca-branca-recorte"), { x: 190, y: 430, w: 700, h: 700 }, { ajuste: "conter", sombra: sombraDe("#0B0530", 40, 60, 0.5) }), "pop", 0.25, flutuar(2.4)),
      ...anima(t("Nova coleção", { x: 40, y: 1240, w: 1000, h: 200 }, { texto: "NOVA COLEÇÃO", fonte: "anton", peso: 400, tamanho: 150, cor: "#FFFFFF", alinhamento: "centro" }), "subir", 0.8),
      ...anima(t("Canecas", { x: 120, y: 1450, w: 840, h: 80 }, { texto: "Canecas personalizadas com a sua arte", fonte: "manrope", peso: 700, tamanho: 42, cor: LIMA, alinhamento: "centro" }), "surgir", 1.2),
    ]),
    3.2,
    "parado",
    { tipo: "zoom", duracao: 0.6 },
  );
  const tres = cena(
    documento(W, STORY, fundoDoBanner({ cor: LIMA, textura: "nenhuma" }), [
      ...anima(t("Já disponível", { x: 40, y: 540, w: 1000, h: 500 }, { texto: "JÁ\nDISPONÍVEL", fonte: "anton", peso: 400, tamanho: 190, linha: 1.1, cor: TINTA, alinhamento: "centro" }), "carimbo", 0.35, { duracao: 0.5 }),
      ...anima(t("Peça", { x: 120, y: 1070, w: 840, h: 80 }, { texto: "Peça agora pelo WhatsApp", fonte: "manrope", peso: 700, tamanho: 46, cor: TINTA, alinhamento: "centro" }), "subir", 0.9),
      ...anima(contato(330, 1200, TINTA, 40), "subir", 1.1),
      ...anima(t("Compre", { x: 270, y: 1400, w: 540, h: 110 }, { texto: "COMPRE AGORA", fonte: "montserrat", peso: 800, tamanho: 44, espaco: 0.08, cor: LIMA, alinhamento: "centro", fundo: { forma: "pilula", cor: TINTA } }), "pop", 1.5, pulsar(1.2)),
      ...anima(marca(p, 330, 1680, 64, TINTA, "centro"), "surgir", 1.7),
    ]),
    3.4,
    "parado",
    { tipo: "empurrar", duracao: 0.5 },
  );
  return documentoDasPaginas([um, dois, tres]);
}

/* Oferta relâmpago: os raios giram sem parar, o raio quica e treme, o 50% OFF bate e treme. */
function ofertaRelampagoAnimada(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFD400";
  const TINTA = "#141414";
  const pecas: Peca[] = [
    ...anima(tex("Raios", "raios", { x: -560, y: -140, w: 2200, h: 2200 }, "#FFFFFF", { opacidade: 0.4, quantidade: 24, bloqueada: false }), null, 0, { enfase: "girar", ritmo: 16 }),
    ...anima(marca(p, 60, 110, 60, TINTA), "surgir", 0),
    ...anima(ic("Raio", "raio", 400, 250, 280, TINTA, { preenchido: true }), "quicar", 0.2, { duracao: 0.9, enfase: "tremer", ritmo: 1.6 }),
    ...anima(t("Oferta", { x: 40, y: 540, w: 1000, h: 290 }, { texto: "OFERTA", fonte: "anton", peso: 400, tamanho: 240, cor: TINTA, alinhamento: "centro" }), "pop", 0.6),
    ...anima(t("Relâmpago", { x: 40, y: 820, w: 1000, h: 220 }, { texto: "RELÂMPAGO", fonte: "anton", peso: 400, tamanho: 170, cor: "#E11D48", alinhamento: "centro" }), "neon", 0.9, { duracao: 0.9 }),
    ...anima(
      [f("Faixa", "retangulo", { x: 90, y: 1060, w: 900, h: 270, rot: -4 }, TINTA, { raio: 28 }), t("50% OFF", { x: 90, y: 1070, w: 900, h: 250, rot: -4 }, { texto: "50% OFF", fonte: "anton", peso: 400, tamanho: 200, cor: AMARELO, alinhamento: "centro" })],
      "carimbo",
      1.5,
      { duracao: 0.45, enfase: "tremer", ritmo: 2 },
    ),
    ...anima(t("Só hoje", { x: 140, y: 1400, w: 800, h: 80 }, { texto: "Só hoje, até 23h59", fonte: "montserrat", peso: 800, tamanho: 46, cor: TINTA, alinhamento: "centro" }), "maquina", 2.1, { duracao: 1 }),
    ...anima(t("Garanta", { x: 270, y: 1560, w: 540, h: 110 }, { texto: "GARANTA O SEU", fonte: "montserrat", peso: 800, tamanho: 42, espaco: 0.08, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor: TINTA } }), "pop", 3, pulsar(1.1)),
  ];
  return cena(documento(W, STORY, fundoDoBanner({ cor: AMARELO, textura: "nenhuma" }), pecas), 6);
}

/* Os bastidores em movimento: a foto aproxima devagar, o play pulsa, o título é revelado e os passos sobem. */
function bastidoresEmMovimento(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFD400";
  const pecas: Peca[] = [
    foto("Bastidores", foto$("prensa-amarelo"), { x: 0, y: 0, w: W, h: STORY }, { bloqueada: true, enquadre: { zoom: 1.05, x: 40, y: 50 }, filtros: { brilho: 88, contraste: 115, saturacao: 112, desfoque: 0, vinheta: 45 } }),
    f("Véu", "retangulo", { x: 0, y: 0, w: W, h: STORY }, linear("#000000", "#000000", 180, 0.2, 0.92)),
    ...anima(marca(p, 60, 120, 70, "#FFFFFF", "esquerda", 420), "surgir", 0.2),
    ...anima(t("Etiqueta", { x: 60, y: 230, w: 330, h: 70 }, { texto: "BASTIDORES", fonte: "montserrat", peso: 800, tamanho: 28, espaco: 0.16, cor: "#0A0A0A", alinhamento: "centro", fundo: { forma: "pilula", cor: AMARELO } }), "pop", 0.4),
    ...anima([f("Botão de play", "circulo", { x: 430, y: 690, w: 220, h: 220 }, comAlfa(AMARELO, 0.95), { sombra: sombraDe("#000000", 16, 40, 0.45) }), f("Play", "triangulo", { x: 505, y: 745, w: 100, h: 110, rot: 90 }, "#0A0A0A")], "pop", 0.8, pulsar(1.3)),
    ...anima(t("Assista", { x: 290, y: 930, w: 500, h: 70 }, { texto: "assista até o final", fonte: "caveat", peso: 700, tamanho: 48, cor: "#FFFFFF", alinhamento: "centro" }), "maquina", 1.2, { duracao: 0.8 }),
    ...anima(
      t("Título", { x: 56, y: 1060, w: 970, h: 430 }, { texto: "COMO NASCE\nSUA ESTAMPA", html: html(`COMO NASCE<br>${trecho("SUA ESTAMPA", { cor: AMARELO })}`), fonte: "anton", peso: 400, tamanho: 176, linha: 0.94, cor: "#FFFFFF" }),
      "revelar",
      1.7,
      { duracao: 0.8 },
    ),
    ...anima(f("Linha", "retangulo", { x: 60, y: 1520, w: 90, h: 6 }, AMARELO), "revelar", 2.4, { duracao: 0.4 }),
    ...anima(t("Passos", { x: 60, y: 1546, w: 900, h: 70 }, { texto: "Arte • Impressão • Prensa • Pronta", fonte: "manrope", peso: 700, tamanho: 38, cor: "#FFFFFF" }), "subir", 2.6),
  ];
  return cena(documento(W, STORY, fundoDoBanner({ cor: "#0A0A0A", textura: "nenhuma" }), pecas), 6, "aproximar");
}

/* Dia das Mães: a foto aproxima, os corações pulam e flutuam, o título sai do borrado. */
function diaDasMaesAnimado(p: PedidoDoModelo): DocumentoDoBanner {
  const ROSA = "#BE185D";
  const pecas: Peca[] = [
    ...anima(marca(p, 330, 110, 60, ROSA, "centro"), "surgir", 0),
    ...anima(foto("Foto", caneca$("mae-filha"), { x: 140, y: 300, w: 800, h: 1000 }, { raio: 400, borda: { cor: "#FFFFFF", largura: 14 }, sombra: sombraDe("#831843", 24, 50, 0.25), enquadre: { zoom: 1.05, x: 50, y: 40 } }), "aproximar", 0.2, { duracao: 0.9 }),
    ...anima(fig("Coração 1", "coracao-com-laco", 40, 280, 220, -12), "pop", 0.9, flutuar(2.6)),
    ...anima(fig("Coração 2", "coracao-rosa", 830, 520, 180, 14), "pop", 1.05, flutuar(2.2)),
    ...anima(fig("Coração 3", "coracao-vermelho", 70, 1150, 150, 8), "pop", 1.2, flutuar(2.9)),
    ...anima(t("Título", { x: 60, y: 1340, w: 960, h: 200 }, { texto: "Feliz Dia das Mães", fonte: "great-vibes", peso: 400, tamanho: 130, cor: ROSA, alinhamento: "centro" }), "desfocar", 1.4, { duracao: 0.9 }),
    ...anima(t("Apoio", { x: 120, y: 1540, w: 840, h: 80 }, { texto: "Presentes que guardam memórias", fonte: "manrope", peso: 700, tamanho: 42, cor: "#831843", alinhamento: "centro" }), "subir", 1.9),
    ...anima(t("Encomende", { x: 260, y: 1680, w: 560, h: 104 }, { texto: "ENCOMENDE O SEU", fonte: "montserrat", peso: 800, tamanho: 40, espaco: 0.08, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor: ROSA } }), "pop", 2.4, pulsar(1.3)),
  ];
  return cena(documento(W, STORY, fundoDoBanner({ cor: "#FDE2E4", cor2: "#FCE7F3", angulo: 180, textura: "nenhuma" }), pecas), 6);
}

/* ================================================================ POST */

/* Depoimento: as aspas pulam, as estrelas acendem uma por uma, o texto é escrito e a cliente aparece. */
function depoimentoAnimado(p: PedidoDoModelo): DocumentoDoBanner {
  const TINTA = "#2B1D12";
  const OURO = "#F59E0B";
  const pecas: Peca[] = [
    ...anima(t("Aspas", { x: 70, y: 40, w: 300, h: 470 }, { texto: "“", fonte: "dm-serif-display", peso: 400, tamanho: 420, linha: 1, cor: "#F4B860" }), "pop", 0.2),
    ...[0, 1, 2, 3, 4].flatMap((i) => anima(ic(`Estrela ${i + 1}`, "estrela", 90 + i * 92, 380, 76, OURO, { preenchido: true }), "pop", 0.6 + i * 0.12, { duracao: 0.45 })),
    ...anima(t("Depoimento", { x: 90, y: 500, w: 900, h: 420 }, { texto: "Amei a caneca! Chegou antes do prazo e a estampa ficou perfeita. Já pedi mais duas.", fonte: "dm-serif-display", peso: 400, tamanho: 64, linha: 1.25, cor: TINTA }), "maquina", 1.3, { duracao: 2 }),
    ...anima(foto("Cliente", foto$("menina-presente"), { x: 90, y: 1000, w: 150, h: 150 }, { circulo: true, borda: { cor: "#FFFFFF", largura: 6 } }), "pop", 3.4),
    ...anima([t("Nome", { x: 270, y: 1010, w: 600, h: 60 }, { texto: "Mariana Souza", fonte: "montserrat", peso: 800, tamanho: 40, cor: TINTA }), t("Cidade", { x: 270, y: 1070, w: 600, h: 60 }, { texto: "cliente de Campinas", fonte: "manrope", peso: 600, tamanho: 32, cor: "#8A6A4F" })], "subir", 3.6),
    ...anima(marca(p, 620, 1220, 56, TINTA, "direita", 400), "surgir", 3.9),
  ];
  return cena(documento(W, POST, fundoDoBanner({ cor: "#FFF6EC", textura: "nenhuma" }), pecas), 6);
}

/* Cupom de boas-vindas: o cartão sobe, o código é digitado e pulsa, a tesoura balança. */
function cupomAnimado(p: PedidoDoModelo): DocumentoDoBanner {
  const ROSA = "#FF4D8D";
  const TINTA = "#1F1B2E";
  const pecas: Peca[] = [
    ...anima(marca(p, 330, 110, 60, "#FFFFFF", "centro"), "surgir", 0),
    ...anima(
      [
        f("Cartão", "retangulo", { x: 120, y: 300, w: 840, h: 640 }, "#FFFFFF", { raio: 44, sombra: sombraDe("#7A1236", 30, 60, 0.3) }),
        t("Ganhe", { x: 160, y: 360, w: 760, h: 70 }, { texto: "GANHE", fonte: "montserrat", peso: 800, tamanho: 40, espaco: 0.2, cor: ROSA, alinhamento: "centro" }),
        t("Desconto", { x: 160, y: 415, w: 760, h: 270 }, { texto: "10% OFF", fonte: "anton", peso: 400, tamanho: 220, cor: TINTA, alinhamento: "centro" }),
        t("Na primeira", { x: 160, y: 680, w: 760, h: 70 }, { texto: "na sua primeira compra", fonte: "manrope", peso: 700, tamanho: 40, cor: "#5B5570", alinhamento: "centro" }),
        f("Picote", "retangulo", { x: 170, y: 780, w: 740, h: 3 }, comAlfa(TINTA, 0.18)),
      ],
      "subir",
      0.3,
      { duracao: 0.8 },
    ),
    ...anima(t("Código", { x: 300, y: 820, w: 480, h: 96 }, { texto: "BEMVINDO10", fonte: "space-grotesk", peso: 700, tamanho: 48, espaco: 0.1, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor: TINTA } }), "maquina", 1.2, { duracao: 0.9, ...pulsar(1.5) }),
    ...anima(fig("Tesoura", "tesoura", 830, 230, 170, 20), "pop", 1, { enfase: "balancar", ritmo: 1.2 }),
    ...anima(t("Use", { x: 120, y: 1020, w: 840, h: 80 }, { texto: "Use no site ou no WhatsApp", fonte: "manrope", peso: 700, tamanho: 42, cor: "#FFFFFF", alinhamento: "centro" }), "surgir", 2),
    ...anima(contato(350, 1150, "#FFFFFF", 36), "subir", 2.3),
  ];
  return cena(documento(W, POST, fundoDoBanner({ cor: ROSA, cor2: "#FF8A3D", angulo: 160, textura: "nenhuma" }), pecas), 5);
}

/* Chegou novidade: a foto é revelada de baixo para cima, o selo chega girando e pulsa, o título sobe. */
function novidadeAnimada(p: PedidoDoModelo): DocumentoDoBanner {
  const LIMA = "#C8FF3D";
  const pecas: Peca[] = [
    ...anima(foto("Produto", foto$("caneca-roxo"), { x: 80, y: 80, w: 920, h: 820 }, { raio: 48, enquadre: { zoom: 1.08, x: 50, y: 50 } }), "revelar", 0.2, { direcao: "cima", duracao: 0.9 }),
    ...anima([f("Selo", "estrela", { x: 770, y: 30, w: 270, h: 270 }, LIMA, { pontas: 12, profundidade: 0.22 }), t("Novo", { x: 790, y: 112, w: 230, h: 105 }, { texto: "NOVO", fonte: "anton", peso: 400, tamanho: 70, cor: "#0F172A", alinhamento: "centro" })], "girar", 1, pulsar(1.4)),
    ...anima(t("Título", { x: 70, y: 930, w: 940, h: 190 }, { texto: "Chegou novidade", fonte: "anton", peso: 400, tamanho: 130, cor: "#FFFFFF" }), "subir", 1.2),
    ...anima(t("Detalhe", { x: 74, y: 1110, w: 900, h: 70 }, { texto: "Caneca mágica roxa · muda de cor no café", fonte: "manrope", peso: 600, tamanho: 38, cor: "#CBD5E1" }), "surgir", 1.5),
    ...anima(contato(74, 1240, "#FFFFFF", 34), "subir", 1.9),
    ...anima(marca(p, 610, 1232, 54, "#FFFFFF", "direita", 400), "surgir", 2.1),
  ];
  return cena(documento(W, POST, fundoDoBanner({ cor: "#0F172A", textura: "nenhuma" }), pecas), 5);
}

/* Frete grátis: o caminhão entra pelo lado e treme no motor, as palavras pulam, a condição sobe. */
function freteGratisAnimado(p: PedidoDoModelo): DocumentoDoBanner {
  const pecas: Peca[] = [
    tex("Listras", "listras", { x: 0, y: 0, w: W, h: POST }, "#FFFFFF", { opacidade: 0.06, quantidade: 26, giro: -30 }),
    ...anima(marca(p, 60, 80, 60, "#FFFFFF"), "surgir", 0),
    ...anima(ic("Caminhão", "caminhao", 290, 220, 500, "#FFFFFF", { espessura: 1.6 }), "deslizar", 0.2, { direcao: "direita", duracao: 0.9, enfase: "tremer", ritmo: 1 }),
    ...anima(t("Frete", { x: 60, y: 640, w: 960, h: 270 }, { texto: "FRETE", fonte: "anton", peso: 400, tamanho: 230, cor: "#FFFFFF", alinhamento: "centro" }), "pop", 0.9),
    ...anima(t("Grátis", { x: 60, y: 920, w: 960, h: 270 }, { texto: "GRÁTIS", fonte: "anton", peso: 400, tamanho: 230, cor: "#FDE047", alinhamento: "centro" }), "pop", 1.05),
    ...anima(t("Condição", { x: 260, y: 1215, w: 560, h: 96 }, { texto: "acima de R$ 199", fonte: "montserrat", peso: 800, tamanho: 44, cor: "#064E3B", alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF" } }), "subir", 1.5, pulsar(1.6)),
  ];
  return cena(documento(W, POST, fundoDoBanner({ cor: "#10B981", cor2: "#047857", angulo: 160, textura: "nenhuma" }), pecas), 5);
}

/* Sorteio: confetes pulam e flutuam, o presente quica, o SORTEIO bate e as regras são escritas. */
function sorteioAnimado(p: PedidoDoModelo): DocumentoDoBanner {
  const pecas: Peca[] = [
    ...[
      ["confete", 60, 90, 170, -14],
      ["balao", 860, 120, 170, 10],
      ["estrelinha", 900, 560, 120, 0],
      ["fogos", 40, 600, 140, 0],
    ].flatMap(([chave, x, y, lado, rot], i) => anima(fig(`Festa ${i + 1}`, chave as string, x as number, y as number, lado as number, rot as number), "pop", 0.1 + i * 0.14, flutuar(2 + i * 0.4))),
    ...anima(fig("Presente", "presente", 370, 200, 340), "quicar", 0.4, { duracao: 1, ...flutuar(2.4) }),
    ...anima(t("Sorteio", { x: 60, y: 580, w: 960, h: 250 }, { texto: "SORTEIO", fonte: "anton", peso: 400, tamanho: 210, cor: "#FFFFFF", alinhamento: "centro" }), "carimbo", 1.1, { duracao: 0.45 }),
    ...anima(t("Prêmio", { x: 90, y: 820, w: 900, h: 80 }, { texto: "Valendo um kit personalizado", fonte: "manrope", peso: 700, tamanho: 44, cor: "#FDE7F3", alinhamento: "centro" }), "surgir", 1.5),
    ...anima(t("Regras", { x: 250, y: 940, w: 620, h: 250 }, { texto: "1. Siga o perfil\n2. Curta este post\n3. Marque 2 amigos", fonte: "montserrat", peso: 700, tamanho: 46, linha: 1.4, cor: "#FFFFFF" }), "maquina", 1.9, { duracao: 1.8 }),
    ...anima(marca(p, 330, 1230, 56, "#FFFFFF", "centro"), "surgir", 3.6),
  ];
  return cena(documento(W, POST, fundoDoBanner({ cor: "#6D28D9", cor2: "#DB2777", angulo: 150, textura: "nenhuma" }), pecas), 6);
}

/* Antes e depois em duas cenas: a peça lisa, a cortina descobre a estampada. */
function antesEDepoisAnimado(p: PedidoDoModelo): DocumentoDoBanner {
  const TINTA = "#141414";
  const rotulo = (texto: string, cor: string) => t("Rótulo", { x: 60, y: 70, w: 360, h: 90 }, { texto, fonte: "montserrat", peso: 800, tamanho: 40, espaco: 0.16, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor } });
  const antes = cena(
    documento(W, POST, fundoDoBanner({ cor: "#F4F4F5", textura: "nenhuma" }), [
      ...anima(rotulo("ANTES", "#71717A"), "pop", 0.2),
      ...anima(foto("Antes", foto$("camiseta-branca-recorte"), { x: 140, y: 200, w: 800, h: 900 }, { ajuste: "conter", sombra: sombraDe("#000000", 24, 40, 0.18) }), "surgir", 0.3),
      ...anima(t("Pergunta", { x: 60, y: 1150, w: 960, h: 120 }, { texto: "Uma camiseta lisa…", fonte: "dm-serif-display", peso: 400, tamanho: 80, cor: TINTA, alinhamento: "centro" }), "maquina", 0.7, { duracao: 0.9 }),
    ]),
    2.6,
  );
  const depois = cena(
    documento(W, POST, fundoDoBanner({ cor: "#141414", textura: "nenhuma" }), [
      ...anima(rotulo("DEPOIS", "#E11D48"), "pop", 0.5),
      foto("Depois", foto$("estampa-preta"), { x: 0, y: 0, w: W, h: 1100 }, { enquadre: { zoom: 1.05, x: 50, y: 50 } }),
      f("Véu", "retangulo", { x: 0, y: 700, w: W, h: 650 }, linear("#141414", "#141414", 180, 0, 1)),
      ...anima(t("Resposta", { x: 60, y: 1100, w: 960, h: 150 }, { texto: "…com a sua estampa", html: html(`…com a ${trecho("sua estampa", { cor: "#FFD400" })}`), fonte: "dm-serif-display", peso: 400, tamanho: 86, cor: "#FFFFFF", alinhamento: "centro" }), "subir", 0.8),
      ...anima(marca(p, 330, 1250, 54, "#FFFFFF", "centro"), "surgir", 1.2),
    ]),
    3.4,
    "aproximar",
    { tipo: "cortina", duracao: 0.8 },
  );
  void nada;
  return documentoDasPaginas([antes, depois]);
}

export const MODELOS_ANIMADOS: ModeloDoEditor[] = [
  { chave: "animado-black-friday", nome: "Contagem Black Friday", descricao: "BLACK e FRIDAY entram de lados opostos, o selo bate e pulsa", montar: contagemBlackFriday, feitoPara: "story", animado: true },
  { chave: "animado-lancamento", nome: "Lançamento em 3 cenas", descricao: "Vem aí, o produto e o já disponível, com transições", montar: lancamentoEmTresCenas, feitoPara: "story", paginas: 3, animado: true },
  { chave: "animado-relampago", nome: "Oferta relâmpago animada", descricao: "Raios girando, raio que quica e o 50% que treme", montar: ofertaRelampagoAnimada, feitoPara: "story", animado: true },
  { chave: "animado-bastidores", nome: "Bastidores em movimento", descricao: "Foto que aproxima, play pulsando e título revelado", montar: bastidoresEmMovimento, feitoPara: "story", ramo: "sublimacao", animado: true },
  { chave: "animado-dia-das-maes", nome: "Dia das Mães animado", descricao: "Foto que aproxima e corações flutuando", montar: diaDasMaesAnimado, feitoPara: "story", ramo: "personalizados", animado: true },
  { chave: "animado-depoimento", nome: "Depoimento animado", descricao: "Estrelas acendendo e o texto sendo escrito", montar: depoimentoAnimado, feitoPara: "post", animado: true },
  { chave: "animado-cupom", nome: "Cupom animado", descricao: "Cartão que sobe e código digitado", montar: cupomAnimado, feitoPara: "post", animado: true },
  { chave: "animado-novidade", nome: "Chegou novidade", descricao: "Foto revelada e selo girando", montar: novidadeAnimada, feitoPara: "post", animado: true },
  { chave: "animado-frete", nome: "Frete grátis animado", descricao: "Caminhão que entra e palavras que pulam", montar: freteGratisAnimado, feitoPara: "post", animado: true },
  { chave: "animado-sorteio", nome: "Sorteio animado", descricao: "Confetes, presente quicando e regras escritas", montar: sorteioAnimado, feitoPara: "post", animado: true },
  { chave: "animado-antes-depois", nome: "Antes e depois animado", descricao: "Duas cenas: a cortina descobre a estampa", montar: antesEDepoisAnimado, feitoPara: "post", paginas: 2, animado: true },
];
