/*
 * Modelos dos ramos (out/2026): sublimação, gráfica e personalizados, em post
 * (1080 × 1350), reels/story (1080 × 1920) e carrossel (várias páginas de
 * post). Cada um tem paleta e tema próprios e usa o que o editor tem de
 * melhor: recorte sem fundo com sombra, estampa curvada na caneca (cilindro
 * dentro da foto), foto dentro de forma (coração), trechos com outra fonte e
 * cor, letra vazada, efeitos de letra, texturas, tabela e o contador de
 * páginas fixo no carrossel.
 *
 * As fotos são do Unsplash e do Pexels (licença livre para uso comercial) e
 * moram no depósito da Ktalogu (products/editor-modelos/ramos/); os recortes
 * sem fundo foram feitos com o isnet (licença comercial). Em outro tamanho a
 * composição encaixa inteira (`encaixar`, o mesmo das coleções).
 */
import { documentoDasPaginas, fonteDaChave, htmlDoTextoLimpo, novoId, paginasDoDocumento, solida, type DocumentoDoBanner, type Peca, type PecaDeForma, type PecaDeIcone, type PecaDeImagem, type PecaDeTabela, type PecaDeTexto, type PecaDeTextura, type Pintura } from "./documento";
import { documento, fundoDoBanner, imagem, texto, type CamposDoTexto, type PedidoDoModelo } from "./modelos-base";
import { encaixar } from "./modelos-colecao";

const DEPOSITO = "https://ptpstwltddugnnlewvbw.supabase.co/storage/v1/object/public/products/editor-modelos/ramos";
const foto$ = (nome: string) => `${DEPOSITO}/${nome}.webp`;

/* ------------------------------------------------------------ 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, ...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: 7, profundidade: 0.2, ...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 };
}

function ic(nome: string, chave: string, x: number, y: number, lado: number, cor: string, extra: Partial<PecaDeIcone> = {}): PecaDeIcone {
  return { id: novoId("ic"), tipo: "icone", nome, x, y, w: lado, h: lado, rot: 0, opacidade: 1, icone: chave, pintura: solida(cor), espessura: 2, preenchido: false, sombra: null, ...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.12, bloqueada: true, estilo, cor, quantidade: 18, tamanho: 0, centroX: 50, centroY: 50, giro: 0, ...extra };
}

const linear = (cor: string, cor2: string, angulo: number, alfa?: number, alfa2?: number): Pintura => ({ tipo: "linear", cor, cor2, angulo, ...(alfa !== undefined ? { alfa } : {}), ...(alfa2 !== undefined ? { alfa2 } : {}) });
const radial = (cor: string, cor2: string, alfa?: number, alfa2?: number): Pintura => ({ tipo: "radial", cor, cor2, angulo: 0, ...(alfa !== undefined ? { alfa } : {}), ...(alfa2 !== undefined ? { alfa2 } : {}) });
const comAlfa = (cor: string, alfa: number): Pintura => ({ ...solida(cor), alfa });
const nada: Pintura = { tipo: "nenhuma", cor: "#FFFFFF", cor2: "#FFFFFF", angulo: 0 };

/* Um trecho do texto com outra cor, fonte ou estilo (as fontes vão pelo nome da família). */
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);
const sombraDe = (cor: string, y: number, desfoque: number, opacidade: number) => ({ cor, x: 0, y, desfoque, opacidade });

/* O logo da loja; sem logo, o nome no lugar (a pessoa troca). */
function marca(p: PedidoDoModelo, x: number, y: number, h: number, cor: string, alinhamento: PecaDeTexto["alinhamento"] = "esquerda", larguraMaxima = 420): 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: "bricolage-grotesque", peso: 800, tamanho: h * 0.6, cor, espaco: 0.06, alinhamento });
}

/* WhatsApp e o número (a pessoa troca pelo dela). */
function contato(x: number, y: number, cor: string, tamanho = 28, rotulo = "(00) 00000-0000"): Peca[] {
  /* O logo oficial do WhatsApp, nas cores dele (a pessoa troca pela versão de uma cor no painel, se quiser). */
  return [ic("WhatsApp", "whatsapp-cor", x, y - tamanho * 0.05, tamanho * 1.45, cor), t("Contato", { x: x + tamanho * 1.75, y: y - tamanho * 0.15, w: tamanho * 12, h: tamanho * 1.65 }, { texto: rotulo, fonte: "manrope", peso: 700, tamanho, cor })];
}

/* O contador "01/06" do carrossel: a mesma peça (mesmo id) fixa em todas as páginas. */
function contadorFixo(x: number, y: number, cor: string, fundo: string | null = null): PecaDeTexto {
  return { ...t("Contador de páginas", { x, y, w: 150, h: 54 }, { texto: "{pagina}/{total}", fonte: "space-grotesk", peso: 700, tamanho: 24, cor, alinhamento: "centro", espaco: 0.08, ...(fundo ? { fundo: { forma: "pilula", cor: fundo } } : {}) }), fixa: true };
}

/* "Arraste para o lado" da capa do carrossel. */
function arraste(x: number, y: number, cor: string, frase = "arraste para o lado"): Peca[] {
  return [t("Arraste", { x, y, w: 380, h: 56 }, { texto: frase, fonte: "caveat", peso: 700, tamanho: 42, cor, alinhamento: "direita" }), ic("Seta do arraste", "seta-direita", x + 392, y + 6, 46, cor, { espessura: 2.4 })];
}

function carrossel(paginas: DocumentoDoBanner[]) {
  return documentoDasPaginas(paginas);
}

/* ======================================================= POST · SUBLIMAÇÃO */

/* Caneca branca recortada com a estampa curvada no corpo, halo e raios: roxo elétrico e lima. */
function canecaComASuaCara(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const ROXO = "#4B2BFF";
  const LIMA = "#C8FF3D";
  const TINTA = "#140C3A";
  const caneca = foto("Caneca", foto$("caneca-branca-recorte"), { x: 170, y: 400, w: 700, h: 700 }, { ajuste: "conter", sombra: sombraDe("#0B0530", 46, 60, 0.5) });
  /* A estampa é a imagem dentro da caneca (recortada pela silhueta dela), curvada no cilindro e multiplicada com a luz da porcelana. */
  const estampa = foto("Estampa da caneca", foto$("adesivos-amarelo"), { x: 170 + 700 * 0.33, y: 400 + 700 * 0.15, w: 700 * 0.7, h: 700 * 0.66 }, { cilindro: { curva: 1, arco: 0 }, mistura: "multiplicar", dentroDe: caneca.id, enquadre: { zoom: 1.15, x: 50, y: 50 } });
  const pecas: Peca[] = [
    tex("Raios", "raios", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.07, quantidade: 28, centroX: 50, centroY: 56 }),
    f("Halo", "circulo", { x: 110, y: 330, w: 860, h: 860 }, radial("#8E7BFF", ROXO, 0.95, 0)),
    f("Anel", "circulo", { x: 150, y: 370, w: 780, h: 780 }, nada, { borda: { cor: LIMA, largura: 3 }, opacidade: 0.7 }),
    caneca,
    estampa,
    t("Título", { x: 64, y: 70, w: 720, h: 230 }, {
      texto: "CANECA COM\nA SUA CARA",
      html: html(`CANECA COM<br>A ${trecho("SUA CARA", { cor: LIMA })}`),
      fonte: "anton",
      peso: 400,
      tamanho: 112,
      linha: 0.94,
      cor: "#FFFFFF",
    }),
    t("Chamada", { x: 66, y: 300, w: 560, h: 48 }, { texto: "Sublimação em alta definição", fonte: "manrope", peso: 700, tamanho: 30, cor: "#D6CFFF" }),
    marca(p, 700, 82, 60, "#FFFFFF", "direita", 320),
    t("Selo", { x: 800, y: 300, w: 230, h: 230, rot: 12 }, { texto: "SUA\nFOTO\nAQUI", fonte: "anton", peso: 400, tamanho: 42, linha: 0.95, cor: TINTA, alinhamento: "centro", fundo: { forma: "explosao", cor: LIMA } }),
    ic("Brilho 1", "estrela-4", 92, 520, 64, LIMA, { preenchido: true, espessura: 0.5 }),
    ic("Brilho 2", "estrela-4", 140, 960, 40, "#FFFFFF", { preenchido: true, espessura: 0.5 }),
    ic("Brilho 3", "estrela-4", 930, 900, 52, LIMA, { preenchido: true, espessura: 0.5 }),
    f("Cartão", "retangulo", { x: 56, y: 1090, w: 968, h: 204 }, "#FFFFFF", { raio: 40, sombra: sombraDe("#0B0530", 18, 40, 0.35) }),
    t("A partir de", { x: 96, y: 1112, w: 320, h: 40 }, { texto: "a partir de", fonte: "manrope", peso: 600, tamanho: 26, cor: "#6B6584" }),
    t("Preço", { x: 92, y: 1146, w: 340, h: 120 }, { texto: "R$ 39,90", html: html(`${trecho("R$", { cor: TINTA })} 39,90`), fonte: "anton", peso: 400, tamanho: 96, cor: ROXO }),
    t("Vantagens", { x: 440, y: 1114, w: 430, h: 160 }, { texto: "Alta definição\nResiste à lava-louças\nPronta em 48 horas", fonte: "manrope", peso: 700, tamanho: 28, linha: 1.55, cor: TINTA, lista: "checks", vertical: "meio" }),
    f("Botão redondo", "circulo", { x: 890, y: 1142, w: 104, h: 104 }, ROXO),
    ic("Seta do botão", "seta-direita", 914, 1166, 56, "#FFFFFF", { espessura: 2.6 }),
  ];
  return documento(W, H, fundoDoBanner({ cor: "#5B33FF", cor2: "#2A0FA8", angulo: 165, textura: "nenhuma" }), pecas);
}

/* Camiseta recortada com o logo no peito, "TIME" vazado atrás e a faixa da oferta: petróleo e laranja. */
function uniformes(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const PETROLEO = "#06343F";
  const LARANJA = "#FF6B1A";
  const CIANO = "#2EE6D6";
  const pecas: Peca[] = [
    tex("Listras", "listras", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.05, quantidade: 22, giro: 45 }),
    t("Time vazado", { x: -40, y: 360, w: 1160, h: 470 }, { texto: "TIME", fonte: "anton", peso: 400, tamanho: 470, linha: 1, alinhamento: "centro", pintura: nada, contorno: { cor: "#FFFFFF", largura: 3 }, opacidade: 0.22 }),
    f("Luz", "circulo", { x: 190, y: 380, w: 700, h: 700 }, radial(CIANO, PETROLEO, 0.35, 0)),
    foto("Camiseta", foto$("camiseta-branca-recorte"), { x: 175, y: 360, w: 730, h: 693 }, { ajuste: "conter", sombra: sombraDe("#000000", 30, 50, 0.45) }),
    t("Logo no peito", { x: 440, y: 560, w: 200, h: 110 }, { texto: "SEU\nLOGO", fonte: "anton", peso: 400, tamanho: 50, linha: 0.95, cor: LARANJA, alinhamento: "centro", mistura: "multiplicar" }),
    t("Título", { x: 60, y: 66, w: 960, h: 200 }, {
      texto: "UNIFORMES QUE\nVESTEM A MARCA",
      html: html(`UNIFORMES QUE<br>${trecho("VESTEM A MARCA", { cor: LARANJA })}`),
      fonte: "archivo-black",
      peso: 400,
      tamanho: 80,
      linha: 1.02,
      cor: "#FFFFFF",
    }),
    ...["Empresas", "Eventos", "Times"].map((rotulo, i) => t(`Chip ${rotulo}`, { x: 60 + i * 210, y: 286, w: 190, h: 58 }, { texto: rotulo, fonte: "space-grotesk", peso: 700, tamanho: 26, cor: PETROLEO, alinhamento: "centro", fundo: { forma: "pilula", cor: CIANO } })),
    marca(p, 760, 290, 54, "#FFFFFF", "direita", 260),
    ic("Camiseta pequena", "camiseta", 930, 1000, 70, CIANO, { espessura: 1.6, rot: 10 }),
    f("Faixa da oferta", "retangulo", { x: 0, y: 1090, w: W, h: 260 }, LARANJA),
    tex("Retícula da faixa", "meio-tom", { x: 540, y: 1090, w: 540, h: 260 }, "#FFFFFF", { opacidade: 0.18, tamanho: 18, giro: 90 }),
    t("Oferta", { x: 60, y: 1118, w: 600, h: 120 }, { texto: "A partir de 10 peças\ncom arte grátis", fonte: "archivo-black", peso: 400, tamanho: 40, linha: 1.12, cor: PETROLEO }),
    t("Preço", { x: 640, y: 1108, w: 380, h: 120 }, { texto: "R$ 34,90", fonte: "anton", peso: 400, tamanho: 92, cor: "#FFFFFF", alinhamento: "direita" }),
    t("Por unidade", { x: 760, y: 1222, w: 260, h: 40 }, { texto: "por unidade", fonte: "manrope", peso: 700, tamanho: 24, cor: PETROLEO, alinhamento: "direita" }),
    ...contato(62, 1270, PETROLEO, 30),
  ];
  return documento(W, H, fundoDoBanner({ cor: PETROLEO, cor2: "#0B4B59", angulo: 160, textura: "nenhuma" }), pecas);
}

/* ========================================================= POST · GRÁFICA */

/* Cartões no mármore sumindo no preto, serifa com itálico dourado: o cartão de visita premium. */
function cartaoPremium(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const PRETO = "#0B0B0D";
  const OURO = "#D9B25F";
  const OURO_CLARO = "#F3DFA6";
  const pecas: Peca[] = [
    foto("Cartões", foto$("cartoes-marmore"), { x: 0, y: 0, w: W, h: 840 }, { desvanecer: { lado: "baixo", tamanho: 0.5 }, filtros: { brilho: 94, contraste: 110, saturacao: 80, desfoque: 0, vinheta: 35 } }),
    f("Véu do topo", "retangulo", { x: 0, y: 0, w: W, h: 300 }, linear(PRETO, PRETO, 180, 0.78, 0)),
    f("Linha do topo", "retangulo", { x: 70, y: 96, w: 56, h: 3 }, OURO),
    t("Etiqueta", { x: 140, y: 74, w: 520, h: 48 }, { texto: "GRÁFICA • LINHA PREMIUM", fonte: "space-grotesk", peso: 700, tamanho: 22, espaco: 0.2, cor: OURO_CLARO }),
    marca(p, 700, 70, 58, "#FFFFFF", "direita", 310),
    t("Título", { x: 66, y: 742, w: 950, h: 250 }, {
      texto: "Primeira impressão\né a que fica.",
      html: html(`Primeira impressão<br>é a que ${trecho("fica.", { cor: OURO, italico: true })}`),
      fonte: "playfair-display",
      peso: 700,
      tamanho: 96,
      linha: 1.04,
      cor: "#FFFFFF",
    }),
    f("Linha dourada", "retangulo", { x: 70, y: 1016, w: 120, h: 3 }, linear(OURO, OURO_CLARO, 90)),
    t("Detalhes", { x: 70, y: 1040, w: 560, h: 130 }, { texto: "Couché 300 g • Laminação fosca\nVerniz localizado • Cantos arredondados", fonte: "manrope", peso: 500, tamanho: 26, linha: 1.55, cor: "#B9B3AA", vertical: "topo" }),
    t("Quantidade", { x: 660, y: 1040, w: 350, h: 40 }, { texto: "1.000 unidades", fonte: "manrope", peso: 700, tamanho: 24, cor: OURO_CLARO, alinhamento: "direita" }),
    t("Preço", { x: 620, y: 1074, w: 390, h: 110 }, { texto: "R$ 89", html: html(`${trecho("R$", { fonte: "manrope", cor: OURO_CLARO })} 89`), fonte: "dm-serif-display", peso: 400, tamanho: 100, cor: OURO, alinhamento: "direita" }),
    f("Separador", "retangulo", { x: 70, y: 1196, w: 940, h: 1 }, comAlfa("#FFFFFF", 0.16)),
    t("Botão", { x: 70, y: 1224, w: 420, h: 78 }, { texto: "PEÇA SEU ORÇAMENTO", fonte: "montserrat", peso: 800, tamanho: 23, espaco: 0.08, cor: PRETO, alinhamento: "centro", fundo: { forma: "pilula", cor: OURO, cor2: OURO_CLARO } }),
    ...contato(560, 1244, "#FFFFFF", 28),
    ic("Brilho", "estrela-4", 950, 690, 44, OURO_CLARO, { preenchido: true, espessura: 0.5 }),
  ];
  return documento(W, H, fundoDoBanner({ cor: PRETO, textura: "grao", corDaTextura: "#FFFFFF" }), pecas);
}

/* ================================================== POST · PERSONALIZADOS */

/* Foto do presente dentro de um coração (com o coração de trás deslocado), etiquetas de adesivo: rosa e vinho. */
function presenteQueEmociona(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const ROSA = "#FF2E7E";
  const VINHO = "#6E0A35";
  const AMARELO = "#FFD84D";
  const etiqueta = (rotulo: string, l: Lugar, fundo: string, cor: string) => t(`Etiqueta ${rotulo}`, l, { texto: rotulo, fonte: "fredoka", peso: 700, tamanho: 30, cor, alinhamento: "centro", fundo: { forma: "pilula", cor: fundo }, sombra: "suave" });
  const pecas: Peca[] = [
    tex("Pontinhos", "pontos", { x: 0, y: 0, w: W, h: H }, ROSA, { opacidade: 0.1, quantidade: 26 }),
    t("Título", { x: 60, y: 56, w: 960, h: 210 }, {
      texto: "Feito pra quem\nvocê ama",
      html: html(`Feito pra quem<br>${trecho("você ama", { fonte: "pacifico", cor: ROSA })}`),
      fonte: "fraunces",
      peso: 900,
      tamanho: 88,
      linha: 1.08,
      cor: VINHO,
      alinhamento: "centro",
    }),
    f("Coração de trás", "coracao", { x: 176, y: 318, w: 790, h: 720 }, ROSA),
    foto("Presente", foto$("presente-rosa"), { x: 140, y: 290, w: 790, h: 720 }, { mascara: "coracao", enquadre: { zoom: 1.15, x: 50, y: 48 }, sombra: sombraDe(VINHO, 20, 40, 0.3) }),
    etiqueta("Nome gravado", { x: 54, y: 470, w: 280, h: 72, rot: -9 }, AMARELO, VINHO),
    etiqueta("Foto + frase", { x: 770, y: 380, w: 250, h: 72, rot: 8 }, "#FFFFFF", ROSA),
    etiqueta("Embalagem inclusa", { x: 700, y: 900, w: 330, h: 72, rot: -6 }, VINHO, "#FFFFFF"),
    ic("Coração 1", "coracao", 90, 300, 60, ROSA, { preenchido: true, espessura: 0.5, rot: -14 }),
    ic("Coração 2", "coracao", 960, 600, 46, VINHO, { preenchido: true, espessura: 0.5, rot: 12 }),
    ic("Brilho", "brilho", 120, 860, 70, AMARELO, { espessura: 2 }),
    t("Texto", { x: 90, y: 1060, w: 900, h: 90 }, { texto: "Canecas, almofadas, quadros e kits com a sua história.", fonte: "manrope", peso: 600, tamanho: 32, linha: 1.3, cor: VINHO, alinhamento: "centro" }),
    t("Botão", { x: 290, y: 1164, w: 500, h: 92 }, { texto: "MONTE O SEU PRESENTE", fonte: "montserrat", peso: 800, tamanho: 29, espaco: 0.04, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor: ROSA }, sombra: "suave" }),
    marca(p, 390, 1272, 52, VINHO, "centro", 300),
  ];
  return documento(W, H, fundoDoBanner({ cor: "#FFF3EA", cor2: "#FFD9E8", angulo: 180, textura: "nenhuma" }), pecas);
}

/* ===================================================== REELS · SUBLIMAÇÃO */

/* Capa de reels dos bastidores: foto da prensa no fundo, véu, botão de play e o título grande: preto e amarelo. */
function bastidores(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1920;
  const AMARELO = "#FFD400";
  const pecas: Peca[] = [
    foto("Bastidores", foto$("prensa-amarelo"), { x: 0, y: 0, w: W, h: H }, { 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: H }, linear("#000000", "#000000", 180, 0.2, 0.92)),
    marca(p, 60, 120, 70, "#FFFFFF", "esquerda", 420),
    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 } }),
    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"),
    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" }),
    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",
    }),
    f("Linha", "retangulo", { x: 60, y: 1520, w: 90, h: 6 }, AMARELO),
    t("Passos", { x: 60, y: 1546, w: 900, h: 70 }, { texto: "Arte • Impressão • Prensa • Pronta", fonte: "manrope", peso: 700, tamanho: 38, cor: "#FFFFFF" }),
  ];
  return documento(W, H, fundoDoBanner({ cor: "#0A0A0A", textura: "nenhuma" }), pecas);
}

/* ======================================================== REELS · GRÁFICA */

/* As três tintas que se misturam (multiplicar) por cima da foto das tintas e a régua CMYK: branco e cores puras. */
function coresQueSaltam(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1920;
  const [C, M, Y, K] = ["#00AEEF", "#EC008C", "#FFE600", "#141414"];
  const pecas: Peca[] = [
    marca(p, 60, 110, 64, K, "esquerda", 400),
    t("Etiqueta", { x: 720, y: 116, w: 300, h: 56 }, { texto: "IMPRESSÃO", fonte: "space-grotesk", peso: 700, tamanho: 24, espaco: 0.2, cor: K, alinhamento: "direita" }),
    foto("Tintas", foto$("tintas-cmyk"), { x: 60, y: 240, w: 960, h: 820 }, { raio: 44, enquadre: { zoom: 1.12, x: 45, y: 55 }, filtros: { brilho: 102, contraste: 112, saturacao: 118, desfoque: 0 } }),
    f("Tinta ciano", "circulo", { x: 750, y: 1150, w: 170, h: 170 }, C, { mistura: "multiplicar", opacidade: 0.92 }),
    f("Tinta magenta", "circulo", { x: 852, y: 1150, w: 170, h: 170 }, M, { mistura: "multiplicar", opacidade: 0.92 }),
    f("Tinta amarela", "circulo", { x: 801, y: 1236, w: 170, h: 170 }, Y, { mistura: "multiplicar", opacidade: 0.92 }),
    t("Título", { x: 56, y: 1100, w: 970, h: 410 }, {
      texto: "CORES QUE\nSALTAM DO\nPAPEL",
      html: html(`CORES QUE<br>${trecho("SALTAM", { cor: M })} DO<br>PAPEL`),
      fonte: "anton",
      peso: 400,
      tamanho: 146,
      linha: 0.92,
      cor: K,
    }),
    ...[C, M, Y, K].map((cor, i) => f(`Régua ${"CMYK"[i]}`, "retangulo", { x: 60 + i * 240, y: 1530, w: 240, h: 26 }, cor)),
    t("Texto", { x: 60, y: 1584, w: 900, h: 110 }, { texto: "Impressão digital e offset com prova de cor. Do cartão ao banner.", fonte: "manrope", peso: 600, tamanho: 36, linha: 1.35, cor: "#3A3A3A", vertical: "topo" }),
  ];
  return documento(W, H, fundoDoBanner({ cor: "#F7F6F1", textura: "grao", corDaTextura: "#000000" }), pecas);
}

/* A foto dos adesivos no amarelo, título com contorno duplo de adesivo e chips girados: amarelo e preto. */
function adesivosQueViramMarca(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1920;
  /* O amarelo da própria foto (sem a faixa de outro tom onde ela começa e termina). */
  const AMARELO = "#F6D80A";
  const PRETO = "#111111";
  const chip = (rotulo: string, l: Lugar) => t(`Chip ${rotulo}`, l, { texto: rotulo, fonte: "bricolage-grotesque", peso: 800, tamanho: 34, cor: PRETO, alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF" }, sombra: "dura" });
  const pecas: Peca[] = [
    tex("Retícula", "meio-tom", { x: 0, y: 0, w: W, h: 620 }, PRETO, { opacidade: 0.09, tamanho: 22, giro: 180 }),
    marca(p, 640, 110, 64, PRETO, "direita", 380),
    t("Título", { x: 50, y: 210, w: 980, h: 420 }, {
      texto: "ADESIVOS\nQUE VIRAM\nMARCA",
      fonte: "bricolage-grotesque",
      peso: 800,
      tamanho: 132,
      linha: 0.95,
      espaco: -0.02,
      cor: PRETO,
      efeito: { tipo: "contorno-duplo", cor: "#FFFFFF", forca: 0.55 },
    }),
    foto("Adesivos", foto$("adesivos-amarelo"), { x: 0, y: 650, w: W, h: 760 }, { enquadre: { zoom: 1.08, x: 50, y: 50 } }),
    chip("Vinil à prova d'água", { x: 60, y: 1380, w: 470, h: 84, rot: -4 }),
    chip("Corte especial", { x: 560, y: 1410, w: 340, h: 84, rot: 5 }),
    chip("Qualquer formato", { x: 120, y: 1490, w: 400, h: 84, rot: 3 }),
    t("Quantidade", { x: 60, y: 1610, w: 400, h: 110 }, { texto: "100 un. por", fonte: "anton", peso: 400, tamanho: 84, cor: PRETO }),
    t("Preço", { x: 440, y: 1606, w: 330, h: 118 }, { texto: "R$ 59", fonte: "anton", peso: 400, tamanho: 84, cor: AMARELO, alinhamento: "centro", fundo: { forma: "pilula", cor: PRETO } }),
    ic("Estrela", "estrela", 880, 1590, 110, PRETO, { preenchido: true, espessura: 0.5, rot: 14 }),
  ];
  return documento(W, H, fundoDoBanner({ cor: AMARELO, textura: "nenhuma" }), pecas);
}

/* ================================================= REELS · PERSONALIZADOS */

/* Festa infantil: balões, confete, foto redonda com borda branca e o selo do kit: lilás, rosa e amarelo. */
function festaComACaraDele(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1920;
  const LILAS = "#8C6BFF";
  const ROSA = "#FF5CA8";
  const AMARELO = "#FFD23F";
  const AZUL = "#3EC5FF";
  const balao = (cor: string, x: number, y: number, lado: number, rot: number): Peca[] => [
    f(`Fio do balão ${cor}`, "retangulo", { x: x + lado / 2 - 1.5, y: y + lado * 1.15, w: 3, h: lado * 0.9, rot: rot * 0.4 }, comAlfa("#FFFFFF", 0.75)),
    f(`Balão ${cor}`, "gota", { x, y, w: lado, h: lado * 1.22, rot: 180 + rot }, radial("#FFFFFF", cor, 0.55, 1), { sombra: sombraDe("#3B1D8F", 14, 26, 0.25) }),
  ];
  const chip = (rotulo: string, l: Lugar, cor: string) => t(`Chip ${rotulo}`, l, { texto: rotulo, fonte: "fredoka", peso: 700, tamanho: 34, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor } });
  const pecas: Peca[] = [
    tex("Confete", "pontos", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.16, quantidade: 30 }),
    ...balao(AMARELO, 60, 470, 150, -12),
    ...balao(AZUL, 880, 420, 140, 10),
    ...balao(ROSA, 900, 1180, 110, 6),
    t("Título", { x: 60, y: 170, w: 960, h: 300 }, {
      texto: "FESTA COM\nA CARA DELE",
      html: html(`FESTA COM<br>${trecho("A CARA DELE", { cor: AMARELO })}`),
      fonte: "lilita-one",
      peso: 400,
      tamanho: 130,
      linha: 0.98,
      cor: "#FFFFFF",
      alinhamento: "centro",
      efeito: { tipo: "levantar", cor: "#3B1D8F", forca: 0.55 },
    }),
    foto("Festa", foto$("festa-mesa"), { x: 190, y: 560, w: 700, h: 700 }, { circulo: true, borda: { cor: "#FFFFFF", largura: 18 }, sombra: sombraDe("#3B1D8F", 24, 50, 0.4), enquadre: { zoom: 1.1, x: 50, y: 50 } }),
    t("Kit", { x: 610, y: 1060, w: 400, h: 400, rot: 10 }, { texto: "kits desde\nR$ 4,90", html: html(`kits desde<br>${trecho("R$ 4,90", { fonte: "lilita-one" })}`), fonte: "fredoka", peso: 700, tamanho: 46, linha: 1.05, cor: "#3B1D8F", alinhamento: "centro", fundo: { forma: "estrela", cor: AMARELO } }),
    chip("Topo de bolo", { x: 60, y: 1340, w: 300, h: 80 }, ROSA),
    chip("Lembrancinhas", { x: 60, y: 1440, w: 340, h: 80 }, AZUL),
    chip("Caixinhas", { x: 420, y: 1440, w: 260, h: 80 }, "#3B1D8F"),
    t("Texto", { x: 60, y: 1548, w: 880, h: 70 }, { texto: "Tudo no tema que ele escolher.", fonte: "fredoka", peso: 600, tamanho: 40, cor: "#FFFFFF" }),
    marca(p, 60, 1640, 64, "#FFFFFF", "esquerda", 400),
  ];
  return documento(W, H, fundoDoBanner({ cor: LILAS, cor2: ROSA, angulo: 165, textura: "nenhuma" }), pecas);
}

/* ================================================ CARROSSEL · SUBLIMAÇÃO */

/* Seis páginas: capa, quatro produtos (número grande, foto, onde vende) e a chamada final: cobalto, coral e creme. */
function produtosQueVendem(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const AZUL = "#1C3FFF";
  const CORAL = "#FF6F59";
  const CREME = "#FFF6EC";
  const TINTA = "#0E1430";
  const contador = contadorFixo(900, 60, "#FFFFFF", TINTA);
  const capa = documento(W, H, fundoDoBanner({ cor: AZUL, cor2: "#0D24B8", angulo: 160, textura: "nenhuma" }), [
    tex("Ondas", "ondas", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.08, quantidade: 14 }),
    t("Quatro vazado", { x: 40, y: 90, w: 560, h: 700 }, { texto: "4", fonte: "anton", peso: 400, tamanho: 760, linha: 0.9, alinhamento: "centro", pintura: nada, contorno: { cor: CORAL, largura: 5 }, opacidade: 0.9 }),
    foto("Caneca", foto$("caneca-roxo"), { x: 540, y: 170, w: 430, h: 520, rot: 6 }, { raio: 36, borda: { cor: "#FFFFFF", largura: 14 }, sombra: sombraDe("#000000", 24, 50, 0.4) }),
    contador,
    marca(p, 60, 66, 58, "#FFFFFF", "esquerda", 360),
    t("Título", { x: 60, y: 800, w: 960, h: 320 }, {
      texto: "PRODUTOS QUE\nVENDEM O\nANO TODO",
      html: html(`PRODUTOS QUE<br>VENDEM O<br>${trecho("ANO TODO", { cor: CORAL })}`),
      fonte: "archivo-black",
      peso: 400,
      tamanho: 92,
      linha: 1.02,
      cor: "#FFFFFF",
    }),
    t("Subtítulo", { x: 60, y: 1130, w: 520, h: 60 }, { texto: "4 ideias para sublimar", fonte: "manrope", peso: 700, tamanho: 32, cor: "#C9D2FF" }),
    ...arraste(560, 1220, "#FFFFFF"),
  ]);
  const itens: Array<[string, string, string, string[]]> = [
    ["Caneca", "caneca-amarelo", "Presente que nunca sai de moda.", ["Datas comemorativas", "Brindes de empresa", "Lembrança de festa"]],
    ["Camiseta", "camiseta-cabide", "Do uniforme ao evento da família.", ["Empresas e times", "Formaturas", "Aniversários"]],
    ["Garrafa térmica", "garrafas-cores", "O brinde que a pessoa usa todo dia.", ["Academias", "Eventos corporativos", "Kits de fim de ano"]],
    ["Ecobag", "ecobag-colorida", "Marca passeando pela cidade.", ["Lojas e feiras", "Congressos", "Kits de boas-vindas"]],
  ];
  const paginas = itens.map(([nome, arquivo, frase, usos], i) =>
    documento(W, H, fundoDoBanner({ cor: CREME, textura: "nenhuma" }), [
      tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: H }, AZUL, { opacidade: 0.06, quantidade: 24 }),
      f("Bloco da foto", "retangulo", { x: 480, y: 0, w: 600, h: 860 }, AZUL),
      foto(nome, foto$(arquivo), { x: 520, y: 120, w: 500, h: 660 }, { raio: 30, sombra: sombraDe("#000000", 22, 44, 0.35) }),
      contador,
      t("Número", { x: 50, y: 90, w: 430, h: 300 }, { texto: String(i + 1).padStart(2, "0"), fonte: "anton", peso: 400, tamanho: 300, linha: 1, cor: CORAL }),
      t("Produto", { x: 60, y: 400, w: 400, h: 130 }, { texto: nome.toUpperCase(), fonte: "archivo-black", peso: 400, tamanho: 56, linha: 1.05, cor: TINTA, vertical: "topo" }),
      t("Frase", { x: 60, y: 540, w: 400, h: 120 }, { texto: frase, fonte: "manrope", peso: 600, tamanho: 30, linha: 1.35, cor: "#4A5070", vertical: "topo" }),
      t("Onde vende", { x: 60, y: 900, w: 600, h: 44 }, { texto: "ONDE VENDE", fonte: "space-grotesk", peso: 700, tamanho: 24, espaco: 0.2, cor: CORAL }),
      t("Usos", { x: 60, y: 950, w: 640, h: 200 }, { texto: usos.join("\n"), fonte: "manrope", peso: 700, tamanho: 36, linha: 1.6, cor: TINTA, lista: "checks", vertical: "topo" }),
      ic("Ícone do produto", i === 1 ? "camiseta" : i === 0 ? "caneca" : "presente", 900, 1180, 110, AZUL, { espessura: 1.4 }),
    ]),
  );
  const final = documento(W, H, fundoDoBanner({ cor: CORAL, cor2: "#FF8A5B", angulo: 150, textura: "nenhuma" }), [
    tex("Raios", "raios", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.08, quantidade: 24, centroX: 50, centroY: 42 }),
    contador,
    t("Pergunta", { x: 60, y: 300, w: 960, h: 330 }, { texto: "Qual deles você\nvai querer com\na sua marca?", fonte: "archivo-black", peso: 400, tamanho: 84, linha: 1.05, cor: "#FFFFFF", alinhamento: "centro" }),
    t("Botão", { x: 240, y: 720, w: 600, h: 104 }, { texto: "CHAMA NO WHATSAPP", fonte: "montserrat", peso: 800, tamanho: 34, espaco: 0.04, cor: AZUL, alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF" }, sombra: "suave" }),
    ...contato(370, 880, "#FFFFFF", 32),
    marca(p, 340, 1130, 80, "#FFFFFF", "centro", 400),
  ]);
  return carrossel([capa, ...paginas, final]);
}

/* =================================================== CARROSSEL · GRÁFICA */

/* Guia de seis páginas: capa, CMYK, 300 dpi, sangria, fontes/PDF e a chamada; os desenhos são formas do editor: grafite e lima. */
function arquivoProntoParaImprimir(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const GRAFITE = "#1B1D22";
  const LIMA = "#D4FF3A";
  const CINZA = "#9095A0";
  const contador = contadorFixo(900, 60, GRAFITE, LIMA);
  const fundo = () => fundoDoBanner({ cor: GRAFITE, cor2: "#24272E", angulo: 160, textura: "grao", corDaTextura: "#FFFFFF" });
  const cabecalho = (numero: string, titulo: string): Peca[] => [
    t("Número", { x: 60, y: 60, w: 300, h: 56 }, { texto: `CUIDADO ${numero}`, fonte: "space-grotesk", peso: 700, tamanho: 24, espaco: 0.2, cor: LIMA }),
    t("Título", { x: 60, y: 130, w: 960, h: 210 }, { texto: titulo, fonte: "unbounded", peso: 800, tamanho: 74, linha: 1.05, cor: "#FFFFFF", vertical: "topo" }),
  ];
  const explicacao = (frase: string, y = 1010) => t("Explicação", { x: 60, y, w: 960, h: 180 }, { texto: frase, fonte: "manrope", peso: 500, tamanho: 36, linha: 1.4, cor: "#D8DBE2", vertical: "topo" });
  const capa = documento(W, H, fundo(), [
    foto("Lupa", foto$("lupa-cmyk"), { x: 420, y: 0, w: 660, h: H }, { desvanecer: { lado: "esquerda", tamanho: 0.55 }, filtros: { brilho: 100, contraste: 108, saturacao: 112, desfoque: 0 } }),
    contador,
    marca(p, 60, 66, 56, "#FFFFFF", "esquerda", 360),
    t("Título", { x: 56, y: 400, w: 820, h: 420 }, {
      texto: "SEU ARQUIVO\nPRONTO PRA\nIMPRIMIR",
      html: html(`SEU ARQUIVO<br>PRONTO PRA<br>${trecho("IMPRIMIR", { cor: LIMA })}`),
      fonte: "unbounded",
      peso: 800,
      tamanho: 96,
      linha: 1.02,
      cor: "#FFFFFF",
    }),
    t("Subtítulo", { x: 60, y: 850, w: 470, h: 150 }, { texto: "4 cuidados que evitam retrabalho (e gasto à toa).", fonte: "manrope", peso: 600, tamanho: 36, linha: 1.3, cor: CINZA, vertical: "topo" }),
    ...arraste(560, 1220, "#FFFFFF"),
  ]);
  const cmyk = documento(W, H, fundo(), [
    contador,
    ...cabecalho("01", "Mande em CMYK,\nnão em RGB"),
    f("Quadro RGB", "retangulo", { x: 60, y: 420, w: 450, h: 450 }, linear("#FF0040", "#00FF7A", 135), { raio: 30 }),
    f("Quadro CMYK", "retangulo", { x: 570, y: 420, w: 450, h: 450 }, linear("#D6336C", "#3FA66B", 135), { raio: 30 }),
    t("Rótulo RGB", { x: 60, y: 890, w: 450, h: 60 }, { texto: "RGB • na tela", fonte: "space-grotesk", peso: 700, tamanho: 30, cor: "#FFFFFF", alinhamento: "centro" }),
    t("Rótulo CMYK", { x: 570, y: 890, w: 450, h: 60 }, { texto: "CMYK • no papel", fonte: "space-grotesk", peso: 700, tamanho: 30, cor: LIMA, alinhamento: "centro" }),
    explicacao("A tela mostra cores que a tinta não alcança. Em CMYK você vê antes o que vai sair impresso."),
  ]);
  /* 300 dpi: a mesma bolinha em pixels grandes (quadradinhos) e lisa. */
  const quadradinhos: Peca[] = [];
  const lado = 56;
  for (let i = 0; i < 8; i += 1)
    for (let j = 0; j < 8; j += 1) {
      const dx = i - 3.5;
      const dy = j - 3.5;
      if (dx * dx + dy * dy <= 14) quadradinhos.push(f(`Pixel ${i}-${j}`, "retangulo", { x: 60 + i * lado, y: 430 + j * lado, w: lado - 4, h: lado - 4 }, (i + j) % 2 ? "#8FAE1F" : LIMA));
    }
  const dpi = documento(W, H, fundo(), [
    contador,
    ...cabecalho("02", "Imagem com\n300 dpi"),
    ...quadradinhos,
    f("Bolinha lisa", "circulo", { x: 600, y: 440, w: 420, h: 420 }, radial("#F1FFB8", LIMA, 1, 1)),
    t("Rótulo 72", { x: 60, y: 890, w: 450, h: 60 }, { texto: "72 dpi • serrilhado", fonte: "space-grotesk", peso: 700, tamanho: 30, cor: "#FFFFFF", alinhamento: "centro" }),
    t("Rótulo 300", { x: 570, y: 890, w: 450, h: 60 }, { texto: "300 dpi • nítido", fonte: "space-grotesk", peso: 700, tamanho: 30, cor: LIMA, alinhamento: "centro" }),
    explicacao("Foto tirada da internet costuma ter 72 dpi: na tela fica bonita, no papel aparece cada quadradinho."),
  ]);
  const sangria = documento(W, H, fundo(), [
    contador,
    ...cabecalho("03", "Deixe 3 mm\nde sangria"),
    f("Sangria", "retangulo", { x: 190, y: 400, w: 700, h: 520 }, comAlfa(LIMA, 0.25), { raio: 6 }),
    f("Folha", "retangulo", { x: 230, y: 440, w: 620, h: 440 }, "#FFFFFF", { raio: 4, sombra: sombraDe("#000000", 10, 24, 0.35) }),
    f("Margem de segurança", "retangulo", { x: 280, y: 490, w: 520, h: 340 }, nada, { borda: { cor: "#1C9BEF", largura: 3 } }),
    t("Seu texto", { x: 300, y: 600, w: 480, h: 120 }, { texto: "Texto e logo\naqui dentro", fonte: "manrope", peso: 800, tamanho: 40, linha: 1.15, cor: GRAFITE, alinhamento: "centro" }),
    t("Legenda sangria", { x: 60, y: 940, w: 480, h: 50 }, { texto: "■ sangria (é cortada)", fonte: "space-grotesk", peso: 700, tamanho: 28, cor: LIMA }),
    t("Legenda segurança", { x: 540, y: 940, w: 480, h: 50 }, { texto: "■ área segura", fonte: "space-grotesk", peso: 700, tamanho: 28, cor: "#59B8FF", alinhamento: "direita" }),
    explicacao("Estique o fundo 3 mm além do corte e mantenha o que importa longe da borda.", 1020),
  ]);
  const pdf = documento(W, H, fundo(), [
    contador,
    ...cabecalho("04", "Fontes em curva\ne PDF"),
    t("Aa", { x: 60, y: 380, w: 560, h: 520 }, { texto: "Aa", fonte: "playfair-display", peso: 900, tamanho: 440, linha: 1, cor: "#FFFFFF", alinhamento: "centro" }),
    f("Selo do PDF", "circulo", { x: 640, y: 470, w: 340, h: 340 }, LIMA),
    t("PDF", { x: 640, y: 560, w: 340, h: 160 }, { texto: "PDF", fonte: "unbounded", peso: 800, tamanho: 96, cor: GRAFITE, alinhamento: "centro" }),
    ic("Certo", "check-circulo", 880, 460, 100, "#FFFFFF", { espessura: 2.2 }),
    explicacao("Converta as fontes em curva (ou incorpore no PDF). Assim a letra sai do jeito que você escolheu."),
  ]);
  const final = documento(W, H, fundoDoBanner({ cor: LIMA, textura: "nenhuma" }), [
    tex("Retícula", "meio-tom", { x: 0, y: 0, w: W, h: H }, GRAFITE, { opacidade: 0.08, tamanho: 20, giro: 135 }),
    contador,
    ic("Impressora", "impressora", 440, 230, 200, GRAFITE, { espessura: 1.4 }),
    t("Chamada", { x: 60, y: 480, w: 960, h: 300 }, { texto: "Mande seu arquivo.\nA gente confere\nantes de imprimir.", fonte: "unbounded", peso: 800, tamanho: 68, linha: 1.12, cor: GRAFITE, alinhamento: "centro" }),
    t("Botão", { x: 260, y: 850, w: 560, h: 100 }, { texto: "ENVIAR ARQUIVO", fonte: "montserrat", peso: 800, tamanho: 34, espaco: 0.06, cor: LIMA, alinhamento: "centro", fundo: { forma: "pilula", cor: GRAFITE } }),
    ...contato(370, 1000, GRAFITE, 32),
    marca(p, 340, 1170, 76, GRAFITE, "centro", 400),
  ]);
  return carrossel([capa, cmyk, dpi, sangria, pdf, final]);
}

/* ============================================ CARROSSEL · PERSONALIZADOS */

/* Kit corporativo de fim de ano em cinco páginas: verde-garrafa, creme e dourado, serifa elegante. */
function kitCorporativo(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const VERDE = "#12372A";
  const CREME = "#F3EBDD";
  const OURO = "#C9A45C";
  const TERRA = "#9A5530";
  const contador = contadorFixo(900, 60, VERDE, OURO);
  const titulo = (texto_: string, htmlDoTitulo: string, y: number, cor: string, h = 260): PecaDeTexto =>
    t("Título", { x: 60, y, w: 960, h }, { texto: texto_, html: html(htmlDoTitulo), fonte: "cormorant-garamond", peso: 700, tamanho: 96, linha: 1.02, cor });
  const capa = documento(W, H, fundoDoBanner({ cor: VERDE, cor2: "#0B241B", angulo: 160, textura: "grao", corDaTextura: "#FFFFFF" }), [
    foto("Presente", foto$("presente-verde"), { x: 650, y: 150, w: 370, h: 700 }, { raio: 185, borda: { cor: OURO, largura: 6 }, enquadre: { zoom: 1.2, x: 50, y: 55 } }),
    contador,
    marca(p, 60, 66, 56, CREME, "esquerda", 360),
    t("Etiqueta", { x: 60, y: 470, w: 460, h: 50 }, { texto: "KITS CORPORATIVOS", fonte: "space-grotesk", peso: 700, tamanho: 24, espaco: 0.24, cor: OURO }),
    t("Título", { x: 60, y: 530, w: 580, h: 330 }, { texto: "Presentes que\nfortalecem\nrelações", html: html(`Presentes que<br>${trecho("fortalecem", { italico: true, cor: OURO })}<br>relações`), fonte: "cormorant-garamond", peso: 700, tamanho: 88, linha: 1.02, cor: CREME, vertical: "topo" }),
    t("Texto", { x: 60, y: 900, w: 900, h: 110 }, { texto: "Para clientes, parceiros e a sua equipe no fim de ano.", fonte: "manrope", peso: 500, tamanho: 32, linha: 1.4, cor: "#CFC6B4", vertical: "topo" }),
    f("Linha", "retangulo", { x: 60, y: 1060, w: 960, h: 1 }, comAlfa(OURO, 0.6)),
    ...arraste(560, 1220, CREME),
  ]);
  const itens: Array<[string, string]> = [
    ["Caderno com capa gravada", "cadernos"],
    ["Garrafa térmica com o logo", "garrafa-branca-recorte"],
    ["Caneca na cor da marca", "caneca-verde"],
  ];
  const noKit = documento(W, H, fundoDoBanner({ cor: CREME, textura: "nenhuma" }), [
    contador,
    titulo("O que vai\nno kit", `O que vai<br>${trecho("no kit", { italico: true, cor: TERRA })}`, 80, VERDE),
    ...itens.flatMap(([nome, arquivo], i) => {
      const y = 380 + i * 300;
      return [
        f(`Círculo ${i + 1}`, "circulo", { x: 60, y, w: 250, h: 250 }, i === 1 ? VERDE : "#E7DCC8"),
        foto(nome, foto$(arquivo), { x: 72, y: y + 12, w: 226, h: 226 }, i === 1 ? { ajuste: "conter" } : { circulo: true }),
        t(`Item ${i + 1}`, { x: 350, y: y + 40, w: 670, h: 110 }, { texto: nome, fonte: "cormorant-garamond", peso: 700, tamanho: 50, linha: 1.05, cor: VERDE }),
        t(`Detalhe ${i + 1}`, { x: 352, y: y + 150, w: 660, h: 50 }, { texto: ["Gravação a laser ou hot stamping", "Inox, 500 ml, gravação permanente", "Sublimação com a sua paleta"][i], fonte: "manrope", peso: 600, tamanho: 26, cor: "#6E6A5E" }),
      ];
    }),
  ]);
  const marcaNoDetalhe = documento(W, H, fundoDoBanner({ cor: VERDE, textura: "nenhuma" }), [
    foto("Cartões", foto$("cartoes-branco"), { x: 0, y: 0, w: W, h: 760 }, { filtros: { brilho: 98, contraste: 104, saturacao: 90, desfoque: 0, temperatura: 12 }, desvanecer: { lado: "baixo", tamanho: 0.35 } }),
    t("Marca no cartão", { x: 600, y: 330, w: 300, h: 70, rot: -14 }, { texto: "Sua marca", fonte: "cormorant-garamond", peso: 700, italico: true, tamanho: 48, cor: OURO, alinhamento: "centro" }),
    contador,
    titulo("Sua marca em\ncada detalhe", `Sua marca em<br>${trecho("cada detalhe", { italico: true, cor: OURO })}`, 760, CREME),
    t("Técnicas", { x: 60, y: 1030, w: 960, h: 200 }, { texto: "Gravação a laser\nHot stamping dourado\nEmbalagem com cartão personalizado", fonte: "manrope", peso: 600, tamanho: 32, linha: 1.55, cor: "#E2D8C4", lista: "pontos", vertical: "topo" }),
  ]);
  const passos: Array<[string, string]> = [
    ["Você escolhe os itens", "e a quantidade de cada kit"],
    ["A gente aprova a arte", "com prova digital antes de produzir"],
    ["Entregamos embalado", "com cartão e laço, pronto para dar"],
  ];
  const comoFunciona = documento(W, H, fundoDoBanner({ cor: CREME, textura: "nenhuma" }), [
    contador,
    titulo("Como\nfunciona", `Como<br>${trecho("funciona", { italico: true, cor: TERRA })}`, 80, VERDE),
    f("Trilho", "retangulo", { x: 118, y: 450, w: 4, h: 680 }, comAlfa(VERDE, 0.25)),
    ...passos.flatMap(([titulo_, detalhe], i) => {
      const y = 420 + i * 250;
      return [
        t(`Passo ${i + 1}`, { x: 60, y, w: 120, h: 120 }, { texto: String(i + 1), fonte: "cormorant-garamond", peso: 700, tamanho: 64, cor: CREME, alinhamento: "centro", fundo: { forma: "circulo", cor: VERDE } }),
        t(`Etapa ${i + 1}`, { x: 220, y: y + 6, w: 800, h: 64 }, { texto: titulo_, fonte: "cormorant-garamond", peso: 700, tamanho: 52, cor: VERDE }),
        t(`Detalhe ${i + 1}`, { x: 222, y: y + 72, w: 800, h: 48 }, { texto: detalhe, fonte: "manrope", peso: 600, tamanho: 28, cor: "#6E6A5E" }),
      ];
    }),
  ]);
  const final = documento(W, H, fundoDoBanner({ cor: VERDE, cor2: "#0B241B", angulo: 170, textura: "grao", corDaTextura: "#FFFFFF" }), [
    contador,
    ic("Laço", "laco-presente", 450, 210, 180, OURO),
    titulo("Peça o orçamento\ndo seu kit", `Peça o orçamento<br>${trecho("do seu kit", { italico: true, cor: OURO })}`, 400, CREME),
    t("Prazo", { x: 60, y: 680, w: 960, h: 60 }, { texto: "Pedidos para o fim de ano até 30 de novembro", fonte: "manrope", peso: 600, tamanho: 32, cor: "#CFC6B4", alinhamento: "centro" }),
    t("Botão", { x: 260, y: 800, w: 560, h: 100 }, { texto: "QUERO MEU ORÇAMENTO", fonte: "montserrat", peso: 800, tamanho: 30, espaco: 0.06, cor: VERDE, alinhamento: "centro", fundo: { forma: "pilula", cor: OURO } }),
    ...contato(370, 960, CREME, 32),
    marca(p, 340, 1150, 76, CREME, "centro", 400),
  ]);
  /* As páginas de dentro alinham o título pelo meio. */
  for (const pagina of [noKit, comoFunciona, marcaNoDetalhe]) for (const peca of pagina.pecas) if (peca.tipo === "texto" && peca.nome === "Título") peca.vertical = "topo";
  for (const peca of final.pecas) if (peca.tipo === "texto" && peca.nome === "Título") peca.alinhamento = "centro";
  return carrossel([capa, noKit, marcaNoDetalhe, comoFunciona, final]);
}

/* Tabela de lembrancinhas em cinco páginas (com a tabela do editor): turquesa, rosa e amarelo. */
function tabelaDeLembrancinhas(p: PedidoDoModelo): DocumentoDoBanner {
  const W = 1080;
  const H = 1350;
  const TURQUESA = "#00B3A4";
  const ROSA = "#FF6FA5";
  const AMARELO = "#FFD166";
  const CREME = "#FFF9F0";
  const TINTA = "#23303B";
  const contador = contadorFixo(900, 60, "#FFFFFF", ROSA);
  const tabela = (nome: string, celulas: string[][], y: number, h: number): PecaDeTabela => ({
    id: novoId("tb"),
    tipo: "tabela",
    nome,
    x: 60,
    y,
    w: 960,
    h,
    rot: 0,
    opacidade: 1,
    celulas,
    fonte: "fredoka",
    tamanho: 34,
    corDoTexto: TINTA,
    cabecalho: true,
    corDoCabecalho: TURQUESA,
    corDoTextoDoCabecalho: "#FFFFFF",
    corDaLinha: "#FFFFFF",
    corDaLinha2: "#FFF0DA",
    corDaBorda: "#F1E2C8",
    alinhamento: "centro",
    raio: 28,
  });
  const tituloDaPagina = (texto_: string, y = 120): PecaDeTexto => t("Título", { x: 60, y, w: 800, h: 150 }, { texto: texto_, fonte: "lilita-one", peso: 400, tamanho: 82, linha: 1, cor: TINTA, vertical: "topo" });
  const capa = documento(W, H, fundoDoBanner({ cor: TURQUESA, cor2: "#009488", angulo: 160, textura: "nenhuma" }), [
    tex("Confete", "pontos", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.16, quantidade: 28 }),
    foto("Lembrancinhas", foto$("lembrancinhas"), { x: 100, y: 170, w: 880, h: 620, rot: -3 }, { raio: 30, borda: { cor: "#FFFFFF", largura: 16 }, sombra: sombraDe("#00453F", 24, 44, 0.4) }),
    contador,
    marca(p, 60, 66, 56, "#FFFFFF", "esquerda", 360),
    t("Título", { x: 60, y: 830, w: 960, h: 250 }, {
      texto: "TABELA DE\nLEMBRANCINHAS",
      html: html(`TABELA DE<br>${trecho("LEMBRANCINHAS", { cor: AMARELO })}`),
      fonte: "lilita-one",
      peso: 400,
      tamanho: 112,
      linha: 1,
      cor: "#FFFFFF",
      efeito: { tipo: "levantar", cor: "#00453F", forca: 0.5 },
    }),
    t("Ano", { x: 60, y: 1100, w: 300, h: 70 }, { texto: "Valores 2026", fonte: "fredoka", peso: 700, tamanho: 32, cor: TINTA, alinhamento: "centro", fundo: { forma: "pilula", cor: AMARELO } }),
    ...arraste(560, 1220, "#FFFFFF"),
  ]);
  const kits = documento(W, H, fundoDoBanner({ cor: CREME, textura: "nenhuma" }), [
    tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: H }, ROSA, { opacidade: 0.08, quantidade: 26 }),
    contador,
    tituloDaPagina("Kits de festa"),
    t("Por unidade", { x: 60, y: 250, w: 700, h: 50 }, { texto: "valor por unidade, com a arte do tema", fonte: "fredoka", peso: 500, tamanho: 30, cor: "#6B7680" }),
    tabela(
      "Tabela de kits",
      [
        ["Item", "20 un.", "50 un.", "100 un."],
        ["Caixa milk", "R$ 3,90", "R$ 3,50", "R$ 2,90"],
        ["Tubete", "R$ 2,50", "R$ 2,20", "R$ 1,90"],
        ["Sacolinha", "R$ 4,90", "R$ 4,40", "R$ 3,90"],
        ["Copo", "R$ 6,90", "R$ 6,20", "R$ 5,50"],
        ["Tag", "R$ 1,20", "R$ 0,99", "R$ 0,80"],
      ],
      340,
      720,
    ),
    t("Observação", { x: 60, y: 1110, w: 960, h: 90 }, { texto: "Combine itens e ganhe a tag de presente.", fonte: "fredoka", peso: 700, tamanho: 34, cor: "#FFFFFF", alinhamento: "centro", fundo: { forma: "pilula", cor: ROSA } }),
  ]);
  const papelaria = documento(W, H, fundoDoBanner({ cor: CREME, textura: "nenhuma" }), [
    tex("Pontos", "pontos", { x: 0, y: 0, w: W, h: H }, TURQUESA, { opacidade: 0.08, quantidade: 26 }),
    contador,
    tituloDaPagina("Papelaria da festa"),
    t("Por unidade", { x: 60, y: 250, w: 700, h: 50 }, { texto: "impressão em papel fotográfico ou adesivo", fonte: "fredoka", peso: 500, tamanho: 30, cor: "#6B7680" }),
    tabela(
      "Tabela de papelaria",
      [
        ["Item", "Quantidade", "Valor"],
        ["Convite digital", "1 arte", "R$ 25,00"],
        ["Convite impresso", "20 un.", "R$ 39,90"],
        ["Topo de bolo", "1 un.", "R$ 29,90"],
        ["Rótulo de água", "20 un.", "R$ 19,90"],
        ["Adesivo redondo", "48 un.", "R$ 14,90"],
      ],
      340,
      720,
    ),
    ic("Presente", "presente", 900, 1130, 100, ROSA, { espessura: 1.6, rot: 8 }),
  ]);
  const passos: Array<[string, string, string]> = [
    ["calendario", "Reserve a data", "com 15 dias de antecedência"],
    ["mensagem", "Conte o tema", "nome, idade e as cores da festa"],
    ["check-circulo", "Aprove a arte", "mandamos a prévia pelo WhatsApp"],
    ["presente", "Retire ou receba", "tudo embalado e conferido"],
  ];
  const encomendar = documento(W, H, fundoDoBanner({ cor: AMARELO, cor2: "#FFC14D", angulo: 160, textura: "nenhuma" }), [
    contador,
    tituloDaPagina("Como encomendar"),
    ...passos.flatMap(([icone, titulo_, detalhe], i) => {
      const y = 330 + i * 230;
      return [
        f(`Fundo do passo ${i + 1}`, "retangulo", { x: 60, y, w: 960, h: 200 }, "#FFFFFF", { raio: 36, sombra: sombraDe("#8A5A00", 10, 24, 0.18) }),
        f(`Círculo ${i + 1}`, "circulo", { x: 90, y: y + 40, w: 120, h: 120 }, i % 2 ? ROSA : TURQUESA),
        ic(`Ícone ${i + 1}`, icone, 120, y + 70, 60, "#FFFFFF", { espessura: 2 }),
        t(`Etapa ${i + 1}`, { x: 240, y: y + 34, w: 740, h: 70 }, { texto: titulo_, fonte: "lilita-one", peso: 400, tamanho: 52, cor: TINTA }),
        t(`Detalhe ${i + 1}`, { x: 242, y: y + 108, w: 740, h: 56 }, { texto: detalhe, fonte: "fredoka", peso: 500, tamanho: 32, cor: "#5C6670" }),
      ];
    }),
  ]);
  const final = documento(W, H, fundoDoBanner({ cor: ROSA, cor2: "#FF8DB8", angulo: 160, textura: "nenhuma" }), [
    tex("Confete", "pontos", { x: 0, y: 0, w: W, h: H }, "#FFFFFF", { opacidade: 0.18, quantidade: 28 }),
    contador,
    foto("Criança com presente", foto$("menina-presente"), { x: 290, y: 140, w: 500, h: 500 }, { circulo: true, borda: { cor: "#FFFFFF", largura: 16 }, enquadre: { zoom: 1.25, x: 45, y: 40 }, sombra: sombraDe("#8C1F4E", 20, 40, 0.35) }),
    t("Chamada", { x: 60, y: 690, w: 960, h: 220 }, { texto: "Reserve a data\nda sua festa", fonte: "lilita-one", peso: 400, tamanho: 96, linha: 1.02, cor: "#FFFFFF", alinhamento: "centro", efeito: { tipo: "levantar", cor: "#8C1F4E", forca: 0.5 } }),
    t("Botão", { x: 260, y: 950, w: 560, h: 100 }, { texto: "QUERO ENCOMENDAR", fonte: "fredoka", peso: 700, tamanho: 38, cor: ROSA, alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF" } }),
    ...contato(370, 1100, "#FFFFFF", 32),
    marca(p, 340, 1200, 70, "#FFFFFF", "centro", 400),
  ]);
  return carrossel([capa, kits, papelaria, encomendar, final]);
}

/* ============================================================ outros tamanhos */

/* Desenhado num tamanho, pedido em outro: cada página encaixa inteira (o mesmo jeito das coleções). */
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_DOS_RAMOS = (
  [
    { chave: "ramo-caneca", nome: "Caneca com a sua cara", descricao: "Caneca recortada com estampa curvada", montar: canecaComASuaCara, ramo: "sublimacao", feitoPara: "post" },
    { chave: "ramo-uniformes", nome: "Uniformes", descricao: "Camiseta com logo e faixa de oferta", montar: uniformes, ramo: "sublimacao", feitoPara: "post" },
    { chave: "ramo-cartao", nome: "Cartão premium", descricao: "Preto, dourado e serifa", montar: cartaoPremium, ramo: "grafica", feitoPara: "post" },
    { chave: "ramo-presente", nome: "Presente que emociona", descricao: "Foto em coração e etiquetas", montar: presenteQueEmociona, ramo: "personalizados", feitoPara: "post" },
    { chave: "ramo-bastidores", nome: "Bastidores", descricao: "Capa de reels com play", montar: bastidores, ramo: "sublimacao", feitoPara: "story" },
    { chave: "ramo-cmyk", nome: "Cores que saltam", descricao: "Tintas CMYK que se misturam", montar: coresQueSaltam, ramo: "grafica", feitoPara: "story" },
    { chave: "ramo-adesivos", nome: "Adesivos", descricao: "Amarelo, contorno de adesivo", montar: adesivosQueViramMarca, ramo: "grafica", feitoPara: "story" },
    { chave: "ramo-festa", nome: "Festa infantil", descricao: "Balões, confete e selo do kit", montar: festaComACaraDele, ramo: "personalizados", feitoPara: "story" },
    { chave: "ramo-produtos", nome: "Produtos que vendem", descricao: "Carrossel: capa, 4 produtos e chamada", montar: produtosQueVendem, ramo: "sublimacao", feitoPara: "carrossel", paginas: 6 },
    { chave: "ramo-arquivo", nome: "Arquivo pronto", descricao: "Carrossel: guia da gráfica em 6 páginas", montar: arquivoProntoParaImprimir, ramo: "grafica", feitoPara: "carrossel", paginas: 6 },
    { chave: "ramo-corporativo", nome: "Kit corporativo", descricao: "Carrossel elegante de fim de ano", montar: kitCorporativo, ramo: "personalizados", feitoPara: "carrossel", paginas: 5 },
    { chave: "ramo-tabela", nome: "Tabela de lembrancinhas", descricao: "Carrossel com tabela de preços", montar: tabelaDeLembrancinhas, ramo: "personalizados", feitoPara: "carrossel", paginas: 5 },
  ] as const
).map((m) => ({ ...m, montar: emQualquerTamanho(m.montar) }));

/* Os ajudantes também servem aos modelos animados (modelos-animados.ts). */
export { t, f, foto, ic, tex, linear, radial, comAlfa, nada, trecho, html, sombraDe, marca, contato, foto$ };
