/*
 * Os modelos profissionais do editor de artes (out/2026): Black Friday,
 * coleção editorial, frete grátis, cupom em ticket, depoimento, comunicado e
 * neon. Usam o que o editor tem de melhor (trecho com outra cor ou vazado,
 * ícones, brilho atrás da foto, faixas giradas) e se arrumam sozinhos em
 * qualquer tamanho:
 *  - faixa (largura ≥ 1,6 × altura): texto à esquerda, foto à direita;
 *  - o resto (quadrado, retrato, story, A4): tudo empilhado no centro.
 * A coluna é empilhada (modelos-base.ts): se não cabe, tudo diminui junto.
 */
import {
  ICONES,
  htmlDoTextoLimpo,
  luminancia,
  misturar,
  novoId,
  solida,
  sombraSuave,
  type DocumentoDoBanner,
  type Peca,
  type PecaDeIcone,
} from "./documento";
import { AMARELO, corDeFundo, documento, empilhar, fundoDoBanner, forma, imagem, linhaDoLogo, texto, type Linha, type PedidoDoModelo } from "./modelos-base";

type Jeito = { W: number; H: number; faixa: boolean; alto: boolean; u: number; m: number };

function jeito(p: PedidoDoModelo): Jeito {
  const W = p.largura;
  const H = p.altura;
  const menor = Math.min(W, H);
  const faixa = W / H >= 1.6;
  return { W, H, faixa, alto: H / W >= 1.25, u: faixa ? H : menor * 0.66, m: faixa ? H * 0.12 : menor * 0.08 };
}

const trecho = (estilo: string, conteudo: string) => `<span style="${estilo}">${conteudo}</span>`;
const vazado = (cor: string, grossura: number) => `color:transparent;-webkit-text-stroke:${Math.round(grossura * 10) / 10}px ${cor}`;

function iconeEm(chave: string, x: number, y: number, lado: number, cor: string, extra: Partial<PecaDeIcone> = {}): PecaDeIcone {
  return { id: novoId("ic"), tipo: "icone", nome: ICONES[chave]?.nome || "Ícone", x, y, w: lado, h: lado, rot: 0, opacidade: 1, icone: chave, pintura: solida(cor), espessura: 1.8, preenchido: false, sombra: null, ...extra };
}

/* Um círculo centrado em outra peça, `fator` vezes maior. */
function emVolta(alvo: { x: number; y: number; w: number; h: number }, fator: number) {
  const lado = Math.max(alvo.w, alvo.h) * fator;
  return { x: alvo.x + alvo.w / 2 - lado / 2, y: alvo.y + alvo.h / 2 - lado / 2, w: lado, h: lado };
}

/* A cor da loja quando dá para usar como destaque em fundo claro (as muito claras escurecem). */
function destaqueSobreClaro(cor: string) {
  return luminancia(cor) > 0.35 ? misturar(cor, "#000000", 0.45) : cor;
}

function pecasDoLogo(linhas: Linha[]) {
  return linhas.map((l) => l.peca);
}

/* ============================================================ black friday */

function blackFriday(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, alto, u, m } = jeito(p);
  const escuro = "#09090D";
  const realce = luminancia(p.cor) > 0.02 && luminancia(p.cor) < 0.75 ? p.cor : "#7C3AED";
  const alinhar = faixa ? "esquerda" : "centro";
  const contorno = Math.max(2, u * (faixa ? 0.0055 : 0.0075));

  const chamada = texto({ nome: "Chamada", texto: "A SEXTA MAIS ESPERADA DO ANO", tamanho: u * 0.036, peso: 800, espaco: 0.26, cor: AMARELO, alinhamento: alinhar });
  const titulo = texto({
    nome: "Título",
    texto: faixa ? "BLACK FRIDAY" : "BLACK\nFRIDAY",
    html: htmlDoTextoLimpo(`BLACK${faixa ? " " : "<br>"}${trecho(vazado(AMARELO, contorno), "FRIDAY")}`),
    fonte: "anton",
    peso: 400,
    tamanho: u * (faixa ? 0.25 : 0.3),
    linha: 0.92,
    espaco: 0.01,
    alinhamento: alinhar,
  });
  const oferta = texto({ nome: "Oferta", texto: "ATÉ 70% OFF", html: htmlDoTextoLimpo(`ATÉ ${trecho(`color:${AMARELO}`, "70% OFF")}`), fonte: "kanit", peso: 900, tamanho: u * 0.105, linha: 1, alinhamento: alinhar });
  const botao = texto({ nome: "Botão", texto: "APROVEITE AGORA", tamanho: u * 0.042, peso: 900, cor: escuro, espaco: 0.08, alinhamento: "centro", fundo: { forma: "pilula", cor: AMARELO } });
  const nota = texto({ nome: "Detalhe", texto: "De 24 a 28 de novembro · enquanto durar o estoque", fonte: "outfit", peso: 500, tamanho: u * 0.03, opacidade: 0.6, alinhamento: alinhar, linha: 1.25 });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, ajuste: "cobrir", circulo: true, sombra: false }) : null;
  const logo = linhaDoLogo(p, u * 0.085, u * 0.05);
  const pecas: Peca[] = [];

  /* A faixa amarela girada, com a chamada repetida (vai além das bordas). */
  const faixaGirada = (y: number, giro: number) => {
    const tamanho = u * 0.048;
    const unidade = "BLACK FRIDAY  •  ATÉ 70% OFF  •  ";
    const largura = W * 1.5;
    const vezes = Math.max(2, Math.floor(largura / (unidade.length * 0.43 * tamanho)));
    return texto({ nome: "Faixa", texto: unidade.repeat(vezes).trim(), fonte: "anton", peso: 400, tamanho, cor: escuro, espaco: 0.04, alinhamento: "centro", x: -W * 0.25, y, w: largura, h: tamanho * 1.9, rot: giro, fundo: { forma: "retangulo", cor: AMARELO, raio: 0 } });
  };

  /* O "%" enorme e vazado, bem apagado, atrás de tudo. */
  const porcento = texto({ nome: "Fundo %", texto: "%", fonte: "anton", peso: 400, tamanho: (faixa ? H : Math.min(W, H)) * 1.1, cor: "#FFFFFF", alinhamento: "centro", opacidade: 0.07, contorno: { cor: "#FFFFFF", largura: Math.max(2, u * 0.006) } });
  porcento.pintura = { tipo: "nenhuma", cor: "#FFFFFF", cor2: "#FFFFFF", angulo: 0 };

  if (faixa) {
    const lado = H * 0.86;
    const xFoto = W - m - lado;
    const coluna = (foto ? xFoto - W * 0.05 : W * 0.62) - m;
    empilhar(
      [
        ...logo,
        { peca: chamada, w: coluna, h: u * 0.06, depois: u * 0.015 },
        { peca: titulo, w: coluna, h: u * 0.27, depois: u * 0.01 },
        { peca: oferta, w: coluna, h: u * 0.12, depois: u * 0.06 },
        { peca: botao, w: u * 0.6, h: u * 0.12, fixa: true },
      ],
      m,
      coluna,
      m * 0.85,
      H - m * 0.85,
      false,
    );
    Object.assign(porcento, { x: W - H * 1.05, y: -H * 0.12, w: H * 0.9, h: H * 1.25 });
    pecas.push(porcento);
    if (foto) Object.assign(foto, { x: xFoto, y: (H - lado) / 2, w: lado, h: lado });
  } else {
    const faixas = alto ? 2 : 1;
    const folga = u * 0.17;
    const ladoDaFoto = Math.min(W * 0.62, H * (alto ? 0.3 : 0.34));
    const linhas: Linha[] = [
      ...logo,
      { peca: chamada, w: W - m * 2, h: u * 0.06, depois: u * 0.02 },
      { peca: titulo, w: W - m * 2, h: u * 0.58, depois: u * 0.04 },
    ];
    if (foto) linhas.push({ peca: foto, w: ladoDaFoto, h: ladoDaFoto, depois: u * 0.05, fixa: true });
    linhas.push({ peca: oferta, w: W - m * 2, h: u * 0.12, depois: u * 0.05 }, { peca: botao, w: u * 0.62, h: u * 0.12, depois: u * 0.05, fixa: true }, { peca: nota, w: W - m * 2, h: u * 0.05 });
    empilhar(linhas, m, W - m * 2, m + (faixas === 2 ? folga : 0), H - m - folga, true);
    Object.assign(porcento, { x: W * 0.05, y: H * 0.18, w: W * 0.9, h: H * 0.64 });
    pecas.push(porcento);
  }

  if (foto) {
    pecas.push(forma({ nome: "Brilho", forma: "circulo", ...emVolta(foto, faixa ? 1.45 : 1.7), cor: realce, opacidade: 0.95 }));
    (pecas.at(-1) as { pintura: unknown }).pintura = { tipo: "radial", cor: realce, cor2: escuro, angulo: 0 };
    pecas.push(forma({ nome: "Anel", forma: "circulo", ...emVolta(foto, 1.07), cor: AMARELO, opacidade: 0.9, borda: { cor: AMARELO, largura: Math.max(2, u * 0.006) } }));
    (pecas.at(-1) as { pintura: unknown }).pintura = { tipo: "nenhuma", cor: AMARELO, cor2: AMARELO, angulo: 0 };
    pecas.push(foto);
  }
  pecas.push(...pecasDoLogo(logo), chamada, titulo, oferta, botao);
  if (!faixa) pecas.push(nota);
  if (faixa) pecas.push(faixaGirada(H - u * 0.07, -1.5));
  else {
    pecas.push(faixaGirada(H - u * 0.17, -4));
    if (alto) pecas.push(faixaGirada(u * 0.06, -4));
  }
  return documento(W, H, fundoDoBanner({ cor: escuro, textura: "grao" }), pecas);
}

/* ================================================== coleção (editorial) */

function colecao(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, u, m } = jeito(p);
  const creme = "#F4EEE6";
  const tinta = "#1C1917";
  const acento = destaqueSobreClaro(p.cor);
  const claro = misturar(acento, "#FFFFFF", 0.84);
  const alinhar = faixa ? "esquerda" : "centro";

  const rotulo = texto({ nome: "Rótulo", texto: "LANÇAMENTO · 2026", fonte: "space-grotesk", peso: 700, tamanho: u * 0.032, espaco: 0.36, cor: acento, alinhamento: alinhar });
  const titulo = texto({
    nome: "Título",
    texto: "Nova\ncoleção",
    html: htmlDoTextoLimpo(`Nova<br>${trecho(`font-style:italic;color:${acento}`, "coleção")}`),
    fonte: "dm-serif-display",
    peso: 400,
    tamanho: u * (faixa ? 0.2 : 0.24),
    linha: 0.95,
    espaco: -0.01,
    cor: tinta,
    alinhamento: alinhar,
  });
  const apoio = texto({ nome: "Texto", texto: "Peças pensadas para durar, com acabamento impecável e entrega para todo o Brasil.", fonte: "outfit", peso: 400, tamanho: u * 0.042, linha: 1.4, cor: "#57534E", alinhamento: alinhar });
  const botao = texto({ nome: "Botão", texto: "Ver a coleção  →", fonte: "outfit", peso: 700, tamanho: u * 0.04, cor: creme, alinhamento: "centro", espaco: 0.02, fundo: { forma: "pilula", cor: tinta } });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, ajuste: "cobrir", sombra: true }) : null;
  const logo = linhaDoLogo(p, u * 0.08, u * 0.06);
  const pecas: Peca[] = [];

  if (faixa) {
    const lado = H * 1.15;
    const xCirculo = W - lado * 1.02;
    const circulo = forma({ nome: "Círculo", forma: "circulo", x: xCirculo, y: (H - lado) / 2, w: lado, h: lado, cor: claro });
    pecas.push(circulo);
    const coluna = Math.min(W * 0.48, xCirculo - m * 1.6);
    empilhar(
      [...logo, { peca: rotulo, w: coluna, h: u * 0.055, depois: u * 0.03 }, { peca: titulo, w: coluna, h: u * 0.4, depois: u * 0.04 }, { peca: apoio, w: coluna * 0.9, h: u * 0.13, depois: u * 0.06 }, { peca: botao, w: u * 0.52, h: u * 0.11, fixa: true }],
      m * 1.3,
      coluna,
      m,
      H - m,
      false,
    );
    if (foto) {
      const ladoDaFoto = H * 0.84;
      Object.assign(foto, { x: Math.min(W - m * 0.8 - ladoDaFoto, xCirculo + lado * 0.5 - ladoDaFoto / 2), y: (H - ladoDaFoto) / 2, w: ladoDaFoto, h: ladoDaFoto });
    }
    pecas.push(iconeEm("brilho", xCirculo - u * 0.02, H * 0.12, u * 0.12, acento, { espessura: 1.4 }));
  } else {
    const ladoDaFoto = Math.min(W * 0.62, H * 0.36);
    const linhas: Linha[] = [...logo];
    if (foto) linhas.push({ peca: foto, w: ladoDaFoto, h: ladoDaFoto, depois: u * 0.08, fixa: true });
    linhas.push(
      { peca: rotulo, w: W - m * 2, h: u * 0.055, depois: u * 0.03 },
      { peca: titulo, w: W - m * 2, h: u * 0.48, depois: u * 0.04 },
      { peca: apoio, w: W * 0.72, h: u * 0.14, depois: u * 0.06 },
      { peca: botao, w: u * 0.56, h: u * 0.11, fixa: true },
    );
    empilhar(linhas, m, W - m * 2, m, H - m, true);
    if (foto) pecas.push(forma({ nome: "Círculo", forma: "circulo", ...emVolta(foto, 1.28), cor: claro }));
    else pecas.push(forma({ nome: "Círculo", forma: "circulo", x: W * 0.55, y: -W * 0.25, w: W * 0.7, h: W * 0.7, cor: claro }));
    pecas.push(iconeEm("brilho", W - m - u * 0.11, m, u * 0.11, acento, { espessura: 1.4 }));
  }
  if (foto) foto.raio = foto.w * 0.05;
  /* A linha fina de acabamento, embaixo, como em revista. */
  pecas.push(forma({ nome: "Linha", forma: "retangulo", x: m, y: H - m * 0.55, w: W - m * 2, h: Math.max(2, u * 0.003), cor: tinta, opacidade: 0.18 }));
  if (foto) pecas.push(foto);
  pecas.push(...pecasDoLogo(logo), rotulo, titulo, apoio, botao);
  return documento(W, H, fundoDoBanner({ cor: creme, textura: "nenhuma" }), pecas);
}

/* ============================================================ frete grátis */

function freteGratis(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, u, m } = jeito(p);
  const base = corDeFundo(p.cor);
  const fundo2 = misturar(base, "#000000", 0.35);
  const alinhar = faixa ? "esquerda" : "centro";
  const contorno = Math.max(2, u * 0.006);

  const selo = forma({ nome: "Selo", forma: "circulo", x: 0, y: 0, w: 10, h: 10, cor: "#FFFFFF", sombra: true });
  const caminhao = iconeEm("caminhao", 0, 0, 10, base, { espessura: 1.7 });
  const titulo = texto({
    nome: "Título",
    texto: "FRETE\nGRÁTIS",
    html: htmlDoTextoLimpo(`FRETE<br>${trecho(vazado("#FFFFFF", contorno), "GRÁTIS")}`),
    fonte: "unbounded",
    peso: 800,
    tamanho: u * (faixa ? 0.17 : 0.2),
    linha: 1.1,
    alinhamento: alinhar,
  });
  const apoio = texto({ nome: "Texto", texto: "para todo o Brasil nas compras acima de", fonte: "outfit", peso: 500, tamanho: u * 0.045, opacidade: 0.9, alinhamento: alinhar });
  const valor = texto({ nome: "Valor", texto: "R$ 199", fonte: "kanit", peso: 900, tamanho: u * 0.09, cor: "#141414", alinhamento: "centro", fundo: { forma: "pilula", cor: AMARELO } });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, ajuste: "cobrir", borda: { cor: "#FFFFFF", largura: Math.max(4, u * 0.012) } }) : null;
  const logo = linhaDoLogo(p, u * 0.08, u * 0.05);
  const pecas: Peca[] = [];

  /* O caminhão gigante e apagado, saindo pela borda (só na faixa larga). */
  const sombraDoCaminhao = iconeEm("caminhao", 0, 0, 10, "#FFFFFF", { opacidade: 0.1, espessura: 1.2, rot: -8 });

  if (faixa) {
    const lado = H * 0.82;
    const coluna = W * 0.5;
    const ladoDoSelo = u * 0.2;
    empilhar([...logo, { peca: titulo, w: coluna, h: u * 0.36, depois: u * 0.04 }, { peca: apoio, w: coluna, h: u * 0.07, depois: u * 0.04 }, { peca: valor, w: u * 0.42, h: u * 0.14, fixa: true }], m + ladoDoSelo + u * 0.06, coluna, m, H - m, false);
    Object.assign(selo, { x: m, y: (H - ladoDoSelo) / 2, w: ladoDoSelo, h: ladoDoSelo });
    Object.assign(sombraDoCaminhao, { x: W - H * 1.25, y: -H * 0.1, w: H * 1.3, h: H * 1.3 });
    if (foto) Object.assign(foto, { x: W - m - lado, y: (H - lado) / 2, w: lado, h: lado });
  } else {
    const ladoDoSelo = u * 0.26;
    const ladoDaFoto = Math.min(W * 0.58, H * 0.3);
    const linhas: Linha[] = [...logo];
    const marcador = texto({ nome: "Lugar do selo", texto: "", tamanho: 10 });
    linhas.push({ peca: marcador, w: ladoDoSelo, h: ladoDoSelo, depois: u * 0.06, fixa: true });
    linhas.push({ peca: titulo, w: W - m * 2, h: u * 0.42, depois: u * 0.04 }, { peca: apoio, w: W - m * 2, h: u * 0.07, depois: u * 0.04 }, { peca: valor, w: u * 0.46, h: u * 0.15, depois: foto ? u * 0.06 : 0, fixa: true });
    if (foto) linhas.push({ peca: foto, w: ladoDaFoto, h: ladoDaFoto, fixa: true });
    empilhar(linhas, m, W - m * 2, m, H - m * 1.6, true);
    Object.assign(selo, { x: marcador.x, y: marcador.y, w: marcador.w, h: marcador.h });
    sombraDoCaminhao.oculta = true;
  }
  const dentro = selo.w * 0.56;
  Object.assign(caminhao, { x: selo.x + (selo.w - dentro) / 2, y: selo.y + (selo.h - dentro) / 2, w: dentro, h: dentro });
  /* A onda clara no pé. */
  const onda = forma({ nome: "Onda", forma: "onda", x: 0, y: H - u * 0.14, w: W, h: u * 0.14, cor: "#FFFFFF", opacidade: 0.12 });
  pecas.push(...(sombraDoCaminhao.oculta ? [] : [sombraDoCaminhao]), onda, selo, caminhao);
  if (foto) {
    foto.raio = foto.w * 0.08;
    pecas.push(foto);
  }
  pecas.push(...pecasDoLogo(logo), titulo, apoio, valor);
  return documento(W, H, fundoDoBanner({ cor: base, cor2: fundo2, angulo: 150, textura: "pontos", corDaTextura: "#FFFFFF" }), pecas);
}

/* ================================================================== cupom */

function cupom(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, u, m } = jeito(p);
  const base = corDeFundo(p.cor);
  const outra = misturar(base, "#FF3D7F", 0.5);
  const meio = misturar(base, outra, 0.5);
  const pecas: Peca[] = [];

  const titulo = texto({ nome: "Título", texto: "Um presente pra você", fonte: "sora", peso: 800, tamanho: u * (faixa ? 0.12 : 0.1), linha: 1.02, alinhamento: faixa ? "esquerda" : "centro" });
  const apoio = texto({ nome: "Texto", texto: "Use o cupom na sua primeira compra e economize já.", fonte: "outfit", peso: 500, tamanho: u * 0.042, opacidade: 0.9, linha: 1.35, alinhamento: faixa ? "esquerda" : "centro" });
  const logo = linhaDoLogo(p, u * 0.08, u * 0.05);

  /* O ticket: cartão branco, com os dois "cortes" redondos nas laterais. */
  const cw = faixa ? Math.min(W * 0.42, H * 1.35) : W - m * 2;
  const ch = faixa ? H * 0.74 : Math.min(H * 0.42, cw * 0.66);
  let cx: number;
  let cy: number;
  if (faixa) {
    cx = W - m - cw;
    cy = (H - ch) / 2;
    empilhar([...logo, { peca: titulo, w: cx - m * 2.2, h: u * 0.28, depois: u * 0.04 }, { peca: apoio, w: (cx - m * 2.2) * 0.9, h: u * 0.13 }], m * 1.2, cx - m * 2.2, m, H - m, false);
  } else {
    cx = m;
    const sobra = H - ch;
    cy = sobra * 0.52;
    empilhar([...logo, { peca: titulo, w: W - m * 2, h: u * 0.22, depois: u * 0.03 }, { peca: apoio, w: W * 0.8, h: u * 0.12 }], m, W - m * 2, m, cy - u * 0.06, true);
  }
  const cartao = forma({ nome: "Ticket", forma: "retangulo", x: cx, y: cy, w: cw, h: ch, cor: "#FFFFFF", raio: Math.min(cw, ch) * 0.07, sombra: true });
  cartao.sombra = sombraSuave(0.28);
  const corte = ch * 0.2;
  const corteE = forma({ nome: "Corte", forma: "circulo", x: cx - corte / 2, y: cy + ch * 0.62 - corte / 2, w: corte, h: corte, cor: meio });
  const corteD = forma({ nome: "Corte", forma: "circulo", x: cx + cw - corte / 2, y: cy + ch * 0.62 - corte / 2, w: corte, h: corte, cor: meio });
  const pontilhado = forma({ nome: "Linha", forma: "retangulo", x: cx + corte * 0.8, y: cy + ch * 0.62 - 1, w: cw - corte * 1.6, h: Math.max(2, ch * 0.008), cor: base, opacidade: 0.18 });

  const k = Math.min(cw, ch * 1.5);
  const rotulo = texto({ nome: "Rótulo", texto: "CUPOM DE DESCONTO", fonte: "space-grotesk", peso: 700, tamanho: k * 0.036, espaco: 0.32, cor: base, alinhamento: "centro" });
  const desconto = texto({ nome: "Desconto", texto: "10% OFF", html: htmlDoTextoLimpo(`10%${trecho("font-size:" + Math.round(k * 0.08) + "px", " OFF")}`), fonte: "kanit", peso: 900, tamanho: k * 0.17, linha: 1, cor: "#141414", alinhamento: "centro" });
  const codigo = texto({ nome: "Código", texto: "BEMVINDO10", fonte: "space-grotesk", peso: 700, tamanho: k * 0.052, espaco: 0.14, cor: base, alinhamento: "centro", fundo: { forma: "retangulo", cor: misturar(base, "#FFFFFF", 0.88), raio: k * 0.02 } });
  const nota = texto({ nome: "Detalhe", texto: "válido até 30/11 · use no carrinho", fonte: "outfit", peso: 500, tamanho: k * 0.03, cor: "#71717A", alinhamento: "centro" });
  empilhar([{ peca: rotulo, w: cw * 0.9, h: k * 0.06, depois: k * 0.01 }, { peca: desconto, w: cw * 0.9, h: k * 0.2 }], cx, cw, cy + ch * 0.06, cy + ch * 0.58, true);
  empilhar([{ peca: codigo, w: cw * 0.62, h: k * 0.1, depois: k * 0.02, fixa: true }, { peca: nota, w: cw * 0.9, h: k * 0.045 }], cx, cw, cy + ch * 0.66, cy + ch * 0.96, true);

  const presente = iconeEm("presente", cx + cw - k * 0.13, cy - k * 0.07, k * 0.16, "#FFFFFF", { rot: 12, espessura: 1.6 });
  pecas.push(cartao, corteE, corteD, pontilhado, ...pecasDoLogo(logo), titulo, apoio, rotulo, desconto, codigo, nota, presente);
  return documento(W, H, fundoDoBanner({ cor: base, cor2: outra, angulo: 135, textura: "raios", corDaTextura: "#FFFFFF" }), pecas);
}

/* ============================================================== depoimento */

function depoimento(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, u, m } = jeito(p);
  const fundo = "#FAFAF9";
  const acento = destaqueSobreClaro(p.cor);
  const alinhar = faixa ? "esquerda" : "centro";
  const pecas: Peca[] = [];

  const aspas = texto({ nome: "Aspas", texto: "“", fonte: "dm-serif-display", peso: 400, tamanho: u * 0.9, linha: 0.8, cor: acento, opacidade: 0.14, alinhamento: "esquerda" });
  const frase = texto({ nome: "Depoimento", texto: "Atendimento impecável e o pedido chegou antes do prazo. Já virei cliente fiel!", html: htmlDoTextoLimpo(`Atendimento ${trecho(`color:${acento}`, "impecável")} e o pedido chegou antes do prazo. Já virei cliente fiel!`), fonte: "sora", peso: 700, tamanho: u * (faixa ? 0.075 : 0.085), linha: 1.28, cor: "#18181B", alinhamento: alinhar });
  const nome = texto({ nome: "Nome", texto: "Mariana Souza", fonte: "outfit", peso: 700, tamanho: u * 0.042, cor: "#18181B", alinhamento: alinhar });
  const cidade = texto({ nome: "Cidade", texto: "cliente desde 2024 · Recife, PE", fonte: "outfit", peso: 400, tamanho: u * 0.032, cor: "#71717A", alinhamento: alinhar });
  const estrelas = texto({ nome: "Lugar das estrelas", texto: "", tamanho: 10 });
  const logo = linhaDoLogo(p, u * 0.08, u * 0.06);
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, ajuste: "cobrir", circulo: true, sombra: true, borda: { cor: "#FFFFFF", largura: Math.max(4, u * 0.012) } }) : null;

  const larguraDasEstrelas = u * 0.36;
  if (faixa) {
    const lado = H * 0.72;
    const coluna = W - m * 2.4 - (foto ? lado + W * 0.06 : 0);
    empilhar([...logo, { peca: estrelas, w: larguraDasEstrelas, h: u * 0.07, depois: u * 0.05, fixa: true }, { peca: frase, w: coluna, h: u * 0.42, depois: u * 0.06 }, { peca: nome, w: coluna, h: u * 0.06, depois: u * 0.01 }, { peca: cidade, w: coluna, h: u * 0.05 }], m * 1.4, coluna, m, H - m, false);
    if (foto) Object.assign(foto, { x: W - m * 1.2 - lado, y: (H - lado) / 2, w: lado, h: lado });
    Object.assign(aspas, { x: m * 0.4, y: -u * 0.12, w: u * 0.7, h: u * 0.9 });
  } else {
    const ladoDaFoto = Math.min(W * 0.3, H * 0.2);
    const linhas: Linha[] = [...logo, { peca: estrelas, w: larguraDasEstrelas, h: u * 0.07, depois: u * 0.06, fixa: true }, { peca: frase, w: W - m * 2.4, h: u * 0.4, depois: u * 0.07 }];
    if (foto) linhas.push({ peca: foto, w: ladoDaFoto, h: ladoDaFoto, depois: u * 0.04, fixa: true });
    linhas.push({ peca: nome, w: W - m * 2, h: u * 0.06, depois: u * 0.01 }, { peca: cidade, w: W - m * 2, h: u * 0.05 });
    empilhar(linhas, m, W - m * 2, m * 1.4, H - m * 1.4, true);
    Object.assign(aspas, { x: m * 0.6, y: m * 0.2, w: u * 0.7, h: u * 0.9 });
  }
  /* Cinco estrelas cheias no lugar marcado. */
  const passo = estrelas.w / 5;
  for (let i = 0; i < 5; i += 1) pecas.push(iconeEm("estrela", estrelas.x + passo * i + passo * 0.08, estrelas.y, passo * 0.84, "#F59E0B", { preenchido: true, espessura: 1 }));
  pecas.unshift(aspas);
  pecas.push(forma({ nome: "Barra", forma: "retangulo", x: 0, y: 0, w: faixa ? u * 0.025 : W, h: faixa ? H : u * 0.025, cor: acento }));
  if (foto) pecas.push(foto);
  pecas.push(...pecasDoLogo(logo), frase, nome, cidade);
  return documento(W, H, fundoDoBanner({ cor: fundo, textura: "nenhuma" }), pecas);
}

/* ============================================================== comunicado */

function comunicado(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, u, m } = jeito(p);
  const acento = destaqueSobreClaro(p.cor);
  const tinta = "#111827";
  const alinhar = faixa ? "esquerda" : "centro";
  const pecas: Peca[] = [];

  const rotulo = texto({ nome: "Rótulo", texto: "AVISO IMPORTANTE", fonte: "space-grotesk", peso: 700, tamanho: u * 0.034, espaco: 0.36, cor: acento, alinhamento: alinhar });
  const titulo = texto({ nome: "Título", texto: "Horário especial de fim de ano", html: htmlDoTextoLimpo(`Horário especial de ${trecho(`color:${acento}`, "fim de ano")}`), fonte: "sora", peso: 800, tamanho: u * (faixa ? 0.11 : 0.12), linha: 1.08, espaco: -0.02, cor: tinta, alinhamento: alinhar });
  const corpo = texto({ nome: "Texto", texto: "Nos dias 24 e 31 atendemos das 8h às 12h. Pedidos feitos no site seguem normalmente.", fonte: "outfit", peso: 400, tamanho: u * 0.042, linha: 1.45, cor: "#4B5563", alinhamento: alinhar });
  const dia = texto({ nome: "Datas", texto: "24 e 31 de dezembro", fonte: "outfit", peso: 700, tamanho: u * 0.04, cor: tinta, alinhamento: "esquerda" });
  const hora = texto({ nome: "Horário", texto: "das 8h às 12h", fonte: "outfit", peso: 700, tamanho: u * 0.04, cor: tinta, alinhamento: "esquerda" });
  const lugarDoIcone = texto({ nome: "Lugar do ícone", texto: "", tamanho: 10 });
  const logo = linhaDoLogo(p, u * 0.09, u * 0.06);

  const coluna = faixa ? W * 0.56 : W - m * 2;
  const x0 = faixa ? m * 1.3 : m;
  empilhar(
    [...logo, { peca: lugarDoIcone, w: u * 0.17, h: u * 0.17, depois: u * 0.05, fixa: true }, { peca: rotulo, w: coluna, h: u * 0.055, depois: u * 0.025 }, { peca: titulo, w: coluna, h: u * 0.32, depois: u * 0.04 }, { peca: corpo, w: coluna * 0.92, h: u * 0.2 }],
    x0,
    coluna,
    m + u * 0.04,
    faixa ? H - m : H - m - u * 0.36,
    !faixa,
  );
  const circulo = forma({ nome: "Fundo do ícone", forma: "circulo", x: lugarDoIcone.x, y: lugarDoIcone.y, w: lugarDoIcone.w, h: lugarDoIcone.h, cor: misturar(acento, "#FFFFFF", 0.86) });
  const megafone = iconeEm("megafone", lugarDoIcone.x + lugarDoIcone.w * 0.22, lugarDoIcone.y + lugarDoIcone.h * 0.22, lugarDoIcone.w * 0.56, acento, { espessura: 1.8 });

  /* Os dois "cartões" de informação (data e hora), com ícone. */
  const cartaoW = faixa ? W - x0 - coluna - m * 2.2 : (W - m * 2 - u * 0.04) / 2;
  const cartaoH = u * 0.2;
  const infos = faixa
    ? [
        { x: W - m - cartaoW, y: H / 2 - cartaoH - u * 0.02, icone: "calendario", rotulo: dia },
        { x: W - m - cartaoW, y: H / 2 + u * 0.02, icone: "relogio", rotulo: hora },
      ]
    : [
        { x: m, y: H - m - cartaoH, icone: "calendario", rotulo: dia },
        { x: m + cartaoW + u * 0.04, y: H - m - cartaoH, icone: "relogio", rotulo: hora },
      ];
  for (const info of infos) {
    pecas.push(forma({ nome: "Cartão", forma: "retangulo", x: info.x, y: info.y, w: cartaoW, h: cartaoH, cor: "#FFFFFF", raio: u * 0.03, sombra: true }));
    const l = cartaoH * 0.42;
    pecas.push(iconeEm(info.icone, info.x + cartaoH * 0.29, info.y + (cartaoH - l) / 2, l, acento, { espessura: 1.8 }));
    Object.assign(info.rotulo, { x: info.x + cartaoH * 0.29 + l + u * 0.03, y: info.y, w: cartaoW - (cartaoH * 0.29 + l + u * 0.05), h: cartaoH, tamanho: Math.min(info.rotulo.tamanho, cartaoH * 0.24) });
  }
  pecas.unshift(forma({ nome: "Barra", forma: "retangulo", x: 0, y: 0, w: W, h: u * 0.035, cor: acento }));
  pecas.push(circulo, megafone, ...pecasDoLogo(logo), rotulo, titulo, corpo, dia, hora);
  return documento(W, H, fundoDoBanner({ cor: "#F3F4F6", textura: "nenhuma" }), pecas);
}

/* =================================================================== neon */

function neon(p: PedidoDoModelo): DocumentoDoBanner {
  const { W, H, faixa, u, m } = jeito(p);
  const rosa = "#FF2D87";
  const ciano = "#22D3EE";
  const pecas: Peca[] = [];

  const brilho = (cor: string, forca: number) => ({ cor, x: 0, y: 0, desfoque: u * forca, opacidade: 1 });
  const titulo = texto({ nome: "Título", texto: "SEXTOU", fonte: "monoton", peso: 400, tamanho: u * (faixa ? 0.26 : 0.24), linha: 1, cor: "#FFE4F3", alinhamento: "centro" });
  titulo.sombra = brilho(rosa, 0.06);
  const sub = texto({ nome: "Subtítulo", texto: "com 20% off em tudo", fonte: "dancing-script", peso: 700, tamanho: u * 0.1, cor: "#CFFAFE", alinhamento: "centro" });
  sub.sombra = brilho(ciano, 0.04);
  const botao = texto({ nome: "Botão", texto: "SÓ ATÉ MEIA-NOITE", fonte: "space-grotesk", peso: 700, tamanho: u * 0.04, espaco: 0.3, cor: ciano, alinhamento: "centro" });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, ajuste: "cobrir", circulo: true, sombra: false, borda: { cor: "#FF8BC0", largura: Math.max(3, u * 0.008) } }) : null;
  const logo = linhaDoLogo(p, u * 0.08, u * 0.05);

  const moldura = forma({ nome: "Moldura neon", forma: "retangulo", x: m * 0.6, y: m * 0.6, w: W - m * 1.2, h: H - m * 1.2, cor: rosa, raio: u * 0.06, borda: { cor: "#FF8BC0", largura: Math.max(3, u * 0.008) } });
  moldura.pintura = { tipo: "nenhuma", cor: rosa, cor2: rosa, angulo: 0 };
  moldura.sombra = { cor: rosa, x: 0, y: 0, desfoque: u * 0.05, opacidade: 1 };

  if (faixa && foto) {
    const lado = H * 0.7;
    const coluna = W - m * 3 - lado;
    empilhar([...logo, { peca: titulo, w: coluna, h: u * 0.3, depois: u * 0.02 }, { peca: sub, w: coluna, h: u * 0.14, depois: u * 0.05 }, { peca: botao, w: coluna, h: u * 0.07 }], m * 1.4, coluna, m, H - m, true);
    Object.assign(foto, { x: W - m * 1.5 - lado, y: (H - lado) / 2, w: lado, h: lado });
  } else {
    const ladoDaFoto = Math.min(W * 0.5, H * 0.3);
    const linhas: Linha[] = [...logo, { peca: titulo, w: W - m * 2.4, h: u * 0.3, depois: u * 0.03 }, { peca: sub, w: W - m * 2.4, h: u * 0.14, depois: u * 0.06 }];
    if (foto) linhas.push({ peca: foto, w: ladoDaFoto, h: ladoDaFoto, depois: u * 0.06, fixa: true });
    linhas.push({ peca: botao, w: W - m * 2.4, h: u * 0.07 });
    empilhar(linhas, m * 1.2, W - m * 2.4, m * 1.4, H - m * 1.4, true);
  }
  pecas.push(moldura);
  if (foto) {
    foto.sombra = { cor: "#FF2D87", x: 0, y: 0, desfoque: u * 0.05, opacidade: 0.9 };
    pecas.push(forma({ nome: "Luz", forma: "circulo", ...emVolta(foto, 1.6), cor: "#3B0764" }));
    (pecas.at(-1) as { pintura: unknown }).pintura = { tipo: "radial", cor: "#6D28D9", cor2: "#0B0518", angulo: 0 };
    pecas.push(foto);
  }
  pecas.push(...pecasDoLogo(logo), titulo, sub, botao);
  return documento(W, H, fundoDoBanner({ cor: "#0B0518", cor2: "#1A0B33", angulo: 160, textura: "grao" }), pecas);
}

export const MODELOS_PRO = [
  { chave: "black-friday", nome: "Black Friday", descricao: "Preto e amarelo, letra vazada", montar: blackFriday },
  { chave: "colecao", nome: "Coleção", descricao: "Editorial, creme e serifa", montar: colecao },
  { chave: "frete", nome: "Frete grátis", descricao: "Selo com caminhão e valor", montar: freteGratis },
  { chave: "cupom", nome: "Cupom", descricao: "Ticket com código", montar: cupom },
  { chave: "depoimento", nome: "Depoimento", descricao: "Cinco estrelas e a frase", montar: depoimento },
  { chave: "comunicado", nome: "Comunicado", descricao: "Aviso, data e horário", montar: comunicado },
  { chave: "neon", nome: "Neon", descricao: "Noite, brilho rosa e ciano", montar: neon },
];
