/*
 * Banners da loja (1920 × 540, o carrossel do topo) no que está em alta em
 * out/2026: letra gigante que vaza da borda, grade em blocos (bento), serifa
 * editorial, cortes assimétricos, modo escuro com neon, neobrutalismo,
 * letreiro em faixa, foto em duas cores (duotone), Y2K cromado e as datas do
 * varejo. Cada um com paleta, letra e elementos próprios; o título fica
 * grande para ler no celular (o banner aparece inteiro, encolhido).
 *
 * Fotos e recortes do depósito da Ktalogu (Unsplash e Pexels, uso comercial
 * livre; recortes com o isnet), figurinhas Fluent Emoji (MIT) e ícones Lucide
 * (ISC). Fora de 1920 × 540 a composição encaixa inteira (`encaixar`).
 */
import { documentoDasPaginas, fonteDaChave, htmlDoTextoLimpo, novoId, paginasDoDocumento, solida, type DocumentoDoBanner, type Peca, type PecaDeForma, type PecaDeIcone, type PecaDeImagem, type PecaDeTexto, type PecaDeTextura, type Pintura } from "./documento";
import { ICONES_EXTRAS } from "./icones-extras";
import { documento, fundoDoBanner, imagem, texto, type CamposDoTexto, type PedidoDoModelo } from "./modelos-base";
import { encaixar } from "./modelos-colecao";
import { DEPOSITO_DAS_FIGURINHAS } from "./pecas-novas";
import { cartaoRecortado, poligonoRedondo, circuloDeNos, silhueta } from "./silhuetas";

const DEPOSITO = "https://ptpstwltddugnnlewvbw.supabase.co/storage/v1/object/public/products/editor-modelos";
const ramo$ = (nome: string) => `${DEPOSITO}/ramos/${nome}.webp`;
const caneca$ = (nome: string) => `${DEPOSITO}/canecas/${nome}.webp`;
const W = 1920;
const H = 540;

/* ------------------------------------------------------------ peças curtas */

type Lugar = { x: number; y: number; w: number; h: number; rot?: number };

function t(nome: string, l: Lugar, campos: CamposDoTexto): PecaDeTexto {
  return texto({ nome, ...l, rot: l.rot ?? 0, vertical: "meio", alinhamento: "esquerda", ...campos });
}

function f(nome: string, forma: PecaDeForma["forma"], l: Lugar, pintura: Pintura | string, extra: Partial<PecaDeForma> = {}): PecaDeForma {
  return { id: novoId("f"), tipo: "forma", nome, ...l, rot: l.rot ?? 0, opacidade: 1, forma, pintura: typeof pintura === "string" ? solida(pintura) : pintura, raio: 0, borda: null, sombra: null, pontas: 5, profundidade: 0.55, ...extra };
}

function foto(nome: string, src: string, l: Lugar, extra: Partial<PecaDeImagem> = {}): PecaDeImagem {
  return { ...imagem({ nome, src, ...l, rot: l.rot ?? 0, sombra: false, ajuste: "cobrir" }), ...extra };
}

/* O recorte sem fundo (produto, bicho), com a sombra de chão. */
function recorte(nome: string, src: string, l: Lugar, extra: Partial<PecaDeImagem> = {}): PecaDeImagem {
  return foto(nome, src, l, { ajuste: "conter", sombra: { cor: "#000000", x: 0, y: 24, desfoque: 40, opacidade: 0.35 }, ...extra });
}

function ic(nome: string, chave: string, x: number, y: number, lado: number, cor: string, extra: Partial<PecaDeIcone> = {}): PecaDeIcone {
  const desenho = ICONES_EXTRAS[chave];
  return { id: novoId("ic"), tipo: "icone", nome, x, y, w: lado, h: lado, rot: 0, opacidade: 1, icone: desenho ? `lucide-${chave}` : chave, ...(desenho ? { desenho } : {}), pintura: solida(cor), espessura: 2, preenchido: false, sombra: null, ...extra };
}

function fig(nome: string, chave: string, x: number, y: number, lado: number, rot = 0, extra: Partial<PecaDeImagem> = {}): PecaDeImagem {
  return foto(nome, `${DEPOSITO_DAS_FIGURINHAS}/${chave}.webp`, { x, y, w: lado, h: lado, rot }, { ajuste: "conter", ...extra });
}

function tex(nome: string, estilo: PecaDeTextura["estilo"], l: Lugar, cor: string, extra: Partial<PecaDeTextura> = {}): PecaDeTextura {
  return { id: novoId("tex"), tipo: "textura", nome, ...l, rot: l.rot ?? 0, opacidade: 0.1, bloqueada: true, estilo, cor, quantidade: 22, tamanho: 0, centroX: 50, centroY: 50, giro: 0, ...extra };
}

const linear = (cor: string, cor2: string, angulo: number, extra: Partial<Pintura> = {}): Pintura => ({ tipo: "linear", cor, cor2, angulo, ...extra });
const radial = (cor: string, cor2: string, alfa?: number, alfa2?: number): Pintura => ({ tipo: "radial", cor, cor2, angulo: 0, ...(alfa !== undefined ? { alfa } : {}), ...(alfa2 !== undefined ? { alfa2 } : {}) });
const nada: Pintura = { tipo: "nenhuma", cor: "#FFFFFF", cor2: "#FFFFFF", angulo: 0 };
const sombraDe = (cor: string, x: number, y: number, desfoque: number, opacidade: number) => ({ cor, x, y, desfoque, opacidade });

function trecho(conteudo: string, o: { cor?: string; fonte?: string; italico?: boolean; vazado?: { cor: string; largura: number } }) {
  const estilo = [
    o.cor ? `color:${o.cor}` : "",
    o.fonte ? `font-family:'${fonteDaChave(o.fonte).familia}'` : "",
    o.italico ? "font-style:italic" : "",
    o.vazado ? `color:transparent;-webkit-text-stroke:${o.vazado.largura}px ${o.vazado.cor}` : "",
  ]
    .filter(Boolean)
    .join(";");
  return `<span style="${estilo}">${conteudo}</span>`;
}
const html = (partes: string) => htmlDoTextoLimpo(partes);

function marca(p: PedidoDoModelo, x: number, y: number, h: number, cor: string, alinhamento: PecaDeTexto["alinhamento"] = "esquerda", larguraMaxima = 320, fonte = "bricolage-grotesque"): Peca {
  if (p.logo) {
    const w = Math.min(larguraMaxima, h * Math.min(6, Math.max(0.6, p.proporcaoDoLogo || 3)));
    const xx = alinhamento === "direita" ? x + larguraMaxima - w : alinhamento === "centro" ? x + (larguraMaxima - w) / 2 : x;
    return foto("Logo", p.logo, { x: xx, y, w, h }, { papel: "logo", ajuste: "conter" });
  }
  return t("Marca", { x, y, w: larguraMaxima, h }, { texto: "SUA MARCA", fonte, peso: 800, tamanho: h * 0.6, cor, espaco: 0.08, alinhamento });
}

/* Botão em pílula (o texto com o fundo). */
function botao(rotulo: string, x: number, y: number, w: number, fundo: string, cor: string, extra: Partial<CamposDoTexto> = {}): PecaDeTexto {
  return t("Botão", { x, y, w, h: 76 }, { texto: rotulo, fonte: "montserrat", peso: 800, tamanho: 28, espaco: 0.06, cor, alinhamento: "centro", fundo: { forma: "pilula", cor: fundo }, ...extra });
}

const banner = (fundo: Parameters<typeof fundoDoBanner>[0], pecas: Peca[]) => documento(W, H, fundoDoBanner(fundo), pecas);

/* ============================================ 1. LETRA GIGANTE QUE VAZA */

function letraGigante(p: PedidoDoModelo): DocumentoDoBanner {
  const TOMATE = "#FF3B1F";
  const CREME = "#FFF1E0";
  return banner({ cor: TOMATE, textura: "grao", corDaTextura: "#000000" }, [
    t("Palavra gigante", { x: -40, y: -70, w: 2000, h: 520 }, { texto: "CANECAS", fonte: "anton", peso: 400, tamanho: 560, espaco: -0.01, cor: CREME, alinhamento: "centro", linha: 0.9 }),
    recorte("Caneca", ramo$("caneca-branca-recorte"), { x: 700, y: 40, w: 520, h: 520, rot: -8 }, { sombra: sombraDe("#5A0E00", 0, 30, 50, 0.5) }),
    t("Chamada", { x: 90, y: 400, w: 720, h: 60 }, { texto: "com a sua arte, do jeito que você imaginou", fonte: "space-grotesk", peso: 700, tamanho: 28, cor: "#2B0700" }),
    t("Preço", { x: 1290, y: 400, w: 300, h: 90 }, { texto: "a partir de R$ 29,90", fonte: "space-grotesk", peso: 700, tamanho: 30, linha: 1.1, cor: "#2B0700", alinhamento: "direita" }),
    botao("PEÇA A SUA", 1620, 405, 260, "#2B0700", CREME, { tamanho: 24 }),
    marca(p, 90, 466, 40, "#2B0700"),
  ]);
}

/* ===================================================== 2. GRADE EM BLOCOS */

function bento(p: PedidoDoModelo): DocumentoDoBanner {
  const TINTA = "#0F172A";
  const LIMA = "#D4F54A";
  const AZUL = "#3B5BFF";
  const bloco = (nome: string, l: Lugar, cor: Pintura | string, extra: Partial<PecaDeForma> = {}) => f(nome, "retangulo", l, cor, { raio: 34, ...extra });
  const grande = bloco("Bloco da foto", { x: 40, y: 40, w: 900, h: 460 }, "#000000");
  return banner({ cor: "#EEF0F7", textura: "nenhuma" }, [
    grande,
    foto("Foto", ramo$("camiseta-arara"), { x: 40, y: 40, w: 900, h: 460 }, { dentroDe: grande.id, filtros: { brilho: 85, contraste: 105, saturacao: 100, desfoque: 0 } }),
    f("Escurecer", "retangulo", { x: 40, y: 40, w: 900, h: 460 }, linear("#000000", "#000000", 90, { alfa: 0.7, alfa2: 0 }), { raio: 34 }),
    t("Título", { x: 90, y: 116, w: 800, h: 220 }, { texto: "Uniformes que\nvestem a marca", fonte: "bricolage-grotesque", peso: 800, tamanho: 84, linha: 0.98, cor: "#FFFFFF", vertical: "topo" }),
    botao("MONTE O SEU", 90, 390, 300, LIMA, TINTA),
    bloco("Bloco do desconto", { x: 970, y: 40, w: 440, h: 220 }, AZUL),
    t("Desconto", { x: 1000, y: 50, w: 400, h: 140 }, { texto: "-30%", fonte: "anton", peso: 400, tamanho: 150, cor: "#FFFFFF" }),
    t("Desconto: detalhe", { x: 1004, y: 186, w: 390, h: 50 }, { texto: "acima de 20 peças", fonte: "space-grotesk", peso: 700, tamanho: 30, cor: "#DDE3FF" }),
    bloco("Bloco do frete", { x: 970, y: 280, w: 440, h: 220 }, LIMA),
    ic("Caminhão", "caminhao-lucide", 1004, 310, 90, TINTA, { espessura: 2 }),
    t("Frete", { x: 1004, y: 400, w: 390, h: 80 }, { texto: "Frete grátis\nacima de R$ 299", fonte: "space-grotesk", peso: 700, tamanho: 30, linha: 1.1, cor: TINTA }),
    bloco("Bloco do produto", { x: 1440, y: 40, w: 440, h: 460 }, TINTA),
    recorte("Garrafa", ramo$("garrafa-branca-recorte"), { x: 1500, y: 60, w: 320, h: 320, rot: 8 }, { sombra: sombraDe("#000000", 0, 20, 30, 0.6) }),
    t("Produto", { x: 1480, y: 380, w: 380, h: 60 }, { texto: "Garrafa térmica", fonte: "space-grotesk", peso: 700, tamanho: 34, cor: "#FFFFFF" }),
    t("Produto: preço", { x: 1480, y: 432, w: 380, h: 50 }, { texto: "com o seu logo · R$ 49,90", fonte: "space-grotesk", peso: 500, tamanho: 26, cor: "#94A3B8" }),
    marca(p, 90, 52, 40, "#FFFFFF", "esquerda", 240),
  ]);
}

/* ===================================================== 3. EDITORIAL SERIFA */

function editorialSerifa(p: PedidoDoModelo): DocumentoDoBanner {
  const PAPEL = "#F3EEE6";
  const TINTA = "#1A1714";
  const TERRA = "#B5512F";
  const arco = f("Arco", "retangulo", { x: 1240, y: 40, w: 460, h: 560 }, "#D9CBB6", { raio: 230 });
  return banner({ cor: PAPEL, textura: "grao", corDaTextura: "#000000" }, [
    t("Edição", { x: 120, y: 70, w: 700, h: 40 }, { texto: "COLEÇÃO OUTONO · ECOBAGS", fonte: "inter-tight", peso: 600, tamanho: 22, espaco: 0.3, cor: "#7A7166" }),
    t("Título", { x: 110, y: 120, w: 1060, h: 250 }, { texto: "Feitas para carregar\no seu dia", html: html(`Feitas para carregar<br>${trecho("o seu dia", { italico: true, cor: TERRA })}`), fonte: "instrument-serif", peso: 400, tamanho: 116, linha: 1, cor: TINTA }),
    f("Fio", "retangulo", { x: 120, y: 400, w: 90, h: 3 }, TINTA),
    t("Texto", { x: 240, y: 380, w: 620, h: 50 }, { texto: "Algodão cru, estampa no tom da sua marca.", fonte: "newsreader", peso: 400, tamanho: 30, italico: true, cor: "#4A433B" }),
    t("Link", { x: 900, y: 380, w: 300, h: 50 }, { texto: "Ver a coleção →", fonte: "inter-tight", peso: 700, tamanho: 26, cor: TERRA }),
    arco,
    foto("Foto", ramo$("ecobag-pessoa"), { x: 1240, y: 40, w: 460, h: 560 }, { dentroDe: arco.id }),
    t("Número", { x: 1730, y: 70, w: 150, h: 60 }, { texto: "N.º 04", fonte: "instrument-serif", peso: 400, italico: true, tamanho: 40, cor: TERRA, alinhamento: "direita" }),
    marca(p, 120, 462, 40, TINTA, "esquerda", 320, "bodoni-moda"),
  ]);
}

/* ===================================================== 4. CYBER NEON */

function cyberNeon(p: PedidoDoModelo): DocumentoDoBanner {
  const CIANO = "#22D3EE";
  const ROSA = "#FF2BD6";
  return banner({ cor: "#07051A", cor2: "#140A3A", angulo: 180, textura: "nenhuma" }, [
    tex("Grade", "xadrez", { x: 0, y: 0, w: W, h: H }, CIANO, { opacidade: 0.07, tamanho: 64 }),
    f("Luz rosa", "circulo", { x: 1180, y: -260, w: 900, h: 900 }, radial(ROSA, "#07051A", 0.45, 0)),
    f("Luz ciano", "circulo", { x: -300, y: 120, w: 900, h: 900 }, radial(CIANO, "#07051A", 0.3, 0)),
    t("Cyber", { x: 100, y: 60, w: 1100, h: 230 }, { texto: "CYBER\nMONDAY", fonte: "unbounded", peso: 800, tamanho: 118, cor: "#FFFFFF", efeito: { tipo: "neon", cor: ROSA, forca: 0.75 } }),
    t("Oferta", { x: 104, y: 290, w: 1100, h: 90 }, { texto: "Tudo de impressão com até 45% off", fonte: "space-grotesk", peso: 700, tamanho: 48, cor: CIANO }),
    botao("ENTRAR NA OFERTA", 104, 410, 400, CIANO, "#07051A"),
    t("Só hoje", { x: 540, y: 410, w: 400, h: 76 }, { texto: "só hoje · até 23h59", fonte: "space-grotesk", peso: 700, tamanho: 28, cor: "#C4B5FD" }),
    f("Moldura", "retangulo", { x: 1330, y: 90, w: 460, h: 360, rot: 4 }, nada, { borda: { cor: ROSA, largura: 6 }, raio: 26, efeitos: [{ tipo: "brilho", cor: ROSA, x: 0, y: 0, desfoque: 30, opacidade: 0.9 }] }),
    t("Percentual", { x: 1330, y: 120, w: 460, h: 300, rot: 4 }, { texto: "45%", fonte: "unbounded", peso: 800, tamanho: 136, cor: "#FFFFFF", alinhamento: "centro", efeito: { tipo: "neon", cor: CIANO, forca: 0.7 } }),
    marca(p, 1600, 470, 44, "#FFFFFF", "direita", 280),
  ]);
}

/* ===================================================== 5. NEOBRUTALISMO */

function neobrutal(p: PedidoDoModelo): DocumentoDoBanner {
  const PRETO = "#111111";
  const LILAS = "#C4B5FD";
  const AMARELO = "#FFD23F";
  const ROSA = "#FF7AB6";
  const duro = sombraDe(PRETO, 12, 12, 0, 1);
  const borda = { cor: PRETO, largura: 6 };
  return banner({ cor: LILAS, textura: "nenhuma" }, [
    tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: H }, PRETO, { opacidade: 0.1, tamanho: 30 }),
    t("Título", { x: 90, y: 60, w: 1000, h: 260 }, { texto: "CHAVEIROS COM\nA SUA CARA", fonte: "archivo-black", peso: 400, tamanho: 104, linha: 1, cor: PRETO }),
    f("Cartão", "retangulo", { x: 90, y: 340, w: 640, h: 130 }, "#FFFFFF", { raio: 22, borda, sombra: duro }),
    t("Cartão: texto", { x: 120, y: 350, w: 580, h: 110 }, { texto: "Acrílico, MDF ou couro. A partir de 10 unidades.", fonte: "space-grotesk", peso: 700, tamanho: 30, linha: 1.2, cor: PRETO }),
    f("Botão", "retangulo", { x: 770, y: 360, w: 330, h: 96 }, AMARELO, { raio: 48, borda, sombra: duro }),
    t("Botão: texto", { x: 770, y: 360, w: 330, h: 96 }, { texto: "QUERO O MEU →", fonte: "archivo-black", peso: 400, tamanho: 30, cor: PRETO, alinhamento: "centro" }),
    f("Círculo", "circulo", { x: 1250, y: 40, w: 470, h: 470 }, ROSA, { borda, sombra: duro }),
    recorte("Chaveiro", ramo$("chaveiro-coracao-recorte"), { x: 1290, y: 60, w: 400, h: 400, rot: -10 }, { sombra: sombraDe(PRETO, 10, 10, 0, 0.9) }),
    f("Selo", "circulo", { x: 1660, y: 320, w: 190, h: 190, rot: 12 }, AMARELO, { borda, sombra: duro }),
    t("Selo: texto", { x: 1660, y: 320, w: 190, h: 190, rot: -12 }, { texto: "NOVO", fonte: "archivo-black", peso: 400, tamanho: 46, cor: PRETO, alinhamento: "centro" }),
    marca(p, 1600, 30, 44, PRETO, "direita", 280, "archivo-black"),
  ]);
}

/* ===================================================== 6. Y2K CROMADO */

function y2kCromado(p: PedidoDoModelo): DocumentoDoBanner {
  const cromo = linear("#FFFFFF", "#7C83FF", 180, { paradas: [{ pos: 0.45, cor: "#C7D2FE" }, { pos: 0.55, cor: "#4F46E5" }, { pos: 0.75, cor: "#E0E7FF" }] });
  return banner({ cor: "#FF8AD8", cor2: "#7DD3FC", angulo: 120, textura: "nenhuma" }, [
    f("Bolha 1", "circulo", { x: -120, y: -200, w: 640, h: 640 }, radial("#FFFFFF", "#FF8AD8", 0.6, 0)),
    f("Bolha 2", "circulo", { x: 1500, y: 160, w: 600, h: 600 }, radial("#FFFFFF", "#7DD3FC", 0.55, 0)),
    t("Título", { x: 90, y: 60, w: 1100, h: 270 }, { texto: "VOLTA ÀS\nAULAS", fonte: "rubik-bubbles", peso: 400, tamanho: 136, linha: 0.95, cor: "#FFFFFF", pintura: cromo, contorno: { cor: "#312E81", largura: 4 } }),
    t("Chamada", { x: 96, y: 330, w: 900, h: 70 }, { texto: "cadernos, etiquetas e agendas com o nome", fonte: "space-grotesk", peso: 700, tamanho: 38, cor: "#312E81" }),
    botao("MONTAR O KIT", 96, 420, 320, "#312E81", "#FFFFFF"),
    foto("Cadernos", ramo$("cadernos"), { x: 1230, y: 60, w: 520, h: 420, rot: 5 }, { raio: 40, borda: { cor: "#FFFFFF", largura: 10 }, sombra: sombraDe("#312E81", 0, 24, 40, 0.45) }),
    ...[
      [1180, 40, 90],
      [1760, 70, 70],
      [1140, 420, 60],
      [1010, 300, 50],
    ].map(([x, y, l], i) => ic(`Brilho ${i + 1}`, "estrela-4", x, y, l, "#FFFFFF", { preenchido: true, espessura: 0.5, pintura: cromo })),
    fig("Lápis", "lapis", 1660, 380, 170, -20),
    marca(p, 1600, 20, 44, "#312E81", "direita", 280),
  ]);
}

/* ===================================================== 7. LETREIRO EM FAIXA */

function letreiro(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFE14D";
  const PRETO = "#101010";
  const faixa = (y: number, rot: number, cor: string, letra: string, texto_: string) => [
    f("Faixa", "retangulo", { x: -200, y, w: 2320, h: 86, rot }, cor),
    t("Letreiro", { x: -200, y, w: 2320, h: 86, rot }, { texto: texto_, fonte: "anton", peso: 400, tamanho: 50, espaco: 0.06, cor: letra, alinhamento: "centro" }),
  ];
  const repetir = (frase: string, vezes: number) => Array.from({ length: vezes }, () => frase).join("   •   ");
  return banner({ cor: PRETO, textura: "nenhuma" }, [
    foto("Foto", ramo$("estampa-preta"), { x: 0, y: 0, w: W, h: H }, { opacidade: 0.55, filtros: { brilho: 80, contraste: 110, saturacao: 0, desfoque: 0 } }),
    ...faixa(40, -3, AMARELO, PRETO, repetir("FRETE GRÁTIS", 6)),
    ...faixa(410, 2, "#FFFFFF", PRETO, repetir("ATÉ 6X SEM JUROS", 4)),
    t("Título", { x: 160, y: 150, w: 1600, h: 240 }, { texto: "ESTAMPA QUE NÃO SAI NA LAVAGEM", html: html(`ESTAMPA QUE ${trecho("NÃO SAI", { cor: AMARELO })} NA LAVAGEM`), fonte: "anton", peso: 400, tamanho: 112, linha: 1, cor: "#FFFFFF", alinhamento: "centro" }),
    marca(p, 80, 488, 38, "#FFFFFF", "esquerda", 240),
  ]);
}

/* ===================================================== 8. DUOTONE */

function duotone(p: PedidoDoModelo): DocumentoDoBanner {
  return banner({ cor: "#2B0B4F", textura: "nenhuma" }, [
    foto("Foto em duas cores", ramo$("serigrafia"), { x: 760, y: 0, w: 1160, h: H }, { duotone: { escuro: "#2B0B4F", claro: "#FF5FA2" }, desvanecer: { lado: "esquerda", tamanho: 0.45 } }),
    t("Etiqueta", { x: 110, y: 80, w: 600, h: 50 }, { texto: "SERIGRAFIA E SUBLIMAÇÃO", fonte: "space-grotesk", peso: 700, tamanho: 26, espaco: 0.3, cor: "#FF5FA2" }),
    t("Título", { x: 104, y: 140, w: 980, h: 230 }, { texto: "Estampas que\nduram anos", html: html(`Estampas que<br>${trecho("duram anos", { vazado: { cor: "#FFFFFF", largura: 3 } })}`), fonte: "syne", peso: 800, tamanho: 80, linha: 1.02, cor: "#FFFFFF", vertical: "topo" }),
    t("Texto", { x: 110, y: 380, w: 860, h: 56 }, { texto: "Tinta de qualidade, cor firme, lote a partir de 12 peças.", fonte: "manrope", peso: 600, tamanho: 28, cor: "#E9D5FF" }),
    botao("FAZER ORÇAMENTO", 110, 450, 360, "#FF5FA2", "#2B0B4F", { tamanho: 24 }),
    marca(p, 1540, 470, 40, "#FFFFFF", "direita", 340, "syne"),
  ]);
}

/* ===================================================== 9. CORTE NA DIAGONAL */

function corteDiagonal(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFC700";
  const PRETO = "#141414";
  const lado = f("Lado da foto", "paralelogramo", { x: 900, y: 0, w: 1100, h: H }, PRETO);
  const etiqueta = silhueta([poligonoRedondo([{ x: 70, y: 0 }, { x: 420, y: 0 }, { x: 420, y: 160 }, { x: 70, y: 160 }, { x: 0, y: 80 }], 16), circuloDeNos(56, 80, 14)], 1260, 330, solida("#FF3D3D"), { nome: "Etiqueta do preço", rot: -6, efeitos: [{ tipo: "sombra", cor: "#000000", x: 0, y: 14, desfoque: 24, opacidade: 0.35 }] });
  return banner({ cor: AMARELO, textura: "nenhuma" }, [
    lado,
    foto("Foto", ramo$("garrafas-cores"), { x: 900, y: 0, w: 1100, h: H }, { dentroDe: lado.id }),
    t("Título", { x: 100, y: 70, w: 860, h: 260 }, { texto: "Garrafas para\no time todo", fonte: "kanit", peso: 900, tamanho: 104, linha: 0.98, italico: true, cor: PRETO }),
    t("Texto", { x: 104, y: 340, w: 760, h: 60 }, { texto: "Inox, 500 ml, gravação a laser do logo", fonte: "kanit", peso: 600, tamanho: 34, cor: "#3A2E00" }),
    botao("PEDIR KIT DE 10", 104, 420, 360, PRETO, AMARELO),
    etiqueta,
    t("Preço: quantos", { x: 1330, y: 344, w: 350, h: 44, rot: -6 }, { texto: "10 POR", fonte: "kanit", peso: 800, tamanho: 30, espaco: 0.1, cor: "#FFE1E1", alinhamento: "centro" }),
    t("Preço", { x: 1330, y: 384, w: 350, h: 90, rot: -6 }, { texto: "R$ 389", fonte: "kanit", peso: 900, tamanho: 76, cor: "#FFFFFF", alinhamento: "centro" }),
    marca(p, 100, 20, 44, PRETO),
  ]);
}

/* ===================================================== 10. DIA DAS MÃES */

function diaDasMaes(p: PedidoDoModelo): DocumentoDoBanner {
  const PINK = "#E11D74";
  const CREME = "#FFF3F7";
  const arco = f("Moldura", "retangulo", { x: 1180, y: 40, w: 420, h: 520 }, "#FFFFFF", { raio: 210, borda: { cor: "#FFFFFF", largura: 10 } });
  return banner({ cor: PINK, cor2: "#9D174D", angulo: 120, textura: "nenhuma" }, [
    f("Luz", "circulo", { x: 1000, y: -300, w: 900, h: 900 }, radial("#FF8FC4", PINK, 0.6, 0)),
    t("Data", { x: 110, y: 70, w: 700, h: 50 }, { texto: "DIA DAS MÃES · 10 DE MAIO", fonte: "montserrat", peso: 800, tamanho: 26, espaco: 0.3, cor: "#FFD1E6" }),
    t("Título", { x: 100, y: 110, w: 1000, h: 220 }, { texto: "Presente com a\ncara dela", html: html(`Presente com a<br>${trecho("cara dela", { fonte: "great-vibes", cor: "#FFE4F0" })}`), fonte: "playfair-display", peso: 900, tamanho: 104, linha: 1, cor: CREME }),
    t("Texto", { x: 110, y: 350, w: 960, h: 60 }, { texto: "Canecas, almofadas e quadros com a foto de vocês", fonte: "montserrat", peso: 600, tamanho: 28, cor: "#FFE4F0" }),
    botao("ESCOLHER O PRESENTE", 110, 430, 430, CREME, PINK, { tamanho: 24 }),
    arco,
    foto("Foto", caneca$("mae-filha"), { x: 1180, y: 40, w: 420, h: 520 }, { dentroDe: arco.id }),
    fig("Flor 1", "flor-de-cerejeira", 1110, 330, 160, -14),
    fig("Flor 2", "flor-amarela", 1560, 40, 130, 18),
    fig("Coração", "coracao-com-laco", 1660, 330, 160, 10),
    marca(p, 1640, 30, 44, CREME, "direita", 240),
  ]);
}

/* ===================================================== 11. DIA DOS NAMORADOS */

function namorados(p: PedidoDoModelo): DocumentoDoBanner {
  const VERMELHO = "#D90429";
  const papel = f("Polaroid", "retangulo", { x: 1080, y: 50, w: 360, h: 430, rot: -6 }, "#FFFFFF", { sombra: sombraDe("#4A0010", 0, 18, 30, 0.45) });
  return banner({ cor: VERMELHO, cor2: "#7A0019", angulo: 160, textura: "grao", corDaTextura: "#000000" }, [
    tex("Corações", "pontos", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.06, tamanho: 40 }),
    t("Título", { x: 100, y: 70, w: 900, h: 260 }, { texto: "Amor que se vê\ntodo dia", html: html(`Amor que se vê<br>${trecho("todo dia", { fonte: "pacifico", cor: "#FFC2CF" })}`), fonte: "dm-serif-display", peso: 400, tamanho: 108, linha: 1.02, cor: "#FFFFFF" }),
    t("Texto", { x: 104, y: 340, w: 920, h: 60 }, { texto: "Dia dos Namorados: presente personalizado em 48 h", fonte: "poppins", peso: 600, tamanho: 28, cor: "#FFD6DE" }),
    botao("SURPREENDER", 104, 420, 320, "#FFFFFF", VERMELHO),
    papel,
    foto("Foto do casal", caneca$("casal-rosto"), { x: 1100, y: 70, w: 320, h: 320, rot: -6 }, { dentroDe: papel.id }),
    t("Legenda", { x: 1100, y: 400, w: 320, h: 60, rot: -6 }, { texto: "nós dois", fonte: "caveat", peso: 700, tamanho: 40, cor: "#2B0008", alinhamento: "centro" }),
    recorte("Caneca", ramo$("caneca-coracao-recorte"), { x: 1450, y: 120, w: 380, h: 380, rot: 6 }, { sombra: sombraDe("#3A000B", 0, 26, 40, 0.5) }),
    fig("Coração 1", "coracao-vermelho", 1440, 30, 110, 14),
    fig("Coração 2", "dois-coracoes", 1000, 380, 110, -10),
    marca(p, 1640, 470, 44, "#FFFFFF", "direita", 240),
  ]);
}

/* ===================================================== 12. DIA DOS PAIS */

function diaDosPais(p: PedidoDoModelo): DocumentoDoBanner {
  const MARINHO = "#0B1F3A";
  const LARANJA = "#FF7A1A";
  const foto_ = f("Foto", "retangulo", { x: 1120, y: 0, w: 800, h: H }, MARINHO);
  return banner({ cor: MARINHO, textura: "nenhuma" }, [
    foto_,
    foto("Pai e filho", caneca$("pai-ombros"), { x: 1120, y: 0, w: 800, h: H }, { dentroDe: foto_.id, desvanecer: { lado: "esquerda", tamanho: 0.4 } }),
    t("Título", { x: 100, y: 30, w: 1100, h: 330 }, { texto: "PAI É\nPAI", html: html(`PAI É<br>${trecho("PAI", { cor: LARANJA })}`), fonte: "big-shoulders-display", peso: 900, tamanho: 190, linha: 0.86, cor: "#FFFFFF" }),
    t("Texto", { x: 560, y: 110, w: 560, h: 200 }, { texto: "E merece um presente à altura: caneca, chaveiro ou camiseta com a foto de vocês.", fonte: "manrope", peso: 600, tamanho: 32, linha: 1.35, cor: "#C9D6EA" }),
    botao("PRESENTES PARA O PAI", 100, 410, 440, LARANJA, MARINHO, { tamanho: 24 }),
    t("Prazo", { x: 580, y: 410, w: 500, h: 76 }, { texto: "pedidos até 5 de agosto", fonte: "manrope", peso: 700, tamanho: 28, cor: LARANJA }),
    marca(p, 1640, 470, 44, "#FFFFFF", "direita", 240),
  ]);
}

/* ===================================================== 13. NATAL PREMIUM */

function natalPremium(p: PedidoDoModelo): DocumentoDoBanner {
  const VERDE = "#0E3B2E";
  const OURO = "#D4AF37";
  const ouro = linear("#F7E08A", "#B8860B", 120, { paradas: [{ pos: 0.5, cor: "#E9C25A" }] });
  const janela = f("Moldura", "retangulo", { x: 1160, y: 40, w: 640, h: 460 }, VERDE, { raio: 30, borda: { cor: OURO, largura: 6 } });
  return banner({ cor: VERDE, cor2: "#06231B", angulo: 160, textura: "grao", corDaTextura: "#FFFFFF" }, [
    ...[
      [60, 470, 44],
      [980, 60, 70],
      [1040, 420, 44],
      [600, 470, 36],
    ].map(([x, y, l], i) => ic(`Floco ${i + 1}`, "floco-de-neve", x, y, l, "#FFFFFF", { opacidade: 0.5, espessura: 1.4 })),
    t("Etiqueta", { x: 110, y: 80, w: 700, h: 50 }, { texto: "NATAL 2026", fonte: "cinzel", peso: 800, tamanho: 30, espaco: 0.4, cor: OURO }),
    t("Título", { x: 100, y: 130, w: 1000, h: 230 }, { texto: "Natal com a\nsua cara", html: html(`Natal com a<br>${trecho("sua cara", { italico: true })}`), fonte: "bodoni-moda", peso: 700, tamanho: 104, linha: 1.02, cor: "#FFF8E7", pintura: ouro }),
    t("Texto", { x: 110, y: 370, w: 1000, h: 60 }, { texto: "Kits corporativos e presentes personalizados com embalagem", fonte: "manrope", peso: 600, tamanho: 28, cor: "#CFE3D8" }),
    botao("VER OS PRESENTES", 110, 440, 360, OURO, VERDE, { tamanho: 24 }),
    janela,
    foto("Presente", ramo$("presente-vermelho"), { x: 1160, y: 40, w: 640, h: 460 }, { dentroDe: janela.id }),
    ic("Laço", "laco-presente", 1690, 10, 130, OURO, { preenchido: true, pintura: ouro }),
    marca(p, 1640, 480, 40, "#FFF8E7", "direita", 240, "cinzel"),
  ]);
}

/* ===================================================== 14. PET */

function pets(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFCB2B";
  const MARROM = "#3A2410";
  return banner({ cor: AMARELO, textura: "nenhuma" }, [
    tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.25, tamanho: 36 }),
    f("Círculo 1", "circulo", { x: 1080, y: 40, w: 460, h: 460 }, "#FF7A59"),
    f("Círculo 2", "circulo", { x: 1440, y: 90, w: 400, h: 400 }, "#4ECDC4"),
    recorte("Golden", caneca$("pet-golden-recorte"), { x: 1030, y: 30, w: 520, h: 520 }),
    recorte("Corgi", caneca$("pet-corgi-recorte"), { x: 1420, y: 90, w: 450, h: 450 }),
    t("Título", { x: 100, y: 60, w: 900, h: 250 }, { texto: "Seu pet na\ncaneca", html: html(`Seu pet na<br>${trecho("caneca", { cor: "#FFFFFF" })}`), fonte: "titan-one", peso: 400, tamanho: 116, linha: 1, cor: MARROM, contorno: null }),
    t("Texto", { x: 104, y: 320, w: 820, h: 60 }, { texto: "Mande a foto: a gente recorta e monta a arte", fonte: "fredoka", peso: 700, tamanho: 36, cor: MARROM }),
    botao("ENVIAR A FOTO", 104, 410, 330, MARROM, AMARELO, { fonte: "fredoka", tamanho: 30 }),
    ...[
      [960, 60, 70, -20],
      [880, 380, 56, 15],
    ].map(([x, y, l, r], i) => fig(`Patinha ${i + 1}`, "coracao-laranja", x, y, l, r)),
    marca(p, 1640, 20, 44, MARROM, "direita", 240, "fredoka"),
  ]);
}

/* ===================================================== 15. GRÁFICA CORPORATIVA */

function graficaCorporativa(p: PedidoDoModelo): DocumentoDoBanner {
  const PETROLEO = "#0B3B4A";
  const AQUA = "#2DD4BF";
  const vantagens = ["Couché 300 g com laminação", "Prova digital antes de imprimir", "Entrega em 3 dias úteis"];
  const quadro = f("Moldura", "retangulo", { x: 1100, y: 40, w: 780, h: 460 }, PETROLEO, { raio: 28 });
  return banner({ cor: "#F2F7F8", textura: "nenhuma" }, [
    tex("Grade", "xadrez", { x: 0, y: 0, w: 1060, h: H }, PETROLEO, { opacidade: 0.04, tamanho: 48 }),
    t("Etiqueta", { x: 100, y: 70, w: 700, h: 44 }, { texto: "GRÁFICA RÁPIDA", fonte: "inter-tight", peso: 700, tamanho: 24, espaco: 0.3, cor: "#0E7490" }),
    t("Título", { x: 96, y: 110, w: 980, h: 180 }, { texto: "Cartões de visita\na partir de R$ 59", html: html(`Cartões de visita<br>a partir de ${trecho("R$ 59", { cor: "#0E7490" })}`), fonte: "inter-tight", peso: 800, tamanho: 76, linha: 1.04, cor: PETROLEO }),
    ...vantagens.flatMap((v, i) => [ic(`Check ${i + 1}`, "check-circulo", 100, 316 + i * 52, 36, "#0E7490", { espessura: 2.2 }), t(`Vantagem ${i + 1}`, { x: 150, y: 310 + i * 52, w: 600, h: 48 }, { texto: v, fonte: "inter-tight", peso: 600, tamanho: 28, cor: "#334155" })]),
    botao("ORÇAMENTO NA HORA", 700, 380, 360, PETROLEO, "#FFFFFF", { tamanho: 24, fonte: "inter-tight" }),
    quadro,
    foto("Cartões", ramo$("cartoes-marmore"), { x: 1100, y: 40, w: 780, h: 460 }, { dentroDe: quadro.id }),
    t("Selo", { x: 1680, y: 400, w: 180, h: 76 }, { texto: "500 un.", fonte: "inter-tight", peso: 800, tamanho: 30, cor: PETROLEO, alinhamento: "centro", fundo: { forma: "pilula", cor: AQUA } }),
    marca(p, 700, 60, 44, PETROLEO, "direita", 360, "inter-tight"),
  ]);
}

/* ===================================================== 16. GRANDE FORMATO CMYK */

function grandeFormato(p: PedidoDoModelo): DocumentoDoBanner {
  const cores = ["#00AEEF", "#EC008C", "#FFF200", "#1A1A1A"];
  const quadro = f("Foto", "retangulo", { x: 980, y: 0, w: 940, h: H }, "#111111");
  return banner({ cor: "#111111", textura: "nenhuma" }, [
    quadro,
    foto("Plotter", ramo$("grafica-plotter"), { x: 980, y: 0, w: 940, h: H }, { dentroDe: quadro.id, desvanecer: { lado: "esquerda", tamanho: 0.35 } }),
    ...cores.map((cor, i) => f(`Faixa ${["C", "M", "Y", "K"][i]}`, "retangulo", { x: 100 + i * 70, y: 70, w: 54, h: 54 }, cor, { raio: 27, borda: i === 3 ? { cor: "#FFFFFF", largura: 3 } : null })),
    t("Título", { x: 96, y: 140, w: 1000, h: 230 }, { texto: "Lona, banner e\nadesivo em 24 h", html: html(`Lona, banner e<br>adesivo em ${trecho("24 h", { cor: "#FFF200" })}`), fonte: "bebas-neue", peso: 400, tamanho: 120, linha: 0.95, espaco: 0.02, cor: "#FFFFFF" }),
    t("Texto", { x: 100, y: 380, w: 820, h: 50 }, { texto: "Impressão em alta resolução até 3,2 m de largura", fonte: "manrope", peso: 600, tamanho: 30, cor: "#C7C7C7" }),
    botao("CALCULAR MEU BANNER", 100, 440, 400, "#FFF200", "#111111", { tamanho: 24 }),
    marca(p, 1640, 470, 44, "#FFFFFF", "direita", 240),
  ]);
}

/* ===================================================== 17. BRINDES DE EMPRESA */

function brindes(p: PedidoDoModelo): DocumentoDoBanner {
  const LIMA = "#C6F432";
  const PRETO = "#0D0D0D";
  const bolha = (x: number, y: number, l: number, cor: string) => f("Bolha", "circulo", { x, y, w: l, h: l }, cor);
  return banner({ cor: PRETO, textura: "nenhuma" }, [
    t("Título", { x: 100, y: 70, w: 900, h: 260 }, { texto: "Brindes que\nviram marca", html: html(`Brindes que<br>${trecho("viram marca", { cor: LIMA })}`), fonte: "unbounded", peso: 800, tamanho: 96, linha: 1.02, cor: "#FFFFFF" }),
    t("Texto", { x: 104, y: 340, w: 780, h: 60 }, { texto: "Ecobags, garrafas e cadernos com o seu logo", fonte: "manrope", peso: 600, tamanho: 32, cor: "#BDBDBD" }),
    botao("MONTAR MEU KIT", 104, 420, 340, LIMA, PRETO),
    bolha(1020, 120, 300, "#1F1F1F"),
    bolha(1320, 20, 360, LIMA),
    bolha(1620, 180, 280, "#7C5CFF"),
    recorte("Garrafa", ramo$("garrafa-branca-recorte"), { x: 1030, y: 110, w: 290, h: 320, rot: -10 }),
    recorte("Ecobag", ramo$("ecobag-colorida-recorte"), { x: 1330, y: 40, w: 340, h: 380 }),
    recorte("Caneca", ramo$("caneca-branca-recorte"), { x: 1620, y: 200, w: 270, h: 270, rot: 8 }),
    t("Mínimo", { x: 1060, y: 450, w: 420, h: 50 }, { texto: "a partir de 20 unidades", fonte: "manrope", peso: 700, tamanho: 26, cor: LIMA }),
    marca(p, 1640, 470, 44, "#FFFFFF", "direita", 240, "unbounded"),
  ]);
}

/* ===================================================== 18. LIQUIDA */

function liquida(p: PedidoDoModelo): DocumentoDoBanner {
  const AMARELO = "#FFE600";
  return banner({ cor: "#FF5A1F", cor2: "#E0121F", angulo: 120, textura: "nenhuma" }, [
    tex("Raios", "raios", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.1, quantidade: 30, centroX: 72, centroY: 50 }),
    f("Explosão", "explosao", { x: 1190, y: 20, w: 520, h: 520, rot: 8 }, AMARELO, { pontas: 18, profundidade: 0.18, sombra: sombraDe("#7A0000", 0, 16, 30, 0.4) }),
    t("Até", { x: 1250, y: 110, w: 400, h: 70, rot: 8 }, { texto: "ATÉ", fonte: "anton", peso: 400, tamanho: 60, cor: "#B30000", alinhamento: "centro" }),
    t("Percentual", { x: 1220, y: 160, w: 460, h: 230, rot: 8 }, { texto: "60%", fonte: "anton", peso: 400, tamanho: 220, cor: "#B30000", alinhamento: "centro" }),
    t("Off", { x: 1250, y: 370, w: 400, h: 80, rot: 8 }, { texto: "OFF", fonte: "anton", peso: 400, tamanho: 70, cor: "#B30000", alinhamento: "centro" }),
    t("Título", { x: 100, y: 50, w: 1050, h: 300 }, { texto: "QUEIMA DE\nESTOQUE", fonte: "anton", peso: 400, tamanho: 160, linha: 0.92, cor: "#FFFFFF", sombra: "dura" }),
    t("Texto", { x: 104, y: 362, w: 980, h: 60 }, { texto: "Camisetas, canecas e brindes com preço de custo", fonte: "montserrat", peso: 700, tamanho: 32, cor: "#FFE3D3" }),
    botao("APROVEITAR AGORA", 104, 440, 420, AMARELO, "#B30000", { tamanho: 26 }),
    t("Prazo", { x: 560, y: 440, w: 500, h: 76 }, { texto: "enquanto durar o estoque", fonte: "montserrat", peso: 700, tamanho: 26, cor: "#FFFFFF" }),
    marca(p, 1640, 20, 44, "#FFFFFF", "direita", 240),
  ]);
}

/* ===================================================== 19. FRETE E VANTAGENS */

function freteEVantagens(p: PedidoDoModelo): DocumentoDoBanner {
  const AZUL = "#2340FF";
  const vantagens: Array<[string, string, string]> = [
    ["caminhao-lucide", "Frete grátis", "acima de R$ 199"],
    ["cartao-lucide", "6x sem juros", "no cartão"],
    ["pix", "5% no Pix", "à vista"],
    ["escudo-check", "Compra segura", "dados protegidos"],
  ];
  return banner({ cor: AZUL, cor2: "#1428B8", angulo: 135, textura: "nenhuma" }, [
    f("Luz", "circulo", { x: -200, y: -300, w: 900, h: 900 }, radial("#5B73FF", AZUL, 0.7, 0)),
    t("Título", { x: 100, y: 60, w: 1700, h: 170 }, { texto: "Frete grátis para todo o Brasil", html: html(`Frete grátis para ${trecho("todo o Brasil", { cor: "#FFE14D" })}`), fonte: "plus-jakarta-sans", peso: 800, tamanho: 104, cor: "#FFFFFF" }),
    ...vantagens.flatMap(([icone, titulo, detalhe], i) => {
      const x = 100 + i * 440;
      return [
        f(`Cartão ${i + 1}`, "retangulo", { x, y: 270, w: 410, h: 190 }, "#FFFFFF", { raio: 28, opacidade: 0.12 }),
        f(`Ícone ${i + 1}: fundo`, "circulo", { x: x + 30, y: 310, w: 110, h: 110 }, "#FFFFFF"),
        ic(`Ícone ${i + 1}`, icone, x + 55, 335, 60, AZUL, { espessura: 2.2 }),
        t(`Vantagem ${i + 1}`, { x: x + 160, y: 310, w: 245, h: 56 }, { texto: titulo, fonte: "plus-jakarta-sans", peso: 800, tamanho: 30, cor: "#FFFFFF" }),
        t(`Detalhe ${i + 1}`, { x: x + 160, y: 366, w: 240, h: 48 }, { texto: detalhe, fonte: "plus-jakarta-sans", peso: 500, tamanho: 26, cor: "#C7D0FF" }),
      ];
    }),
    marca(p, 1640, 480, 40, "#FFFFFF", "direita", 240, "plus-jakarta-sans"),
  ]);
}

/* ===================================================== 20. LANÇAMENTO MINIMAL */

function lancamentoMinimal(p: PedidoDoModelo): DocumentoDoBanner {
  const ROXO = "#5B21FF";
  return banner({ cor: ROXO, cor2: "#3A0CC9", angulo: 150, textura: "nenhuma" }, [
    f("Anel", "circulo", { x: 1170, y: -40, w: 620, h: 620 }, nada, { borda: { cor: "#FFFFFF", largura: 2 }, opacidade: 0.3 }),
    f("Halo", "circulo", { x: 1230, y: 20, w: 500, h: 500 }, radial("#9B7BFF", ROXO, 0.9, 0)),
    recorte("Camiseta", ramo$("camiseta-branca-recorte"), { x: 1220, y: 30, w: 520, h: 520, rot: -6 }, { sombra: sombraDe("#14005A", 0, 30, 50, 0.55) }),
    t("Novo", { x: 100, y: 90, w: 300, h: 56 }, { texto: "LANÇAMENTO", fonte: "space-grotesk", peso: 700, tamanho: 26, espaco: 0.3, cor: ROXO, alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF" } }),
    t("Título", { x: 96, y: 160, w: 1000, h: 200 }, { texto: "Chegou a camiseta\ndry-fit", html: html(`Chegou a camiseta<br>${trecho("dry-fit", { cor: "#C8FF3D" })}`), fonte: "space-grotesk", peso: 700, tamanho: 92, linha: 1.02, cor: "#FFFFFF" }),
    t("Texto", { x: 100, y: 370, w: 820, h: 50 }, { texto: "Leve, não amassa e a sublimação sai perfeita", fonte: "space-grotesk", peso: 500, tamanho: 30, cor: "#DCD2FF" }),
    botao("CONHECER", 100, 440, 250, "#C8FF3D", "#14005A"),
    ...[
      [1150, 80, 60],
      [1780, 380, 70],
      [1700, 40, 40],
    ].map(([x, y, l], i) => ic(`Brilho ${i + 1}`, "estrela-4", x, y, l, "#C8FF3D", { preenchido: true, espessura: 0.5 })),
    marca(p, 1640, 470, 44, "#FFFFFF", "direita", 240, "space-grotesk"),
  ]);
}

/* ===================================================== 21. FESTA INFANTIL */

function festaInfantil(p: PedidoDoModelo): DocumentoDoBanner {
  const cores = ["#FF5A5F", "#FFC93C", "#2EC4B6", "#7B61FF", "#FF8FAB"];
  const bandeirinhas = Array.from({ length: 16 }, (_, i) => f(`Bandeirinha ${i + 1}`, "triangulo", { x: 40 + i * 118, y: 0, w: 92, h: 90, rot: 180 }, cores[i % cores.length]));
  const balao = (x: number, y: number, l: number, cor: string) => [f("Balão", "circulo", { x, y, w: l, h: l * 1.18 }, radial("#FFFFFF", cor, 0.45, 1), { sombra: sombraDe("#000000", 0, 10, 20, 0.15) }), f("Fio do balão", "retangulo", { x: x + l / 2 - 1, y: y + l * 1.18, w: 2, h: 120 }, "#7A6A8A")];
  const quadro = f("Foto", "retangulo", { x: 1080, y: 110, w: 520, h: 380 }, "#FFFFFF", { raio: 30, borda: { cor: "#FFFFFF", largura: 10 }, rot: 3, sombra: sombraDe("#3B2A50", 0, 16, 30, 0.3) });
  return banner({ cor: "#FFF6E9", textura: "nenhuma" }, [
    ...bandeirinhas,
    t("Título", { x: 100, y: 120, w: 980, h: 220 }, { texto: "A festa com a\ncara dele", html: html(`A festa com a<br>${trecho("cara dele", { cor: "#FF5A5F" })}`), fonte: "baloo-2", peso: 800, tamanho: 100, linha: 1, cor: "#3B2A50" }),
    t("Texto", { x: 104, y: 350, w: 860, h: 56 }, { texto: "Kits de festa, lembrancinhas e topo de bolo personalizados", fonte: "baloo-2", peso: 600, tamanho: 32, cor: "#6B5A80" }),
    botao("MONTAR A FESTA", 104, 430, 340, "#7B61FF", "#FFFFFF", { fonte: "baloo-2", tamanho: 30 }),
    quadro,
    foto("Mesa de festa", ramo$("festa-mesa"), { x: 1080, y: 110, w: 520, h: 380, rot: 3 }, { dentroDe: quadro.id }),
    ...balao(1660, 120, 130, "#FF5A5F"),
    ...balao(1770, 200, 110, "#FFC93C"),
    ...balao(990, 360, 90, "#2EC4B6"),
    fig("Confete", "fogos", 1590, 20, 110, -10),
    marca(p, 1640, 470, 40, "#3B2A50", "direita", 240, "baloo-2"),
  ]);
}

/* ===================================================== 22. PÁSCOA */

function pascoa(p: PedidoDoModelo): DocumentoDoBanner {
  const ROXO = "#6C2BD9";
  const AMARELO = "#FFD84D";
  const ovo = (x: number, y: number, w: number, cor: Pintura, rot: number) => f("Ovo", "circulo", { x, y, w, h: w * 1.3, rot }, cor, { sombra: sombraDe("#2A0B6B", 0, 16, 26, 0.35) });
  const ovoRosa = ovo(1460, 60, 290, linear("#FF8FC4", "#FF4D9A", 160), 8);
  return banner({ cor: ROXO, cor2: "#4515A8", angulo: 140, textura: "nenhuma" }, [
    tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.08, tamanho: 34 }),
    ovo(1240, 140, 250, linear(AMARELO, "#FFB800", 160), -12),
    ovoRosa,
    ovo(1700, 180, 200, linear("#7DE3D0", "#21B8A3", 160), 14),
    tex("Listras do ovo", "listras", { x: 1440, y: 120, w: 330, h: 110, rot: 8 }, "#FFFFFF", { opacidade: 0.45, tamanho: 18, dentroDe: ovoRosa.id, bloqueada: false }),
    ic("Coelho", "coelho", 1100, 300, 160, "#FFFFFF", { espessura: 1.8 }),
    t("Título", { x: 100, y: 80, w: 1000, h: 230 }, { texto: "Páscoa\npersonalizada", html: html(`Páscoa<br>${trecho("personalizada", { cor: AMARELO })}`), fonte: "fredoka", peso: 700, tamanho: 104, linha: 1, cor: "#FFFFFF" }),
    t("Texto", { x: 104, y: 330, w: 860, h: 56 }, { texto: "Caixas, canecas e tags com o nome de cada um", fonte: "fredoka", peso: 500, tamanho: 34, cor: "#E3D5FF" }),
    botao("VER OS KITS", 104, 420, 280, AMARELO, "#3B0F8A", { fonte: "fredoka", tamanho: 30 }),
    marca(p, 1640, 20, 44, "#FFFFFF", "direita", 240, "fredoka"),
  ]);
}

/* ===================================================== 23. PAPELARIA (VOLTA ÀS AULAS) */

function papelaria(p: PedidoDoModelo): DocumentoDoBanner {
  const AZUL = "#1E3A8A";
  const quadro = f("Foto", "retangulo", { x: 1160, y: 60, w: 640, h: 420 }, "#FFFFFF", { rot: -3, sombra: sombraDe("#1E293B", 0, 18, 30, 0.3) });
  return banner({ cor: "#FAFAF5", textura: "nenhuma" }, [
    tex("Quadriculado", "xadrez", { x: 0, y: 0, w: W, h: H }, "#60A5FA", { opacidade: 0.12, tamanho: 36 }),
    f("Margem", "retangulo", { x: 70, y: 0, w: 3, h: H }, "#F87171"),
    t("Título", { x: 110, y: 70, w: 980, h: 230 }, { texto: "Material escolar\ncom o nome", html: html(`Material escolar<br>${trecho("com o nome", { fonte: "caveat", cor: "#EF4444" })}`), fonte: "nunito", peso: 900, tamanho: 96, linha: 1.05, cor: AZUL }),
    t("Rabisco", { x: 680, y: 290, w: 420, h: 70, rot: -4 }, { texto: "não se perde mais!", fonte: "caveat", peso: 700, tamanho: 52, cor: "#EF4444" }),
    t("Texto", { x: 114, y: 330, w: 560, h: 60 }, { texto: "Etiquetas, cadernos e agendas", fonte: "nunito", peso: 700, tamanho: 32, cor: "#334155" }),
    botao("ENCOMENDAR", 114, 420, 300, AZUL, "#FFFFFF", { fonte: "nunito", tamanho: 28 }),
    quadro,
    foto("Papelaria", ramo$("papelaria-marca"), { x: 1180, y: 80, w: 600, h: 380, rot: -3 }, { dentroDe: quadro.id }),
    f("Fita", "retangulo", { x: 1400, y: 40, w: 180, h: 54, rot: 4 }, "#FDE68A", { opacidade: 0.8 }),
    fig("Lápis", "lapis", 1040, 330, 160, 24),
    ic("Seta", "seta-rabisco", 1020, 180, 120, "#EF4444", { espessura: 2.2, rot: 10 }),
    marca(p, 1640, 480, 40, AZUL, "direita", 240, "nunito"),
  ]);
}

/* ===================================================== 24. CUPOM NO BANNER */

function cupomNoBanner(p: PedidoDoModelo): DocumentoDoBanner {
  const MAGENTA = "#D6006F";
  const cupom = silhueta([cartaoRecortado(760, 380, { raio: 30, esquerda: { onde: [0.5], raio: 40 }, direita: { onde: [0.5], raio: 40 } })], 1060, 80, solida("#FFFFFF"), { nome: "Cupom", efeitos: [{ tipo: "sombra", cor: "#4A0026", x: 0, y: 24, desfoque: 40, opacidade: 0.35 }] });
  return banner({ cor: MAGENTA, cor2: "#8A0048", angulo: 140, textura: "nenhuma" }, [
    tex("Raios", "raios", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.06, quantidade: 26, centroX: 75, centroY: 50 }),
    t("Título", { x: 100, y: 90, w: 900, h: 220 }, { texto: "Ganhe 10% na\nprimeira compra", html: html(`Ganhe ${trecho("10%", { cor: "#FFE14D" })} na<br>primeira compra`), fonte: "montserrat", peso: 900, tamanho: 84, linha: 1.05, cor: "#FFFFFF" }),
    t("Texto", { x: 104, y: 330, w: 820, h: 56 }, { texto: "Use o cupom no carrinho e economize já", fonte: "montserrat", peso: 600, tamanho: 32, cor: "#FFD1E8" }),
    botao("COMPRAR AGORA", 104, 420, 380, "#FFE14D", "#6B0038"),
    cupom,
    t("Cupom: rótulo", { x: 1120, y: 120, w: 640, h: 50 }, { texto: "CUPOM DE BOAS-VINDAS", fonte: "montserrat", peso: 800, tamanho: 26, espaco: 0.3, cor: "#9D0052", alinhamento: "centro" }),
    t("Cupom: valor", { x: 1120, y: 170, w: 640, h: 150 }, { texto: "10% OFF", fonte: "anton", peso: 400, tamanho: 140, cor: MAGENTA, alinhamento: "centro" }),
    f("Cupom: picote", "retangulo", { x: 1130, y: 330, w: 620, h: 3 }, "#F3C2D9"),
    t("Cupom: código", { x: 1260, y: 350, w: 360, h: 80 }, { texto: "OLA10", fonte: "space-grotesk", peso: 700, tamanho: 44, espaco: 0.2, cor: "#6B0038", alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFE4F1" } }),
    marca(p, 100, 20, 44, "#FFFFFF", "esquerda", 280),
  ]);
}

/* =============================================================== a lista */

function emQualquerTamanho(montar: (p: PedidoDoModelo) => DocumentoDoBanner) {
  return (p: PedidoDoModelo): DocumentoDoBanner => {
    const doc = montar(p);
    if (p.largura === doc.largura && p.altura === doc.altura) return doc;
    return documentoDasPaginas(paginasDoDocumento(doc).map((pagina) => encaixar(pagina, p.largura, p.altura)));
  };
}

export const MODELOS_DE_BANNER = (
  [
    { chave: "banner-letra-gigante", nome: "Letra gigante", descricao: "Palavra que vaza da borda e o produto na frente", montar: letraGigante, ramo: "sublimacao" },
    { chave: "banner-bento", nome: "Grade em blocos", descricao: "Foto, desconto, frete e produto em blocos", montar: bento, ramo: "sublimacao" },
    { chave: "banner-editorial", nome: "Editorial", descricao: "Serifa de revista e foto em arco", montar: editorialSerifa, ramo: "personalizados" },
    { chave: "banner-cyber", nome: "Cyber Monday neon", descricao: "Modo escuro, grade e neon", montar: cyberNeon, ramo: "grafica" },
    { chave: "banner-neobrutal", nome: "Neobrutalismo", descricao: "Borda preta, sombra dura e selo", montar: neobrutal, ramo: "personalizados" },
    { chave: "banner-y2k", nome: "Y2K cromado", descricao: "Letra de bolha cromada e brilhos", montar: y2kCromado, ramo: "grafica" },
    { chave: "banner-letreiro", nome: "Letreiro em faixa", descricao: "Faixas de texto atravessando a foto", montar: letreiro, ramo: "sublimacao" },
    { chave: "banner-duotone", nome: "Duotone", descricao: "Foto em duas cores e letra vazada", montar: duotone, ramo: "grafica" },
    { chave: "banner-diagonal", nome: "Corte na diagonal", descricao: "Cor e foto em diagonal, etiqueta de preço", montar: corteDiagonal, ramo: "personalizados" },
    { chave: "banner-maes", nome: "Dia das Mães", descricao: "Rosa vivo, foto em arco e flores", montar: diaDasMaes, ramo: "personalizados" },
    { chave: "banner-namorados", nome: "Dia dos Namorados", descricao: "Polaroid do casal e caneca de coração", montar: namorados, ramo: "personalizados" },
    { chave: "banner-pais", nome: "Dia dos Pais", descricao: "Letra condensada gigante e foto", montar: diaDosPais, ramo: "sublimacao" },
    { chave: "banner-natal", nome: "Natal premium", descricao: "Verde, dourado e serifa", montar: natalPremium, ramo: "personalizados" },
    { chave: "banner-pet", nome: "Seu pet na caneca", descricao: "Recortes de cachorro em círculos", montar: pets, ramo: "sublimacao" },
    { chave: "banner-cartoes", nome: "Cartões de visita", descricao: "Gráfica rápida, limpa e com vantagens", montar: graficaCorporativa, ramo: "grafica" },
    { chave: "banner-grande-formato", nome: "Grande formato", descricao: "Plotter e as bolinhas CMYK", montar: grandeFormato, ramo: "grafica" },
    { chave: "banner-brindes", nome: "Brindes de empresa", descricao: "Produtos recortados em bolhas", montar: brindes, ramo: "personalizados" },
    { chave: "banner-liquida", nome: "Queima de estoque", descricao: "Explosão amarela e raios", montar: liquida, ramo: "sublimacao" },
    { chave: "banner-vantagens", nome: "Frete e vantagens", descricao: "Frete grátis e 4 vantagens com ícones", montar: freteEVantagens, ramo: "sublimacao" },
    { chave: "banner-lancamento-minimal", nome: "Lançamento minimal", descricao: "Produto no halo e um título só", montar: lancamentoMinimal, ramo: "sublimacao" },
    { chave: "banner-festa", nome: "Festa infantil", descricao: "Bandeirinhas, balões e foto da mesa", montar: festaInfantil, ramo: "personalizados" },
    { chave: "banner-pascoa", nome: "Páscoa", descricao: "Ovos coloridos e coelho", montar: pascoa, ramo: "personalizados" },
    { chave: "banner-papelaria", nome: "Material escolar", descricao: "Caderno quadriculado e letra à mão", montar: papelaria, ramo: "grafica" },
    { chave: "banner-cupom", nome: "Cupom no banner", descricao: "Cupom de verdade com mordidas", montar: cupomNoBanner, ramo: "sublimacao" },
  ] as const
).map((m) => ({ ...m, feitoPara: "faixa" as const, montar: emQualquerTamanho(m.montar) }));
