const EditorDeBlocos = (() => {     // Parâmetro para configurar a indentação dos blocos agrupados     const INDENTATION_SIZE_PX = 50;     // Cache global para dimensões de imagem, para evitar recarregar o new Image()     const DADOS_IMAGEM_CACHE = new Map();     // Contexto compartilhado: contém estado, elementos DOM e configurações     const context = {         config: {},         editorId: null,         controleId: null,         linhasDoEditor: [],         xBlocks: [],         proximoIdGlobal: 0,         dadosArrastados: null,         elementoArrastadoOriginalDOM: null,         ultimoTextoProcessado: '',         blocosDisponiveis: [],         containerPrincipalEl: null,         paletaBlocosEl: null,         painelEditorWrapperEl: null,         painelEditorEl: null,         xBlocksContainerEl: null,         painelParamsEl: null,         paramsTituloEl: null,         paramsCamposEl: null,         paramsOkBtn: null,         paramsCancelarBtn: null,         hamburgerBtn: null,         overlayEl: null,         callbacks: {},         listaImagens: null,         insertionMarkerEl: null,         dropOccurredInEditor: false     };     function substituirCaracteresEspeciais(texto) {         if (typeof texto !== 'string') return texto;         return texto             .replace(/,/g, '£1')             .replace(/"/g, '£2')             .replace(/'/g, '£3')             .replace(/\[/g, '£4')             .replace(/\]/g, '£5')             .replace(/\{/g, '£6')             .replace(/\}/g, '£7')             .replace(/\~/g, '£8')             .replace(/\r\n|\r|\n/g, '
');     } // =============================== INÍCIO DO NOVO BLOCO DE CÓDIGO ===============================     /**      * Garante que uma cor hexadecimal seja escura o suficiente para ser visível em um fundo branco.      * Se a cor for muito clara, ela é escurecida na mesma matiz para um limite de visibilidade.      * @param {string} hex - A cor no formato #RRGGBB.      * @returns {string} - A cor original ou a versão escurecida.      */     function ensureColorIsVisible(hex) {         const LUMINANCE_LIMIT = 0.85; // Limite de luminosidade (0=preto, 1=branco). 0.85 é um bom teto.         if (!hex || typeof hex !== 'string' || !hex.startsWith('#')) return hex;         // Funções auxiliares de conversão de cor         const hexToRgb = (h) => {             let r = 0, g = 0, b = 0;             if (h.length == 4) {                 r = "0x" + h[1] + h[1]; g = "0x" + h[2] + h[2]; b = "0x" + h[3] + h[3];             } else if (h.length == 7) {                 r = "0x" + h[1] + h[2]; g = "0x" + h[3] + h[4]; b = "0x" + h[5] + h[6];             }             return { r: +r, g: +g, b: +b };         };         const rgbToHsl = (r, g, b) => {             r /= 255; g /= 255; b /= 255;             let max = Math.max(r, g, b), min = Math.min(r, g, b);             let h = 0, s, l = (max + min) / 2;             if (max == min) {                 h = s = 0;             } else {                 let d = max - min;                 s = l > 0.5 ? d / (2 - max - min) : d / (max + min);                 switch (max) {                     case r: h = (g - b) / d + (g < b ? 6 : 0); break;                     case g: h = (b - r) / d + 2; break;                     case b: h = (r - g) / d + 4; break;                 }                 h /= 6;             }             return { h, s, l };         };         const hslToRgb = (h, s, l) => {             let r, g, b;             if (s == 0) {                 r = g = b = l;             } else {                 const hue2rgb = (p, q, t) => {                     if (t < 0) t += 1; if (t > 1) t -= 1;                     if (t < 1 / 6) return p + (q - p) * 6 * t;                     if (t < 1 / 2) return q;                     if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;                     return p;                 };                 let q = l < 0.5 ? l * (1 + s) : l + s - l * s;                 let p = 2 * l - q;                 r = hue2rgb(p, q, h + 1 / 3);                 g = hue2rgb(p, q, h);                 b = hue2rgb(p, q, h - 1 / 3);             }             return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };         };         const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => {             const hex = x.toString(16);             return hex.length === 1 ? '0' + hex : hex;         }).join('');         try {             const rgb = hexToRgb(hex);             const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);             if (hsl.l > LUMINANCE_LIMIT) {                 hsl.l = LUMINANCE_LIMIT; // Limita a luminosidade                 const newRgb = hslToRgb(hsl.h, hsl.s, hsl.l);                 return rgbToHex(newRgb.r, newRgb.g, newRgb.b);             }             return hex; // Retorna a cor original se não for muito clara         } catch(e) {             return hex; // Em caso de erro, retorna a cor original         }     }     // ================================ FIM DO NOVO BLOCO DE CÓDIGO ================================= function parsearTextoComEstilos(txt, corPadrao) {     const partes = [];     // Regex único e mais robusto para capturar os dois casos (com e sem cor)     const regex = /\/\*(\[(#[a-fA-F0-9]{6})\])?(.*?)\*\//g;     let ultimoIndex = 0,         match;     while ((match = regex.exec(txt)) !== null) {         // Adiciona o texto normal que veio ANTES da tag de estilo         if (match.index > ultimoIndex) {             partes.push({                 text: txt.substring(ultimoIndex, match.index),                 bold: false,                 color: corPadrao             });         }         // Processa a tag de estilo encontrada         let corDaParte = ensureColorIsVisible(match[2] || corPadrao);         partes.push({             text: match[3], // Apenas o conteúdo             bold: true,             color: corDaParte         });         ultimoIndex = regex.lastIndex; // Atualiza o índice para depois da tag     }     // Adiciona qualquer texto normal restante no final da linha     if (ultimoIndex < txt.length) {         partes.push({             text: txt.substring(ultimoIndex),             bold: false,             color: corPadrao         });     }     return partes; }     function reverterCaracteresEspeciais(texto) {         if (typeof texto !== 'string') return texto;         return texto             .replace(/
/g, '\n')             .replace(/£1/g, ',')             .replace(/£2/g, '"')             .replace(/£3/g, "'")             .replace(/£4/g, '[')             .replace(/£5/g, ']')             .replace(/£6/g, '{')             .replace(/£7/g, '}')             .replace(/£8/g, '~');     } function getValorCampoNormalizado(valores, nomeDoCampoDefinido) {         if (!valores || typeof nomeDoCampoDefinido !== 'string') {             return undefined;         }         if (Object.prototype.hasOwnProperty.call(valores, nomeDoCampoDefinido)) {             return valores[nomeDoCampoDefinido];         }         const nomeBase = nomeDoCampoDefinido.replace(/<\d+>$/, '');         if (nomeBase !== nomeDoCampoDefinido) {             if (Object.prototype.hasOwnProperty.call(valores, nomeBase)) {                 return valores[nomeBase];             }         }         return undefined;     }     function parseBlockName(nomeCompleto) {         if (typeof nomeCompleto !== 'string') {             return {                 displayName: '',                 tagName: ''             };         }         const nameRegex = /^(.*?)\[(.*?)\]$/;         const match = nomeCompleto.match(nameRegex);         if (match && match[1] && match[2]) {             return {                 displayName: match[1].trim(),                 tagName: match[2].trim()             };         } else {             return {                 displayName: nomeCompleto,                 tagName: nomeCompleto             };         }     } function getFinalImageName(blocoObjeto, sufixoBase) {         // Converte o texto do bloco em um nome base, usando hífens (conforme seu padrão de arquivos)         const nomeBaseImagem = String(blocoObjeto.texto).replace(/\s+/g, '-').toLowerCase();                  // Verifica o contexto de renderização (se está dentro de uma coluna 'E')         const dentroDeColunaE = blocoObjeto._renderContext && blocoObjeto._renderContext.dentroDeColunaE;                  // Define o nome padrão do arquivo         let nomeFinal = `${nomeBaseImagem}${sufixoBase}`;         // Se estiver dentro de uma coluna, tenta encontrar a versão com 'c'         if (dentroDeColunaE) {             // Monta o nome com 'c' antes do sufixo (ex: imagem-lc.png ou imagem-lcb.png)             const nomeComC = `${nomeBaseImagem}c${sufixoBase}`;             if (context.listaImagens.has(nomeComC)) {                 nomeFinal = nomeComC; // Se a versão 'c' existir, usa ela             }         }         // Retorna o nome do arquivo final se ele existir na lista, senão retorna null         return context.listaImagens.has(nomeFinal) ? nomeFinal : null;     }          function applyStyles(element, styleObject) {         if (!element || typeof element.style === 'undefined') {             return;         }         for (const property in styleObject) {             if (Object.prototype.hasOwnProperty.call(styleObject, property)) {                 element.style[property] = styleObject[property];             }         }     }     function normalizarString(str) {         if (!str) return '';         return str             .toLowerCase()             .normalize("NFD")             .replace(/[\u0300-\u036f]/g, '');     }     function parseColorString(rawColor, type = 'editor') {         if (typeof rawColor !== 'string') return rawColor;         const colors = rawColor.split('|');         if (colors.length === 2) {             return (type === 'palette' ? colors[1].trim() : colors[0].trim());         }         return colors[0].trim();     }     function getEditorColor(rawColorString) {         return parseColorString(rawColorString, 'editor');     }     function getPaletteColor(rawColorString) {         return parseColorString(rawColorString, 'palette');     }     function gerarIdUnico(prefixo = 'id_') {         return prefixo + context.proximoIdGlobal++;     }     function blocoEstaValido(bloco) {         if (bloco.groupId && bloco.groupIndex > 0) {             const cabecalhoDoGrupo = context.linhasDoEditor                 .flatMap(l => l.blocos || [])                 .find(b => b.groupId === bloco.groupId && b.groupIndex === 0);             if (cabecalhoDoGrupo) {                 return blocoEstaValido(cabecalhoDoGrupo);             }         }         if (!bloco.camposDefinidos || bloco.camposDefinidos.length === 0) {             return true;         }         if (!bloco.valoresCampos) {             return bloco.camposDefinidos.every(campoDef =>                 campoDef.nome.startsWith('~') || campoDef.nome.includes('+')             );         }         return bloco.camposDefinidos.every(campoDef => {             if (campoDef.nome.startsWith('~') || campoDef.nome.includes('+') || campoDef.nome.includes('&')) {                 return true;             }             // AJUSTE CIRÚRGICO             const valor = getValorCampoNormalizado(bloco.valoresCampos, campoDef.nome);             return valor !== undefined && valor !== null && String(valor).trim() !== '';         });     }     function gerarCodigoPosicao(bloco, contexto = {}) {         const tipoBloco = bloco.tipo.charAt(0);         let posHorizontal = 'C';         let posVertical = '0';         if (contexto.emLinhaP) {             posHorizontal = contexto.ladoSlot === 'esquerda' ? 'E' : 'D';         } else if (contexto.emSlotT) {             posHorizontal = contexto.posicaoSlotT === 'inicio' ? 'E' : 'D';             posVertical = String(contexto.indiceLinhaT + 1);         }         let codigoBase = `${tipoBloco}${posHorizontal}${posVertical}`;         if ((bloco.tipo.startsWith('E') || bloco.tipo.startsWith('C')) && bloco.groupIndex === 0) {             codigoBase += bloco.isCollapsed ? 'C' : 'O';         }         return codigoBase;     }     function gerarStringParametros(bloco, codigoPosicao, parametrosOverride = null) {         let parametros = [];         if (parametrosOverride) {             parametros = [...parametrosOverride];         } else {             if (bloco.camposDefinidos && bloco.camposDefinidos.length > 0) {                 const valores = bloco.valoresCampos || {};                 parametros = bloco.camposDefinidos.map(campoDef => {                     // AJUSTE CIRÚRGICO                     const valorAtual = getValorCampoNormalizado(valores, campoDef.nome);                     const valorSeguro = (valorAtual === null || valorAtual === undefined) ? '' : valorAtual;                     return String(valorSeguro).replace(/,/g, '|');                 });             }         }         if (codigoPosicao) {             parametros.push(codigoPosicao);         }         if (parametros.length === 0) return "";         let paramStr = parametros.join(',');         if (bloco.tipo.startsWith('E') && parametros.every(p => p === '') && parametros.length > 0 && !codigoPosicao) {             paramStr = ','.repeat(parametros.length);         } else if (bloco.tipo.startsWith('E') && parametros.length === 1 && paramStr === '' && !codigoPosicao) {             paramStr = ',';         }         return ":" + paramStr;     }    function atualizarControle() {         if (!context.controleId) return;         const controlador = document.getElementById(context.controleId);         if (!controlador) return;         let textoSaida = '';         const gerarTag = (bloco, contexto) => {             const {                 tagName             } = parseBlockName(bloco.nome);             const nomeBase = normalizarString(tagName);             const codigoPosicao = gerarCodigoPosicao(bloco, contexto);             const stringParams = gerarStringParametros(bloco, codigoPosicao);             return `{${nomeBase}${stringParams}}`;         };         if (context.xBlocks.length > 0) {             textoSaida += context.xBlocks.map(b => gerarTag(b, {})).join(' ') + '\n';         }         context.linhasDoEditor.forEach(linha => {             let linhaTexto = '';             if (linha.tipoLinhaOrigem === 'S') {                 linhaTexto = '

 

';             } else if (linha.tipoLinhaOrigem === 'O') {                 linhaTexto = "
";             } else if (linha.tipoLinhaOrigem === 'U') {                 linhaTexto = "
 
";             } else if (linha.tipoLinhaOrigem === 'R') {                 linhaTexto = "
 
";             } else if (linha.tipoLinhaOrigem === 'P' && linha.slots) {                 const blocosEsquerda = (linha.slots.esquerda || []).map(b => gerarTag(b, {                     emLinhaP: true,                     ladoSlot: 'esquerda'                 }));                 const blocosDireita = (linha.slots.direita || []).slice().reverse().map(b => gerarTag(b, {                     emLinhaP: true,                     ladoSlot: 'direita'                 }));                 const blocosConcatenados = [...blocosEsquerda, ...blocosDireita].join('');                 if (blocosConcatenados) {                     linhaTexto = blocosConcatenados + "\n
 
";                 }             } else if (linha.blocos && linha.blocos.length > 0) {                 const bloco = linha.blocos[0];                 const {                     tagName                 } = parseBlockName(bloco.nome);                 const nomeBase = normalizarString(tagName);                 if (bloco.tipo.startsWith('E') && bloco.groupId) {                     const index = bloco.groupIndex;                     const groupSize = bloco.groupSize;                     let markerText = '';                     if (groupSize === 3) {                         if (index === 0) markerText = '[esquerda inicio]';                         else if (index === 1) markerText = '[esquerda fim][direita inicio]';                         else if (index === 2) markerText = '[direita fim]';                     } else if (groupSize === 4) {                         if (index === 0) markerText = '[esquerda inicio]';                         else if (index === 1) markerText = '[esquerda fim][meio inicio]';                         else if (index === 2) markerText = '[meio fim][direita inicio]';                         else if (index === 3) markerText = '[direita fim]';                     }                     if (index === 0) {                         linhaTexto = `${gerarTag(bloco, {})}${markerText}`;                     } else {                         linhaTexto = markerText;                     }                 } else if (bloco.tipo.startsWith('C') && bloco.groupId) {                     const index = bloco.groupIndex;                     const {                         tagName: cTagName                     } = parseBlockName(bloco.nome);                     const nomeBaseC = normalizarString(cTagName);                     if (index === 0) {                         const cabecalhoGrupo = context.linhasDoEditor                             .flatMap(l => l.blocos)                             .find(b => b.groupId === bloco.groupId && b.groupIndex === 0);                         const nomeComEstado = (cabecalhoGrupo && !cabecalhoGrupo.isCollapsed) ? `${nomeBaseC}!` : nomeBaseC;                         linhaTexto = `[${nomeComEstado} inicio]`;                     } else if (index === 1) {                         linhaTexto = `[${nomeBaseC} fim]`;                     }                 } else if (bloco.tipo.startsWith('T')) {                     const blocoT = linha.blocos[0];                     const campoPlus = blocoT.camposDefinidos && blocoT.camposDefinidos.find(c => c.nome.includes('+'));                     const gerarTagsInternas = (indiceLinha, lado) => {                         const blocos = (blocoT.linhasInternas && blocoT.linhasInternas[indiceLinha] && blocoT.linhasInternas[indiceLinha][lado]) ? blocoT.linhasInternas[indiceLinha][lado] : [];                         return blocos.map(b => gerarTag(b, {                             emSlotT: true,                             indiceLinhaT: indiceLinha,                             posicaoSlotT: lado                         })).join('');                     };                     const findNearestSpace = (text, idealPosition) => {                         const spaceAfter = text.indexOf(' ', idealPosition);                         const spaceBefore = text.lastIndexOf(' ', idealPosition - 1);                         let breakPoint = -1;                         if (spaceBefore !== -1 && spaceAfter !== -1) {                             breakPoint = (idealPosition - spaceBefore < spaceAfter - idealPosition) ? spaceBefore : spaceAfter;                         } else if (spaceBefore !== -1) {                             breakPoint = spaceBefore;                         } else if (spaceAfter !== -1) {                             breakPoint = spaceAfter;                         }                         return breakPoint;                     };                     if (campoPlus) {                         // AJUSTE CIRÚRGICO                         let conteudoProcessado = String(getValorCampoNormalizado(blocoT.valoresCampos, campoPlus.nome) || '');                         const blocosPrimeiraLinha = gerarTagsInternas(0, 'inicio') + gerarTagsInternas(0, 'fim');                         const blocosLinhaMeio = gerarTagsInternas(1, 'inicio') + gerarTagsInternas(1, 'fim');                         const blocosTerceiraLinha = gerarTagsInternas(2, 'inicio') + gerarTagsInternas(2, 'fim');                         const campoStar = blocoT.camposDefinidos && blocoT.camposDefinidos.find(c => c.nome.includes('*') && !c.nome.includes('**'));                         const campoStarStar = blocoT.camposDefinidos && blocoT.camposDefinidos.find(c => c.nome.includes('**'));                         if (blocosTerceiraLinha && campoStarStar) {                             // AJUSTE CIRÚRGICO                             const porcentagemSplit = parseInt(getValorCampoNormalizado(blocoT.valoresCampos, campoStarStar.nome), 10);                             if (!isNaN(porcentagemSplit) && porcentagemSplit > 0 && porcentagemSplit < 100) {                                 const pontoExato = Math.floor(conteudoProcessado.length * (1 - (porcentagemSplit / 100)));                                 const pontoQuebraFinal = findNearestSpace(conteudoProcessado, pontoExato);                                 if (pontoQuebraFinal !== -1) {                                     const parte1 = conteudoProcessado.substring(0, pontoQuebraFinal);                                     const parte2 = conteudoProcessado.substring(pontoQuebraFinal);                                     conteudoProcessado = parte1 + blocosTerceiraLinha + parte2;                                 } else {                                     conteudoProcessado = conteudoProcessado + blocosTerceiraLinha;                                 }                             } else {                                 conteudoProcessado = conteudoProcessado + blocosTerceiraLinha;                             }                         } else {                             conteudoProcessado = conteudoProcessado + blocosTerceiraLinha;                         }                         if (blocosLinhaMeio && campoStar) {                             // AJUSTE CIRÚRGICO                             const porcentagemSplit = parseInt(getValorCampoNormalizado(blocoT.valoresCampos, campoStar.nome), 10);                             if (!isNaN(porcentagemSplit) && porcentagemSplit > 0 && porcentagemSplit < 100) {                                 const pontoExato = Math.floor(conteudoProcessado.length * (porcentagemSplit / 100));                                 const pontoQuebraFinal = findNearestSpace(conteudoProcessado, pontoExato);                                 if (pontoQuebraFinal !== -1) {                                     const parte1 = conteudoProcessado.substring(0, pontoQuebraFinal);                                     const parte2 = conteudoProcessado.substring(pontoQuebraFinal);                                     conteudoProcessado = parte1 + blocosLinhaMeio + parte2;                                 } else {                                     conteudoProcessado = blocosLinhaMeio + ' ' + conteudoProcessado;                                 }                             } else {                                 conteudoProcessado = blocosLinhaMeio + ' ' + conteudoProcessado;                             }                         }                         const conteudoFinalNaoTratado = blocosPrimeiraLinha + conteudoProcessado;                         const conteudoFinalTratado = substituirCaracteresEspeciais(conteudoFinalNaoTratado);                         const paramsFinais = [];                         blocoT.camposDefinidos.forEach(campoDef => {                             if (campoDef.nome === campoPlus.nome) {                                 paramsFinais.push(conteudoFinalTratado);                             } else {                                 // AJUSTE CIRÚRGICO                                 const valor = getValorCampoNormalizado(blocoT.valoresCampos, campoDef.nome) || '';                                 paramsFinais.push(String(valor).replace(/,/g, '|'));                             }                         });                         const codigoPosicaoT = gerarCodigoPosicao(blocoT, {});                         const stringParamsT = gerarStringParametros(blocoT, codigoPosicaoT, paramsFinais);                         linhaTexto = `{${normalizarString(tagName)}${stringParamsT}}`;                     } else {                         linhaTexto = gerarTag(blocoT, {});                     }                 } else {                     linhaTexto = linha.blocos.map(b => gerarTag(b, {})).join('');                 }             }             if (linhaTexto.trim() !== '') {                 textoSaida += linhaTexto.trim() + '\n';             }         });         const textoFormatado = textoSaida.trim();         context.ultimoTextoProcessado = textoFormatado;         controlador.value = textoFormatado;     }     function encontrarLimitesDaAreaNaoTransparente(imageData) {         const {             width,             height,             data         } = imageData;         let minX = width,             minY = height,             maxX = -1,             maxY = -1;         for (let y = 0; y < height; y++) {             for (let x = 0; x < width; x++) {                 const alpha = data[(y * width + x) * 4 + 3];                 if (alpha > 0) {                     if (x < minX) minX = x;                     if (x > maxX) maxX = x;                     if (y < minY) minY = y;                     if (y > maxY) maxY = y;                 }             }         }         if (maxX === -1) {             return {                 x: 0,                 y: 0,                 width: width,                 height: height             };         }         return {             x: minX,             y: minY,             width: maxX - minX + 1,             height: maxY - minY + 1         };     }     function ajustarFonteParaCaber(ctx, texto, larguraMaxima, alturaMaxima, fonteBase = 'Arial') {         let fontSize = alturaMaxima; // Começa com um tamanho que preenche a altura útil         ctx.font = `bold ${fontSize}px ${fonteBase}`;         // Reduz o tamanho da fonte até que o texto caiba na largura máxima         while (ctx.measureText(texto).width > larguraMaxima && fontSize > 5) {             fontSize--;             ctx.font = `bold ${fontSize}px ${fonteBase}`;         }         return fontSize;     }      function parseColorToRgb(colorString) {     if (!colorString || typeof colorString !== 'string') return null;     let s = colorString.trim().toLowerCase();          // Suporta o separador customizado '|'     s = s.replace(/\|/g, ',');     // Tenta corresponder a HEX: #RRGGBB ou #RGB     let match = s.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/);     if (match) {         return { r: parseInt(match[1], 16), g: parseInt(match[2], 16), b: parseInt(match[3], 16) };     }     match = s.match(/^#?([a-f\d])([a-f\d])([a-f\d])$/);     if (match) {         return { r: parseInt(match[1] + match[1], 16), g: parseInt(match[2] + match[2], 16), b: parseInt(match[3] + match[3], 16) };     }          // Tenta corresponder a RGB ou RGBA: rgb(r, g, b) ou rgba(r, g, b, a)     match = s.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)$/);     if (match) {         return { r: parseInt(match[1]), g: parseInt(match[2]), b: parseInt(match[3]) };     }     // Retorna null se nenhum formato for reconhecido (ex: 'transparent', 'linear-gradient(...)')     return null; } /**  * Analisa uma string de gradiente linear de forma robusta, respeitando parênteses em cores rgba().  * @param {string} gradientString - A string do gradiente (ex: "linear-gradient(90deg, rgba(255,0,0,1) | #00ff00)").  * @param {number} width - A largura da área do gradiente.  * @param {number} height - A altura da área do gradiente.  * @returns {object|null} - Um objeto com os parâmetros do gradiente ou null.  */ function parseGradientString(gradientString, width, height) {     if (!gradientString || typeof gradientString !== 'string' || !gradientString.toLowerCase().startsWith('linear-gradient')) {         return null;     }     try {         const contentRegex = /linear-gradient\((.*)\)/i;         let contentMatch = gradientString.match(contentRegex);         if (!contentMatch || !contentMatch[1]) return null;                  let content = contentMatch[1].trim().replace(/\|/g, ',');         const parts = [];         let buffer = '';         let parenLevel = 0;         for (let i = 0; i < content.length; i++) {             const char = content[i];             if (char === '(') parenLevel++;             if (char === ')') parenLevel--;                          if (char === ',' && parenLevel === 0) {                 parts.push(buffer.trim());                 buffer = '';             } else {                 buffer += char;             }         }         parts.push(buffer.trim());         if (parts.length < 2) return null;         const firstPart = parts[0];         let colors = [];         let angle = 180; // Padrão CSS 'to bottom'         if (firstPart.includes('deg') || firstPart.includes('to ')) {             colors = parts.slice(1);             if (firstPart.includes('deg')) {                 angle = parseFloat(firstPart) % 360;             } else {                 const direction = firstPart.replace('to', '').trim();                 if (direction.includes('top')) angle = 0;                 if (direction.includes('right')) angle = 90;                 if (direction.includes('left')) angle = 270;                  // 'bottom' já é o padrão             }         } else {             // Se a primeira parte não for ângulo/direção, é uma cor             colors = parts;         }                  if (colors.length < 2) return null;         const colorStops = colors.map((color, index) => ({             stop: index / (colors.length - 1),             color: color.trim()         }));         let x0 = 0, y0 = 0, x1 = 0, y1 = 0;         if (angle === 0) { y0 = height; }      // to top         else if (angle === 90) { x1 = width; } // to right         else if (angle === 180) { y1 = height; } // to bottom         else if (angle === 270) { x0 = width; } // to left         else { // Cálculo para ângulos diagonais              const rad = angle * (Math.PI / 180);              x0 = width * 0.5 * (1 - Math.sin(rad));              y0 = height * 0.5 * (1 + Math.cos(rad));              x1 = width * 0.5 * (1 + Math.sin(rad));              y1 = height * 0.5 * (1 - Math.cos(rad));         }                  return { x0, y0, x1, y1, colorStops };     } catch (e) {         console.error("Erro ao analisar o gradiente:", e);         return null;     } } async function gerarImagemComFundoTingidoETexto(blocoObjeto, texto, alinhamento, corTexto, corFundo, tamanhoFonteParam = null, margemLatParam = null, margemSupParam = null, arredondamentoParam = null) { const nomeArquivoFinal = getFinalImageName(blocoObjeto, 'b.png'); if (!nomeArquivoFinal) { console.warn(`Imagem base para '${blocoObjeto.texto}' não encontrada.`); return null; } const urlBase = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoFinal)}`; try { const imgBase = await new Promise((resolve, reject) => { const i = new Image(); i.crossOrigin = "Anonymous"; i.onload = () => resolve(i); i.onerror = reject; i.src = urlBase; }); const tempCanvas = document.createElement('canvas'); const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); tempCanvas.width = imgBase.width; tempCanvas.height = imgBase.height; tempCtx.drawImage(imgBase, 0, 0); const imageDataParaLimites = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height); const shapeBounds = encontrarLimitesDaAreaNaoTransparente(imageDataParaLimites); tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height); const gradientParams = parseGradientString(corFundo, shapeBounds.width, shapeBounds.height); if (gradientParams) { const gradient = tempCtx.createLinearGradient( shapeBounds.x + gradientParams.x0, shapeBounds.y + gradientParams.y0, shapeBounds.x + gradientParams.x1, shapeBounds.y + gradientParams.y1 ); gradientParams.colorStops.forEach(stopInfo => { gradient.addColorStop(stopInfo.stop, stopInfo.color); }); tempCtx.fillStyle = gradient; tempCtx.fillRect(shapeBounds.x, shapeBounds.y, shapeBounds.width, shapeBounds.height); tempCtx.globalCompositeOperation = 'destination-in'; tempCtx.drawImage(imgBase, 0, 0); tempCtx.globalCompositeOperation = 'source-over'; } else { tempCtx.drawImage(imgBase, 0, 0); const originalImageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height); const data = originalImageData.data; const corFundoRgb = parseColorToRgb(corFundo); if (corFundoRgb) { const { r: rFundo, g: gFundo, b: bFundo } = corFundoRgb; for (let i = 0; i < data.length; i += 4) { if (data[i + 3] > 0) { const luminosidade = data[i] / 255; data[i] = rFundo * luminosidade; data[i + 1] = gFundo * luminosidade; data[i + 2] = bFundo * luminosidade; } } tempCtx.putImageData(originalImageData, 0, 0); } } const limitesIniciais = shapeBounds; if (limitesIniciais.width <= 0 || limitesIniciais.height <= 0) return null; const parteNaoTransparenteCanvas = document.createElement('canvas'); parteNaoTransparenteCanvas.width = limitesIniciais.width; parteNaoTransparenteCanvas.height = limitesIniciais.height; parteNaoTransparenteCanvas.getContext('2d').drawImage( tempCanvas, limitesIniciais.x, limitesIniciais.y, limitesIniciais.width, limitesIniciais.height, 0, 0, limitesIniciais.width, limitesIniciais.height ); const FONTE_FAMILIA = 'Arial'; let textoFinal = texto; // AJUSTE CIRÚRGICO: Multiplicador em total paridade com os textos normais. Fora do slot = 2.0 / Dentro = 3.0 let multiplicador = 2.0; if (blocoObjeto._renderContext && (blocoObjeto._renderContext.dentroDeColunaE || blocoObjeto._renderContext.dentroDeSlotT)) { multiplicador = 4.0; } const mLatBase = (margemLatParam !== null && String(margemLatParam).trim() !== '' && !isNaN(parseFloat(margemLatParam))) ? parseFloat(margemLatParam) : 15; const mSupBase = (margemSupParam !== null && String(margemSupParam).trim() !== '' && !isNaN(parseFloat(margemSupParam))) ? parseFloat(margemSupParam) : 10; const arredondBase = (arredondamentoParam !== null && String(arredondamentoParam).trim() !== '' && !isNaN(parseFloat(arredondamentoParam))) ? parseFloat(arredondamentoParam) : 0; const mLat = mLatBase * multiplicador; const mSup = mSupBase * multiplicador; const radiusClip = arredondBase * multiplicador; let tamanhoFixoPx = null; if (tamanhoFonteParam && !isNaN(parseFloat(tamanhoFonteParam))) { const tamanhoBase = parseFloat(tamanhoFonteParam); tamanhoFixoPx = Math.max(tamanhoBase * multiplicador, 8); } let fontSizeFinal = tamanhoFixoPx ? tamanhoFixoPx : Math.max(10, limitesIniciais.height - (mSup * 2)); const finalCanvas = document.createElement('canvas'); const finalCtx = finalCanvas.getContext('2d'); finalCtx.font = `${fontSizeFinal}px ${FONTE_FAMILIA}`; const larguraTextoIdeal = finalCtx.measureText(textoFinal).width; let larguraDoElementoNoCanvas = larguraTextoIdeal + (mLat * 2); let desiredDestHeight = (fontSizeFinal * 1.2) + (mSup * 2); larguraDoElementoNoCanvas = Math.max(larguraDoElementoNoCanvas, limitesIniciais.width * 0.4); desiredDestHeight = Math.max(desiredDestHeight, limitesIniciais.height * 0.4); const MARGEM_CANVAS_LATERAL = 10; finalCanvas.width = Math.max(imgBase.width, larguraDoElementoNoCanvas + MARGEM_CANVAS_LATERAL); finalCanvas.height = Math.max(imgBase.height, desiredDestHeight + MARGEM_CANVAS_LATERAL); const codigoAlinhamentoStr = String(alinhamento).split('~')[0].trim(); const MARGEM_POSICIONAMENTO = MARGEM_CANVAS_LATERAL / 2; let destX = (finalCanvas.width - larguraDoElementoNoCanvas) / 2; if (codigoAlinhamentoStr === '1' || codigoAlinhamentoStr === '3') destX = MARGEM_POSICIONAMENTO; if (codigoAlinhamentoStr === '2' || codigoAlinhamentoStr === '4') destX = finalCanvas.width - larguraDoElementoNoCanvas - MARGEM_POSICIONAMENTO; const destY = (finalCanvas.height - desiredDestHeight) / 2; finalCtx.clearRect(0, 0, finalCanvas.width, finalCanvas.height); // AJUSTE CIRÚRGICO: Define e Aplica a máscara para o "Arredondamento" estrito antes da pintura const clipRoundRect = (ctx, x, y, w, h, r) => { ctx.beginPath(); ctx.moveTo(x + r, y); ctx.arcTo(x + w, y, x + w, y + h, r); ctx.arcTo(x + w, y + h, x, y + h, r); ctx.arcTo(x, y + h, x, y, r); ctx.arcTo(x, y, x + w, y, r); ctx.closePath(); }; finalCtx.save(); const safeRadiusClip = Math.min(radiusClip, larguraDoElementoNoCanvas / 2, desiredDestHeight / 2); clipRoundRect(finalCtx, destX, destY, larguraDoElementoNoCanvas, desiredDestHeight, safeRadiusClip); finalCtx.clip(); const radius = 10; const sourceW = limitesIniciais.width; const sourceH = limitesIniciais.height; const corner = Math.min(radius, sourceW / 2, sourceH / 2); finalCtx.drawImage(parteNaoTransparenteCanvas, 0, 0, corner, corner, destX, destY, corner, corner); finalCtx.drawImage(parteNaoTransparenteCanvas, sourceW - corner, 0, corner, corner, destX + larguraDoElementoNoCanvas - corner, destY, corner, corner); finalCtx.drawImage(parteNaoTransparenteCanvas, 0, sourceH - corner, corner, corner, destX, destY + desiredDestHeight - corner, corner, corner); finalCtx.drawImage(parteNaoTransparenteCanvas, sourceW - corner, sourceH - corner, corner, corner, destX + larguraDoElementoNoCanvas - corner, destY + desiredDestHeight - corner, corner, corner); finalCtx.drawImage(parteNaoTransparenteCanvas, corner, 0, sourceW - 2 * corner, corner, destX + corner, destY, larguraDoElementoNoCanvas - 2 * corner, corner); finalCtx.drawImage(parteNaoTransparenteCanvas, corner, sourceH - corner, sourceW - 2 * corner, corner, destX + corner, destY + desiredDestHeight - corner, larguraDoElementoNoCanvas - 2 * corner, corner); finalCtx.drawImage(parteNaoTransparenteCanvas, 0, corner, corner, sourceH - 2 * corner, destX, destY + corner, corner, desiredDestHeight - 2 * corner); finalCtx.drawImage(parteNaoTransparenteCanvas, sourceW - corner, corner, corner, sourceH - 2 * corner, destX + larguraDoElementoNoCanvas - corner, destY + corner, corner, desiredDestHeight - 2 * corner); finalCtx.drawImage(parteNaoTransparenteCanvas, corner, corner, sourceW - 2 * corner, sourceH - 2 * corner, destX + corner, destY + corner, larguraDoElementoNoCanvas - 2 * corner, desiredDestHeight - 2 * corner); finalCtx.restore(); finalCtx.textBaseline = 'middle'; finalCtx.fillStyle = corTexto || 'black'; finalCtx.textAlign = 'center'; finalCtx.font = `${fontSizeFinal}px ${FONTE_FAMILIA}`; const xTexto = destX + larguraDoElementoNoCanvas / 2; const yTexto = destY + desiredDestHeight / 2 + (fontSizeFinal * 0.07); finalCtx.fillText(textoFinal, xTexto, yTexto); const dataUrl = finalCanvas.toDataURL('image/png'); blocoObjeto.imagemGeradaCache = dataUrl; blocoObjeto.textoGeradoCache = texto; blocoObjeto.alinhamentoGeradoCache = alinhamento; blocoObjeto.corTextoGeradoCache = corTexto; blocoObjeto.corFundoGeradoCache = corFundo; blocoObjeto.tamanhoFonteGeradoCache = tamanhoFonteParam; blocoObjeto.margemLatGeradoCache = margemLatParam; blocoObjeto.margemSupGeradoCache = margemSupParam; blocoObjeto.arredondamentoGeradoCache = arredondamentoParam; blocoObjeto.imagemUrlCache = dataUrl; blocoObjeto.imgWidthCache = finalCanvas.width; blocoObjeto.imgHeightCache = finalCanvas.height; return dataUrl; } catch (error) { console.warn(`Falha ao gerar imagem tingida/gradiente para ${blocoObjeto.nome}:`, error); return null; } }          // =============================== INÍCIO DO NOVO CÓDIGO =============================== // VERSÃO FINAL CORRIGIDA - Força margens zero e ajusta o cálculo de recuo. // VERSÃO FINAL - Recuo dinâmico baseado na largura real dos blocos e margens zero. // VERSÃO DEFINITIVA - Usa um processo iterativo para resolver a dependência circular entre altura e largura. // VERSÃO FINAL CORRIGIDA - Aumenta o padding horizontal para um recuo visível e eficaz. // VERSÃO DEFINITIVA - Usa um recuo horizontal fixo (30%) para slots ocupados, resolvendo o erro de cálculo de largura. // VERSÃO FINAL - Recuo horizontal ajustado e cálculo de recuo refeito a cada quebra de linha. // VERSÃO FINAL E DEFINITIVA - Calcula a largura real dos blocos internos a partir de suas imagens base. // VERSÃO FINAL - Usa recuo de coluna (1/3 da largura) para slots ocupados. Lógica simples e robusta. // VERSÃO DEFINITIVA - Pré-carrega as dimensões dos blocos internos para garantir o cálculo de recuo 100% preciso e dinâmico. async function gerarImagemTextoComplexo(blocoObjeto, texto, alinhamento, corTexto, tamanhoTexto, margem) {     const textoDecodificado = reverterCaracteresEspeciais(texto || '');     const NOME_FONTE = 'Arial';     const FAT_MULT_TAMANHO = 3.0;          const parsearTextoComEstilos = (txt, corPadrao) => {         const partes = [];         const regex = /\/\*(\[(#[a-fA-F0-9]{6})\])?(.*?)\*\//g;         let ultimoIndex = 0, match;         while ((match = regex.exec(txt)) !== null) {             if (match.index > ultimoIndex) partes.push({ text: txt.substring(ultimoIndex, match.index), bold: false, color: corPadrao });             let corDaParte = ensureColorIsVisible(match[2] || corPadrao);             partes.push({ text: match[3], bold: true, color: corDaParte });             ultimoIndex = regex.lastIndex;         }         if (ultimoIndex < txt.length) partes.push({ text: txt.substring(ultimoIndex), bold: false, color: corPadrao });         return partes;     };     const getImageUrlForBlock = (blocoP) => {         const nomeBaseImagem = String(blocoP.texto).replace(/\s+/g, '_').toLowerCase();         const nomeArquivoEspecificoP = `${nomeBaseImagem}p.png`;         const nomeArquivoPadrao = `${nomeBaseImagem}.png`;         if (context.listaImagens.has(nomeArquivoEspecificoP)) {             return `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoEspecificoP)}`;         } else if (context.listaImagens.has(nomeArquivoPadrao)) {             return `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoPadrao)}`;         }         return null;     };     const getOriginalImageDimensions = (blocoP) => { // AJUSTE CIRÚRGICO: Se o bloco já calculou e guardou a dimensão real (especialmente verticais), use-a. if (blocoP.imgWidthCache && blocoP.imgHeightCache) { return { width: blocoP.imgWidthCache, height: blocoP.imgHeightCache }; } const urlImagemFinal = getImageUrlForBlock(blocoP); if (urlImagemFinal && DADOS_IMAGEM_CACHE.has(urlImagemFinal)) { return DADOS_IMAGEM_CACHE.get(urlImagemFinal); } return { width: 100, height: 50 }; };     try {         const imgBase = await new Promise((resolve, reject) => {             const i = new Image(); i.crossOrigin = "Anonymous"; i.onload = () => resolve(i); i.onerror = reject;             const nomeArquivoFinal = getFinalImageName(blocoObjeto, 'b.png');             if (!nomeArquivoFinal) throw new Error(`Imagem base não encontrada.`);             i.src = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoFinal)}`;         });                  const blocosInternos = [].concat(...blocoObjeto.linhasInternas.map(l => l.inicio.concat(l.fim)));         const urlsParaVerificar = new Set(blocosInternos.map(b => getImageUrlForBlock(b)).filter(Boolean));         const promisesDeCarregamento = [];         for (const url of urlsParaVerificar) {             if (!DADOS_IMAGEM_CACHE.has(url)) {                 promisesDeCarregamento.push(new Promise((resolve) => {                     const img = new Image();                     img.onload = () => { DADOS_IMAGEM_CACHE.set(url, { width: img.width, height: img.height }); resolve(); };                     img.onerror = () => { DADOS_IMAGEM_CACHE.set(url, { width: 100, height: 50 }); resolve(); };                     img.src = url;                 }));             }         }         await Promise.all(promisesDeCarregamento);         const canvas = document.createElement('canvas');         const ctx = canvas.getContext('2d');         canvas.width = imgBase.width;         let editorWidth = context.painelEditorEl ? context.painelEditorEl.clientWidth : 800;         editorWidth -= 20;          let domWidth = editorWidth;         if (blocoObjeto._renderContext && blocoObjeto._renderContext.dentroDeColunaE) {             domWidth = editorWidth / 3;         }         let scale = canvas.width / domWidth;         if (isNaN(scale) || scale <= 0) scale = 1.0;         const PADDING_Y = 8 * scale;          const DOM_OFFSET_X = 21 * scale;          const SLOT_CONTOUR_PADDING_PX = 10 * scale;          const GAP_ENTRE_BLOCOS_PX = 4 * scale;         const MAX_P_HEIGHT_CANVAS = 50 * scale;         const marginY = 4 * scale;          const getDimensaoBloco = (b, canvasWidth) => {             let widthPx = 0;             let heightPx = MAX_P_HEIGHT_CANVAS;                           let paramLargura = b.larguraGeradoCache;             if (!paramLargura && b.camposDefinidos && b.valoresCampos) {                 const cLarg = b.camposDefinidos.find(c => c.nome.includes('$[23]'));                 if (cLarg) paramLargura = getValorCampoNormalizado(b.valoresCampos, cLarg.nome);             }                          const dimOrig = getOriginalImageDimensions(b);             const isBlockType4x = blocoObjeto.camposDefinidos && blocoObjeto.camposDefinidos.some(c => c.nome.includes('$[4'));             const parentWidth = canvasWidth * (isBlockType4x ? 0.45 : 0.33);             if (paramLargura) {                 const sVal = String(paramLargura).trim().toLowerCase();                 const num = parseFloat(sVal);                 if (!isNaN(num)) {                     if (sVal.endsWith('px')) {                         const screenWidth = window.innerWidth || window.screen.width || 1920;                         widthPx = canvasWidth * (num / screenWidth);                     } else {                         widthPx = canvasWidth * (num / 100);                     }                     if (widthPx > 0 && dimOrig && dimOrig.width > 0) {                         heightPx = (widthPx * dimOrig.height) / dimOrig.width;                     }                 }             } else {                 let imageContentWidth = (dimOrig && dimOrig.width > 0) ? dimOrig.width : 100;                 let imageContentHeight = (dimOrig && dimOrig.height > 0) ? dimOrig.height : 50;                                  if (b.imagemGeradaCache || b.tipo.startsWith('T') || b.camposDefinidos?.some(c => c.nome.includes('$[21]'))) {                     if (imageContentWidth > parentWidth) {                         const scaleW = parentWidth / imageContentWidth;                         widthPx = parentWidth;                         heightPx = imageContentHeight * scaleW;                     } else {                         widthPx = imageContentWidth;                         heightPx = imageContentHeight;                     }                 } else if (b.tipo === 'P') {                     heightPx = Math.min(imageContentHeight * scale, MAX_P_HEIGHT_CANVAS);                     widthPx = (heightPx / imageContentHeight) * imageContentWidth;                 } else {                     widthPx = imageContentWidth * scale;                     heightPx = imageContentHeight * scale;                 }             }             return { width: widthPx, height: heightPx };         };         const calcularLarguraRealDosBlocosNoSlot = (blocos, canvasWidth) => {             if (!blocos || blocos.length === 0) return 0;             let larguraTotal = 0;             for (const b of blocos) {                 larguraTotal += getDimensaoBloco(b, canvasWidth).width;             }             if (blocos.length > 1) larguraTotal += (blocos.length - 1) * GAP_ENTRE_BLOCOS_PX;             return Math.min(larguraTotal, canvasWidth - 10);         };         const calcularAlturaRealDosBlocosNoSlot = (blocos, canvasWidth) => {             if (!blocos || blocos.length === 0) return 0;             let maxH = 0;             for (const b of blocos) {                 const h = getDimensaoBloco(b, canvasWidth).height;                 if (h > maxH) maxH = h;             }             return maxH;         };         const obterCaixasDeColisao = (alturaTotalContainer, canvasWidth) => {             const slotHeight = alturaTotalContainer / 3;              const leftBlocks = [];             const rightBlocks = [];             const criarCaixa = (w, h, rowY) => {                 if (w <= 0) return null;                 // AJUSTE CIRÚRGICO: A âncora agora é rigidamente presa ao topo exato do slot (rowY),                 // impedindo o "recuo falso" acima da imagem conforme a altura total do slot cresce.                 let top = rowY;                 return { top: top - marginY - 20, bottom: top + h + marginY, width: w + DOM_OFFSET_X };             };             for(let i=0; i<3; i++) {                 let rowY = i * slotHeight;                 let wL = calcularLarguraRealDosBlocosNoSlot(blocoObjeto.linhasInternas[i]?.inicio, canvasWidth);                 let hL = calcularAlturaRealDosBlocosNoSlot(blocoObjeto.linhasInternas[i]?.inicio, canvasWidth);                 let boxL = criarCaixa(wL, hL, rowY);                 if (boxL) leftBlocks.push(boxL);                 let wR = calcularLarguraRealDosBlocosNoSlot(blocoObjeto.linhasInternas[i]?.fim, canvasWidth);                 let hR = calcularAlturaRealDosBlocosNoSlot(blocoObjeto.linhasInternas[i]?.fim, canvasWidth);                 let boxR = criarCaixa(wR, hR, rowY);                 if (boxR) rightBlocks.push(boxR);             }             return { leftBlocks, rightBlocks };         };         const pAlinhamento = String(alinhamento || '1').split('~')[0].trim();         let pCorTexto = String(corTexto || '#000000').split('~')[0].trim();         const pTamanhoTexto = String(tamanhoTexto || '10').split('~')[0].trim();         pCorTexto = ensureColorIsVisible(pCorTexto);                  const fontSize = Math.max(10, parseFloat(pTamanhoTexto) * FAT_MULT_TAMANHO);         const lineHeight = fontSize * 1.15;         const linhasOriginais = textoDecodificado.split('\n');         let alturaFinalEstavel = 0;         let linesParaDesenhar = [];         const MAX_ITERATIONS = 5;         const simularLayout = (alturaParaSimulacao) => {             const colisao = obterCaixasDeColisao(alturaParaSimulacao, canvas.width);             let currentY = PADDING_Y;              let currentLines = [];             for (const linha of linhasOriginais) {                 if (linha.trim() === '' && currentY > 0) {                     currentLines.push({ y: currentY, content: [], isManualBreak: true });                     currentY += lineHeight;                     continue;                 }                 const styledTextParts = parsearTextoComEstilos(linha, pCorTexto);                 let palavrasDaLinha = [];                 styledTextParts.forEach(part => {                     part.text.split(/\s+/).filter(p => p).forEach(p => palavrasDaLinha.push({ ...part, text: p }));                 });                 if (palavrasDaLinha.length === 0) {                     if (currentY > 0 && linha.length === 0) { currentLines.push({ y: currentY, content: [], isManualBreak: true }); currentY += lineHeight; }                     continue;                 }                                  let currentLineParts = [];                 let currentX = 0;                 for (let idx = 0; idx < palavrasDaLinha.length; idx++) {                     const palavraInfo = palavrasDaLinha[idx];                     ctx.font = `${palavraInfo.bold ? 'bold' : ''} ${fontSize}px ${NOME_FONTE}`;                     const palavraWidth = ctx.measureText(palavraInfo.text + " ").width;                     let spaceFound = false;                     let currentRecuoE = 0, currentRecuoD = 0, currentME = 0, currentMD = 0, currentW = 0;                     while (!spaceFound && currentY < 10000) {                         currentRecuoE = 0;                         currentRecuoD = 0;                                                  for (let b of colisao.leftBlocks) {                             if (currentY + lineHeight - marginY > b.top && currentY + marginY < b.bottom) currentRecuoE = Math.max(currentRecuoE, b.width);                         }                         for (let b of colisao.rightBlocks) {                             if (currentY + lineHeight - marginY > b.top && currentY + marginY < b.bottom) currentRecuoD = Math.max(currentRecuoD, b.width);                         }                         currentME = (currentRecuoE > 0 ? currentRecuoE + SLOT_CONTOUR_PADDING_PX : 0);                         currentMD = (currentRecuoD > 0 ? currentRecuoD + SLOT_CONTOUR_PADDING_PX : 0);                         currentW = canvas.width - currentME - currentMD;                         if (currentW >= Math.min(palavraWidth, 40)) {                             spaceFound = true;                         } else {                             if (currentLineParts.length > 0) {                                 currentLines.push({ y: currentY, content: currentLineParts });                                 currentLineParts = [];                             }                             currentY += lineHeight;                         }                     }                     if (currentLineParts.length === 0) currentX = currentME;                     if (currentX + palavraWidth > canvas.width - currentMD && currentLineParts.length > 0) {                         currentLines.push({ y: currentY, content: currentLineParts });                         currentY += lineHeight;                         currentLineParts = [];                                                  currentRecuoE = 0;                         for (let b of colisao.leftBlocks) {                             if (currentY + lineHeight - marginY > b.top && currentY + marginY < b.bottom) currentRecuoE = Math.max(currentRecuoE, b.width);                         }                         currentX = (currentRecuoE > 0 ? currentRecuoE + SLOT_CONTOUR_PADDING_PX : 0);                     }                     currentLineParts.push(palavraInfo);                     currentX += palavraWidth;                 }                 if (currentLineParts.length > 0) {                     currentLines.push({ y: currentY, content: currentLineParts });                     currentY += lineHeight;                 }             }             return { calculatedHeight: Math.max(166 * scale, currentY + PADDING_Y), lines: currentLines };         };         alturaFinalEstavel = simularLayout(166 * scale).calculatedHeight;         for (let i = 0; i < MAX_ITERATIONS; i++) {             let resultadoSimulacao = simularLayout(alturaFinalEstavel);             if (Math.abs(resultadoSimulacao.calculatedHeight - alturaFinalEstavel) < 2) {                 linesParaDesenhar = resultadoSimulacao.lines;                 alturaFinalEstavel = resultadoSimulacao.calculatedHeight;                 break;             }             alturaFinalEstavel = resultadoSimulacao.calculatedHeight;             linesParaDesenhar = resultadoSimulacao.lines;         }                  canvas.height = alturaFinalEstavel;         const corner = Math.min(15, imgBase.width / 2, imgBase.height / 2);                  ctx.drawImage(imgBase, 0, 0, corner, corner, 0, 0, corner, corner);         ctx.drawImage(imgBase, imgBase.width - corner, 0, corner, corner, canvas.width - corner, 0, corner, corner);         ctx.drawImage(imgBase, 0, imgBase.height - corner, corner, corner, 0, canvas.height - corner, corner, corner);         ctx.drawImage(imgBase, imgBase.width - corner, imgBase.height - corner, corner, corner, canvas.width - corner, canvas.height - corner, corner, corner);         ctx.drawImage(imgBase, corner, 0, imgBase.width - 2 * corner, corner, corner, 0, canvas.width - 2 * corner, corner);         ctx.drawImage(imgBase, corner, imgBase.height - corner, imgBase.width - 2 * corner, corner, corner, canvas.height - corner, canvas.width - 2 * corner, corner);         ctx.drawImage(imgBase, 0, corner, corner, imgBase.height - 2 * corner, 0, corner, corner, canvas.height - 2 * corner);         ctx.drawImage(imgBase, imgBase.width - corner, corner, corner, imgBase.height - 2 * corner, canvas.width - corner, corner, corner, canvas.height - 2 * corner);         ctx.drawImage(imgBase, corner, corner, imgBase.width - 2 * corner, imgBase.height - 2 * corner, corner, corner, canvas.width - 2 * corner, canvas.height - 2 * corner);         const colisaoFinal = obterCaixasDeColisao(alturaFinalEstavel, canvas.width);                  for (const line of linesParaDesenhar) {             if (line.isManualBreak || line.content.length === 0) continue;                          const lineTopY = line.y;             const baselineY = line.y + lineHeight;                          let currentRecuoE = 0;             let currentRecuoD = 0;             for (let b of colisaoFinal.leftBlocks) {                 if (lineTopY + lineHeight - marginY > b.top && lineTopY + marginY < b.bottom) currentRecuoE = Math.max(currentRecuoE, b.width);             }             for (let b of colisaoFinal.rightBlocks) {                 if (lineTopY + lineHeight - marginY > b.top && lineTopY + marginY < b.bottom) currentRecuoD = Math.max(currentRecuoD, b.width);             }             const margemEsquerdaTotal = (currentRecuoE > 0 ? currentRecuoE + SLOT_CONTOUR_PADDING_PX : 0);             const margemDireitaTotal = (currentRecuoD > 0 ? currentRecuoD + SLOT_CONTOUR_PADDING_PX : 0);             const larguraDisponivel = canvas.width - margemEsquerdaTotal - margemDireitaTotal;                          let lineWidth = 0;             line.content.forEach(p => { ctx.font = `${p.bold ? 'bold' : ''} ${fontSize}px ${NOME_FONTE}`; lineWidth += ctx.measureText(p.text + " ").width; });             if (lineWidth > 0) lineWidth -= ctx.measureText(" ").width;             let x = margemEsquerdaTotal;             if (pAlinhamento === '0') x = margemEsquerdaTotal + (larguraDisponivel - lineWidth) / 2;             else if (pAlinhamento === '2') x = canvas.width - margemDireitaTotal - lineWidth;             for (const part of line.content) {                 ctx.font = `${part.bold ? 'bold' : ''} ${fontSize}px ${NOME_FONTE}`;                 ctx.fillStyle = part.color;                 ctx.fillText(part.text + " ", x, baselineY);                 x += ctx.measureText(part.text + " ").width;             }         }         const dataUrl = canvas.toDataURL('image/png');         blocoObjeto.imagemGeradaCache = dataUrl;         blocoObjeto.imagemUrlCache = dataUrl;         blocoObjeto.imgWidthCache = canvas.width;         blocoObjeto.imgHeightCache = canvas.height;         blocoObjeto.cacheParams4x = { texto, alinhamento, corTexto, tamanhoTexto, margem };         setTimeout(() => {             const container = document.querySelector(`[data-bloco-id="${blocoObjeto.id}"] > .bloco-visor`);             if (container) {                 container.style.setProperty('justify-content', 'flex-start', 'important');                 const linhas = container.querySelectorAll(':scope > div:not(.bloco-content-wrapper)');                 linhas.forEach(linha => {                     linha.style.setProperty('flex', '1 1 33.333%', 'important');                     linha.style.setProperty('min-height', '0', 'important');                     linha.style.setProperty('max-height', '33.333%', 'important');                     linha.style.setProperty('margin', '0', 'important');                     linha.style.setProperty('padding', '0', 'important');                 });             }         }, 150);         return dataUrl;     } catch (error) {         console.warn(`Falha ao gerar imagem de texto complexo para ${blocoObjeto.nome}:`, error);         return null;     } } async function gerarImagemComTexto(blocoObjeto, texto, alinhamento, tamanhoFonteParam, corTextoParam) {     const nomeBaseImagem = String(blocoObjeto.texto).replace(/\s+/g, '_').toLowerCase();     const nomeArquivoBaseTransparente = `${nomeBaseImagem}b.png`;     if (!context.listaImagens.has(nomeArquivoBaseTransparente)) {         return null;     }     const urlBaseTransparente = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoBaseTransparente)}`;     try {         const img = await new Promise((resolve, reject) => {             const i = new Image();             i.onload = () => resolve(i);             i.onerror = reject;             i.src = urlBaseTransparente;         });         const dimensoesBase = { width: img.width, height: img.height };         DADOS_IMAGEM_CACHE.set(urlBaseTransparente, dimensoesBase);         const canvas = document.createElement('canvas');         const ctx = canvas.getContext('2d');         const MARGEM_HORIZONTAL_PX = 30;         const MARGEM_VERTICAL_PX = 10;         const FATOR_ALTURA_LINHA = 1.2;         const FONTE_FAMILIA = 'Arial';         const larguraUtil = dimensoesBase.width - MARGEM_HORIZONTAL_PX;         const tamanhoBase = parseFloat(tamanhoFonteParam) || 10;         let multiplicador = 2.0;         if (blocoObjeto._renderContext && (blocoObjeto._renderContext.dentroDeColunaE || blocoObjeto._renderContext.dentroDeSlotT)) {             multiplicador = 3.0;         }         let fontSize = Math.max(tamanhoBase * multiplicador, 8);         const lineHeight = fontSize * FATOR_ALTURA_LINHA;         // --- INÍCIO DA NOVA LÓGICA DE QUEBRA DE LINHA ---         const corBaseFinal = ensureColorIsVisible(corTextoParam || 'black');         const manualLines = texto.split('
');         const finalLines = []; // Array que conterá as linhas finais, já com quebra automática         for (const line of manualLines) {             const segments = parsearTextoComEstilos(line, corBaseFinal);             const words = [];             segments.forEach(segment => {                 segment.text.split(' ').forEach(word => {                     if (word) {                         words.push({ text: word, bold: segment.bold, color: segment.color });                     }                 });             });             if (words.length > 0) {                 let currentLine = [];                 words.forEach(word => {                     const testLine = [...currentLine, word];                     let testWidth = 0;                     testLine.forEach((w, index) => {                         const fontWeight = w.bold ? 'bold ' : '';                         ctx.font = `${fontWeight}${fontSize}px ${FONTE_FAMILIA}`;                         testWidth += ctx.measureText(w.text + (index < testLine.length - 1 ? ' ' : '')).width;                     });                     if (testWidth > larguraUtil && currentLine.length > 0) {                         finalLines.push(currentLine);                         currentLine = [word];                     } else {                         currentLine.push(word);                     }                 });                 finalLines.push(currentLine);             } else {                  finalLines.push([]); // Adiciona uma linha vazia para manter o
            }         }         // --- FIM DA NOVA LÓGICA DE QUEBRA DE LINHA ---         const alturaTotalTexto = (finalLines.length * lineHeight) + MARGEM_VERTICAL_PX;         const alturaFinalCanvas = Math.max(dimensoesBase.height, alturaTotalTexto);         canvas.width = dimensoesBase.width;         canvas.height = alturaFinalCanvas;         ctx.drawImage(img, 0, 0, dimensoesBase.width, alturaFinalCanvas);         ctx.textBaseline = 'middle';                  let startY = (canvas.height / 2) - ((finalLines.length - 1) * lineHeight / 2);         finalLines.forEach(lineSegments => {             let totalWidth = 0;             lineSegments.forEach((segment, index) => {                 const fontWeight = segment.bold ? 'bold ' : '';                 ctx.font = `${fontWeight}${fontSize}px ${FONTE_FAMILIA}`;                 totalWidth += ctx.measureText(segment.text + (index < lineSegments.length - 1 ? ' ' : '')).width;             });                          const codigoAlinhamentoStr = String(alinhamento).split('~')[0].trim();             let currentX;             if (codigoAlinhamentoStr === '1' || codigoAlinhamentoStr === '3') { currentX = 15; }             else if (codigoAlinhamentoStr === '2' || codigoAlinhamentoStr === '4') { currentX = canvas.width - 15 - totalWidth; }             else { currentX = (canvas.width - totalWidth) / 2; }             lineSegments.forEach((segment, index) => {                 const fontWeight = segment.bold ? 'bold ' : '';                 ctx.font = `${fontWeight}${fontSize}px ${FONTE_FAMILIA}`;                 ctx.fillStyle = segment.color;                 const wordText = segment.text + (index < lineSegments.length - 1 ? ' ' : '');                 ctx.fillText(wordText, currentX, startY);                 currentX += ctx.measureText(wordText).width;             });             startY += lineHeight;         });         const dataUrl = canvas.toDataURL('image/png');         blocoObjeto.imagemGeradaCache = dataUrl;         blocoObjeto.textoGeradoCache = texto;         blocoObjeto.alinhamentoGeradoCache = alinhamento;         blocoObjeto.tamanhoFonteGeradoCache = tamanhoFonteParam;         blocoObjeto.corTextoGeradoCache = corTextoParam;         blocoObjeto.imagemUrlCache = dataUrl;         blocoObjeto.imgWidthCache = canvas.width;         blocoObjeto.imgHeightCache = canvas.height;         return dataUrl;     } catch (error) {         console.warn(`Falha ao gerar imagem com texto para ${blocoObjeto.nome}:`, error);         return null;     } } // ========================================================== // 2. ADICIONE ESTA NOVA FUNÇÃO AUXILIAR AO SEU SCRIPT // ========================================================== function updateInsertionMarkerInSlotT(e, slotDiv) {     limparFantasmasAtivos();     const children = Array.from(slotDiv.querySelectorAll('.bloco-renderizado[data-bloco-id]'));     let targetElement = null;     let insertBefore = false;     for (const child of children) {         const rect = child.getBoundingClientRect();         const midX = rect.left + rect.width / 2;         if (e.clientX < midX) {             targetElement = child;             insertBefore = true;             break;         }         targetElement = child;         insertBefore = false;     }     if (targetElement) {         if (insertBefore) {             slotDiv.insertBefore(context.insertionMarkerEl, targetElement);             slotDiv.dataset.dropTargetIdInSlot = targetElement.dataset.blocoId;         } else {             slotDiv.insertBefore(context.insertionMarkerEl, targetElement.nextSibling);             slotDiv.dataset.dropTargetIdInSlot = targetElement.dataset.blocoId;         }     } else {         slotDiv.appendChild(context.insertionMarkerEl);         delete slotDiv.dataset.dropTargetIdInSlot;     } } async function carregarImagemParaBloco(elementoVisor, blocoObjeto) { if (!elementoVisor || !blocoObjeto) return; if (!blocoObjeto._renderContext) { blocoObjeto._renderContext = {}; } blocoObjeto._renderContext.dentroDeColunaE = !!elementoVisor.closest(`.${context.editorId}_coluna-bloco-e`); blocoObjeto._renderContext.dentroDeSlotT = !!elementoVisor.closest('.slot-t'); const aplicarEstilosDeImagem = (divEl, url, imgWidth, imgHeight, bloco, retries = 0) => { const isGroupHeader = (bloco.tipo.startsWith('E') || bloco.tipo.startsWith('C')) && bloco.groupIndex === 0; if (isGroupHeader) { applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: 'cover', backgroundPosition: 'center' }); return; } const parentWidth = divEl.parentElement ? divEl.parentElement.clientWidth : 0; const MAX_RETRIES = 10; if (parentWidth === 0 && !url.startsWith('data:') && retries < MAX_RETRIES) { setTimeout(() => aplicarEstilosDeImagem(divEl, url, imgWidth, imgHeight, bloco, retries + 1), 50); return; } const contentWrapperEl = divEl.querySelector('.bloco-content-wrapper'); if (contentWrapperEl) { contentWrapperEl.style.display = 'none'; } divEl.style.padding = '0'; const isBlueBlock = bloco.tipo.startsWith('L'); const hasCustomWidth = !!bloco.larguraGeradoCache; if (isBlueBlock) { const baseContainerWidth = parentWidth > 0 ? parentWidth : (context.painelEditorEl ? context.painelEditorEl.clientWidth : 800); let larguraRealPx = baseContainerWidth; if (hasCustomWidth) { const larguraParam = String(bloco.larguraGeradoCache).trim().toLowerCase(); const num = parseFloat(larguraParam); if (!isNaN(num)) { if (larguraParam.endsWith('px')) { larguraRealPx = num; } else { larguraRealPx = baseContainerWidth * (num / 100); } } } const alturaRealPx = (larguraRealPx * imgHeight) / imgWidth; applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat', backgroundPosition: 'center center', backgroundColor: 'transparent', overflow: 'visible' }); divEl.style.setProperty('width', `${larguraRealPx}px`, 'important'); divEl.style.setProperty('height', `${alturaRealPx}px`, 'important'); divEl.style.setProperty('min-height', `${alturaRealPx}px`, 'important'); divEl.style.setProperty('max-width', '100%', 'important'); divEl.style.setProperty('max-height', 'none', 'important'); let alinhamento = '0'; if (bloco.alinhamentoGeradoCache) { alinhamento = String(bloco.alinhamentoGeradoCache).split('~')[0].trim(); } else if (bloco.camposDefinidos && bloco.valoresCampos) { const cAlinh = bloco.camposDefinidos.find(c => c.nome.includes('$[22]') || c.nome.includes('$[12]')); if (cAlinh) { const val = getValorCampoNormalizado(bloco.valoresCampos, cAlinh.nome); if (val) alinhamento = String(val).split('~')[0].trim(); } } if (alinhamento === '1' || alinhamento === '3') { divEl.style.setProperty('margin-left', '0', 'important'); divEl.style.setProperty('margin-right', 'auto', 'important'); } else if (alinhamento === '2' || alinhamento === '4') { divEl.style.setProperty('margin-left', 'auto', 'important'); divEl.style.setProperty('margin-right', '0', 'important'); } else { divEl.style.setProperty('margin-left', 'auto', 'important'); divEl.style.setProperty('margin-right', 'auto', 'important'); } if (divEl.parentElement) { divEl.parentElement.style.setProperty('width', '100%', 'important'); divEl.parentElement.style.setProperty('flex-basis', '100%', 'important'); divEl.parentElement.style.setProperty('height', 'auto', 'important'); divEl.parentElement.style.setProperty('min-height', `${alturaRealPx}px`, 'important'); divEl.parentElement.style.setProperty('max-width', '100%', 'important'); divEl.parentElement.style.setProperty('max-height', 'none', 'important'); divEl.parentElement.style.setProperty('display', 'block', 'important'); divEl.parentElement.style.setProperty('overflow', 'visible', 'important'); } return; } if (hasCustomWidth) { const larguraParam = String(bloco.larguraGeradoCache).trim().toLowerCase(); let larguraRealPx = null; const editorWidth = context.painelEditorEl ? context.painelEditorEl.clientWidth : 800; const screenWidth = window.innerWidth || window.screen.width || 1920; if (larguraParam.endsWith('px')) { const pxValue = parseFloat(larguraParam); larguraRealPx = editorWidth * (pxValue / screenWidth); } else { const perc = parseFloat(larguraParam); larguraRealPx = editorWidth * (perc / 100); } const alturaRealPx = (larguraRealPx * imgHeight) / imgWidth; applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat', backgroundPosition: 'top center', backgroundColor: 'transparent', overflow: 'visible' }); divEl.style.setProperty('width', `${larguraRealPx}px`, 'important'); divEl.style.setProperty('height', `${alturaRealPx}px`, 'important'); divEl.style.setProperty('min-height', `${alturaRealPx}px`, 'important'); divEl.style.setProperty('max-width', 'none', 'important'); divEl.style.setProperty('max-height', 'none', 'important'); if (divEl.parentElement) { divEl.parentElement.style.setProperty('width', `${larguraRealPx}px`, 'important'); divEl.parentElement.style.setProperty('height', '100%', 'important'); divEl.parentElement.style.setProperty('min-height', `${alturaRealPx}px`, 'important'); divEl.parentElement.style.setProperty('max-width', 'none', 'important'); divEl.parentElement.style.setProperty('max-height', 'none', 'important'); divEl.parentElement.style.setProperty('overflow', 'visible', 'important'); divEl.parentElement.style.setProperty('flex-basis', `${larguraRealPx}px`, 'important'); divEl.parentElement.style.setProperty('flex-shrink', '0', 'important'); divEl.parentElement.style.setProperty('flex-grow', '0', 'important'); divEl.parentElement.style.setProperty('align-items', 'flex-start', 'important'); } const slotT = divEl.closest('.slot-t'); if (slotT) { slotT.style.removeProperty('min-height'); slotT.style.setProperty('overflow', 'visible', 'important'); slotT.style.setProperty('align-items', 'flex-start', 'important'); setTimeout(() => { const tBlockEl = slotT.closest('.bloco-renderizado'); if (tBlockEl) { const rectT = tBlockEl.getBoundingClientRect(); let maxBottomVisivel = rectT.bottom; const imagensInternas = tBlockEl.querySelectorAll('.slot-t .bloco-renderizado .bloco-visor'); imagensInternas.forEach(imgVisor => { if (imgVisor.offsetParent !== null) { const rectImg = imgVisor.getBoundingClientRect(); if (rectImg.bottom > maxBottomVisivel) maxBottomVisivel = rectImg.bottom; } }); const vazamento = maxBottomVisivel - rectT.bottom; if (vazamento > 0) { tBlockEl.style.setProperty('margin-bottom', `${Math.round(vazamento) + 5}px`, 'important'); } else { tBlockEl.style.removeProperty('margin-bottom'); } } }, 100); } } else { const isPDentroDeT = bloco.tipo === 'P' && divEl.closest('.slot-t'); const isPForaDeT = bloco.tipo === 'P' && !isPDentroDeT; const isPDentroDeE = bloco.tipo === 'P' && divEl.closest(`.${context.editorId}_coluna-bloco-e`); const isGeneratedImage = url.startsWith('data:'); if ((isPForaDeT && !isPDentroDeE) || isPDentroDeE) { applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: 'contain', backgroundRepeat: 'no-repeat', backgroundPosition: 'center center', backgroundColor: 'transparent', width: '100%', height: 'auto', aspectRatio: `${imgWidth} / ${imgHeight}`, maxHeight: '150px' }); } else if (isPDentroDeT) { applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: 'contain', backgroundRepeat: 'no-repeat', backgroundPosition: 'center center', backgroundColor: 'transparent', width: 'auto', height: '100%', aspectRatio: `${imgWidth} / ${imgHeight}`, maxHeight: '50px' }); } else { if (isGeneratedImage || bloco.tipo.startsWith('T')) { applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: 'contain', backgroundRepeat: 'no-repeat', backgroundPosition: 'center center', backgroundColor: 'transparent', width: '100%', height: 'auto', aspectRatio: `${imgWidth} / ${imgHeight}` }); } else { let imageContentHeight = imgHeight, imageContentWidth = imgWidth; let maxContentW = parentWidth; if (maxContentW > 0 && imageContentWidth > maxContentW) { const scaleFactorW = maxContentW / imageContentWidth; imageContentWidth = maxContentW; imageContentHeight *= scaleFactorW; } imageContentWidth = Math.round(imageContentWidth); imageContentHeight = Math.round(imageContentHeight); applyStyles(divEl, { backgroundImage: `url('${url}')`, backgroundSize: `${imageContentWidth}px ${imageContentHeight}px`, backgroundRepeat: 'no-repeat', backgroundPosition: 'center center', backgroundColor: 'transparent', minHeight: imageContentHeight + 'px', maxWidth: imageContentWidth + 'px', width: '100%', overflow: 'visible' }); } } } }; const campos = blocoObjeto.camposDefinidos || []; const valores = blocoObjeto.valoresCampos || {}; let imagemGerada = false; let deveTentarGerarImagemDinamica = campos.some(c => c.nome.includes('$[')) && blocoObjeto.tipo !== 'X'; if (deveTentarGerarImagemDinamica) { const campoTextoComplexoDef = campos.find(c => c.nome.includes('$[41]')); const valorTexto = campoTextoComplexoDef ? getValorCampoNormalizado(valores, campoTextoComplexoDef.nome) : undefined; if (valorTexto !== undefined) { const valorAlinhamento = (campos.find(c => c.nome.includes('$[42]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[42]'))?.nome) : '1') || '1'; const valorCorTexto = (campos.find(c => c.nome.includes('$[43]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[43]'))?.nome) : '#000000') || '#000000'; const valorTamanho = (campos.find(c => c.nome.includes('$[44]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[44]'))?.nome) : '20') || '20'; const valorMargem = (campos.find(c => c.nome.includes('$[45]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[45]'))?.nome) : '5%') || '5%'; const cacheAtual = { texto: valorTexto, alinhamento: valorAlinhamento, corTexto: valorCorTexto, tamanhoTexto: valorTamanho, margem: valorMargem }; if (blocoObjeto.imagemGeradaCache && JSON.stringify(blocoObjeto.cacheParams4x) === JSON.stringify(cacheAtual)) { aplicarEstilosDeImagem(elementoVisor, blocoObjeto.imagemGeradaCache, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); return; } if (String(valorTexto).trim()) { const dataUrl = await gerarImagemTextoComplexo(blocoObjeto, valorTexto, valorAlinhamento, valorCorTexto, valorTamanho, valorMargem); if (dataUrl) { aplicarEstilosDeImagem(elementoVisor, dataUrl, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); imagemGerada = true; } } } const campoTextoDinamicoDef = campos.find(c => c.nome.includes('$[31]')); const valorTexto3x = campoTextoDinamicoDef ? getValorCampoNormalizado(valores, campoTextoDinamicoDef.nome) : undefined; if (!imagemGerada && valorTexto3x !== undefined) { const valorAlinhamento = (campos.find(c => c.nome.includes('$[32]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[32]'))?.nome) : '0') || '0'; const valorCorTexto = (campos.find(c => c.nome.includes('$[33]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[33]'))?.nome) : '#000000') || '#000000'; const valorCorFundo = (campos.find(c => c.nome.includes('$[34]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[34]'))?.nome) : '#CCCCCC') || '#CCCCCC'; // Busca estrita pelos índices, padronizada com o restante do sistema const campoTamanhoBotaoDef = campos.find(c => c.nome.includes('$[35]')); const valorTamanhoBotao = campoTamanhoBotaoDef ? getValorCampoNormalizado(valores, campoTamanhoBotaoDef.nome) : null; const campoMargemLatDef = campos.find(c => c.nome.includes('$[36]')); const valorMargemLat = campoMargemLatDef ? getValorCampoNormalizado(valores, campoMargemLatDef.nome) : null; const campoMargemSupDef = campos.find(c => c.nome.includes('$[37]')); const valorMargemSup = campoMargemSupDef ? getValorCampoNormalizado(valores, campoMargemSupDef.nome) : null; const campoArredondDef = campos.find(c => c.nome.includes('$[38]')); const valorArredond = campoArredondDef ? getValorCampoNormalizado(valores, campoArredondDef.nome) : null; if (valorTexto3x && String(valorTexto3x).trim() !== '') { if (blocoObjeto.imagemGeradaCache && blocoObjeto.textoGeradoCache === valorTexto3x && blocoObjeto.alinhamentoGeradoCache === valorAlinhamento && blocoObjeto.corTextoGeradoCache === valorCorTexto && blocoObjeto.corFundoGeradoCache === valorCorFundo && blocoObjeto.tamanhoFonteGeradoCache === valorTamanhoBotao && blocoObjeto.margemLatGeradoCache === valorMargemLat && blocoObjeto.margemSupGeradoCache === valorMargemSup && blocoObjeto.arredondamentoGeradoCache === valorArredond) { aplicarEstilosDeImagem(elementoVisor, blocoObjeto.imagemGeradaCache, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); return; } const dataUrl = await gerarImagemComFundoTingidoETexto(blocoObjeto, valorTexto3x, valorAlinhamento, valorCorTexto, valorCorFundo, valorTamanhoBotao, valorMargemLat, valorMargemSup, valorArredond); if (dataUrl) { aplicarEstilosDeImagem(elementoVisor, dataUrl, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); imagemGerada = true; } } } const campoImagemDef = campos.find(c => c.nome.includes('$[21]')); const valorImagem = campoImagemDef ? getValorCampoNormalizado(valores, campoImagemDef.nome) : undefined; if (!imagemGerada && valorImagem !== undefined) { const valorAlinhamentoImg = (campos.find(c => c.nome.includes('$[22]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[22]'))?.nome) : '0') || '0'; const campoLarguraImgDef = campos.find(c => c.nome.includes('$[23]')); const valorLarguraImg = campoLarguraImgDef ? getValorCampoNormalizado(valores, campoLarguraImgDef.nome) : null; if (valorImagem && String(valorImagem).trim() !== '') { if (blocoObjeto.imagemGeradaCache && blocoObjeto.textoGeradoCache === valorImagem && blocoObjeto.alinhamentoGeradoCache === valorAlinhamentoImg && blocoObjeto.larguraGeradoCache === valorLarguraImg) { aplicarEstilosDeImagem(elementoVisor, blocoObjeto.imagemGeradaCache, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); return; } const resultado = await gerarImagemComOutraImagem(blocoObjeto, valorImagem, valorAlinhamentoImg, valorLarguraImg); if (resultado.success) { aplicarEstilosDeImagem(elementoVisor, resultado.dataUrl, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); imagemGerada = true; } } } const campoTextoDef = campos.find(c => c.nome.includes('$[11]')); const valorTexto1x = campoTextoDef ? getValorCampoNormalizado(valores, campoTextoDef.nome) : undefined; if (!imagemGerada && valorTexto1x !== undefined) { const valorAlinhamento = (campos.find(c => c.nome.includes('$[12]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[12]'))?.nome) : '0') || '0'; const valorTamanhoFonte = (campos.find(c => c.nome.includes('$[13]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[13]'))?.nome) : '20') || '20'; const valorCorTexto = (campos.find(c => c.nome.includes('$[14]')) ? getValorCampoNormalizado(valores, campos.find(c => c.nome.includes('$[14]'))?.nome) : '#000000') || '#000000'; if (valorTexto1x && String(valorTexto1x).trim() !== '') { if (blocoObjeto.imagemGeradaCache && blocoObjeto.textoGeradoCache === valorTexto1x && blocoObjeto.alinhamentoGeradoCache === valorAlinhamento && blocoObjeto.tamanhoFonteGeradoCache === valorTamanhoFonte && blocoObjeto.corTextoGeradoCache === valorCorTexto) { aplicarEstilosDeImagem(elementoVisor, blocoObjeto.imagemGeradaCache, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); return; } const dataUrl = await gerarImagemComTexto(blocoObjeto, valorTexto1x, valorAlinhamento, valorTamanhoFonte, valorCorTexto); if (dataUrl) { aplicarEstilosDeImagem(elementoVisor, dataUrl, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); imagemGerada = true; } } } } if (imagemGerada) { elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); return; } if (blocoObjeto.imagemUrlCache && blocoObjeto.imgWidthCache && blocoObjeto.imgHeightCache && !blocoObjeto.imagemGeradaCache) { aplicarEstilosDeImagem(elementoVisor, blocoObjeto.imagemUrlCache, blocoObjeto.imgWidthCache, blocoObjeto.imgHeightCache, blocoObjeto); elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); return; } let urlImagemEstatica = null; if (context.listaImagens && context.listaImagens.size > 0 && blocoObjeto.tipo !== 'X') { const isPBlock = blocoObjeto.tipo.charAt(0) === 'P'; if (isPBlock) { const nomeArquivoP = getFinalImageName(blocoObjeto, 'p.png'); if (nomeArquivoP && context.listaImagens.has(nomeArquivoP)) urlImagemEstatica = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoP)}`; } if (!urlImagemEstatica) { const nomeArquivoPadrao = getFinalImageName(blocoObjeto, '.png'); if (nomeArquivoPadrao && context.listaImagens.has(nomeArquivoPadrao)) urlImagemEstatica = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoPadrao)}`; } } if (urlImagemEstatica) { elementoVisor.parentElement.classList.add('bloco-carregando-imagem'); const image = new Image(); image.onload = () => { const dimensions = { width: image.width, height: image.height }; DADOS_IMAGEM_CACHE.set(urlImagemEstatica, dimensions); blocoObjeto.imagemUrlCache = urlImagemEstatica; blocoObjeto.imgWidthCache = dimensions.width; blocoObjeto.imgHeightCache = dimensions.height; aplicarEstilosDeImagem(elementoVisor, urlImagemEstatica, dimensions.width, dimensions.height, blocoObjeto); elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); }; image.onerror = () => { elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); }; image.src = urlImagemEstatica; return; } const contentWrapperEl = elementoVisor.querySelector('.bloco-content-wrapper'); if (contentWrapperEl) { contentWrapperEl.style.display = 'flex'; } elementoVisor.style.padding = '8px'; elementoVisor.parentElement.classList.remove('bloco-carregando-imagem'); } async function gerarImagemComOutraImagem(blocoObjeto, nomeImagemOverlay, alinhamento, larguraParam = null) { const nomeArquivoFinal = getFinalImageName(blocoObjeto, 'b.png'); if (!nomeArquivoFinal) { return { success: false, reason: 'Imagem de fundo não encontrada' }; } const urlBase = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoFinal)}`; const nomeImagemOverlayNormalizado = nomeImagemOverlay.replace(/\\/g, '/'); if (!context.listaImagens.has(nomeImagemOverlayNormalizado)) { return { success: false, reason: `Imagem de sobreposição '${nomeImagemOverlayNormalizado}' não encontrada na lista` }; } const urlOverlay = `imagens/${nomeImagemOverlayNormalizado}`; try { const [imgBase, imgOverlay] = await Promise.all([ new Promise((resolve, reject) => { const i = new Image(); i.crossOrigin = "Anonymous"; i.onload = () => resolve(i); i.onerror = reject; i.src = urlBase; }), new Promise((resolve, reject) => { const i = new Image(); i.crossOrigin = "Anonymous"; i.onload = () => resolve(i); i.onerror = reject; i.src = urlOverlay; }) ]); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const finalCanvasWidth = imgBase.width; const scale = finalCanvasWidth / imgOverlay.width; const overlayFinalWidth = finalCanvasWidth; const overlayFinalHeight = imgOverlay.height * scale; // AJUSTE CIRÚRGICO: A altura do canvas acompanha estritamente a imagem, matando o padding superior matemático const finalCanvasHeight = Math.max(20, overlayFinalHeight); canvas.width = finalCanvasWidth; canvas.height = finalCanvasHeight; const corner = Math.min(10, imgBase.width / 2, imgBase.height / 2); ctx.drawImage(imgBase, 0, 0, corner, corner, 0, 0, corner, corner); ctx.drawImage(imgBase, imgBase.width - corner, 0, corner, corner, canvas.width - corner, 0, corner, corner); ctx.drawImage(imgBase, 0, imgBase.height - corner, corner, corner, 0, canvas.height - corner, corner, corner); ctx.drawImage(imgBase, imgBase.width - corner, imgBase.height - corner, corner, corner, canvas.width - corner, canvas.height - corner, corner, corner); ctx.drawImage(imgBase, corner, 0, imgBase.width - 2 * corner, corner, corner, 0, canvas.width - 2 * corner, corner); ctx.drawImage(imgBase, corner, imgBase.height - corner, imgBase.width - 2 * corner, corner, corner, canvas.height - corner, canvas.width - 2 * corner, corner); ctx.drawImage(imgBase, 0, corner, corner, imgBase.height - 2 * corner, 0, corner, corner, canvas.height - 2 * corner); ctx.drawImage(imgBase, imgBase.width - corner, corner, corner, imgBase.height - 2 * corner, canvas.width - corner, corner, corner, canvas.height - 2 * corner); ctx.drawImage(imgBase, corner, corner, imgBase.width - 2 * corner, imgBase.height - 2 * corner, corner, corner, canvas.width - 2 * corner, canvas.height - 2 * corner); // AJUSTE CIRÚRGICO: O "y" foi zerado para encostar rigorosamente no topo const y = 0; const codigoAlinhamentoStr = String(alinhamento).split('~')[0].trim(); let x = (finalCanvasWidth - overlayFinalWidth) / 2; if (codigoAlinhamentoStr === '1' || codigoAlinhamentoStr === '3') { x = 0; } else if (codigoAlinhamentoStr === '2' || codigoAlinhamentoStr === '4') { x = finalCanvasWidth - overlayFinalWidth; } ctx.drawImage(imgOverlay, x, y, overlayFinalWidth, overlayFinalHeight); const dataUrl = canvas.toDataURL('image/png'); blocoObjeto.imagemGeradaCache = dataUrl; blocoObjeto.textoGeradoCache = nomeImagemOverlay; blocoObjeto.alinhamentoGeradoCache = alinhamento; blocoObjeto.larguraGeradoCache = larguraParam; blocoObjeto.imagemUrlCache = dataUrl; blocoObjeto.imgWidthCache = canvas.width; blocoObjeto.imgHeightCache = canvas.height; return { success: true, dataUrl: dataUrl }; } catch (error) { console.warn(`Falha ao gerar imagem com sobreposição para ${blocoObjeto.nome}:`, error); return { success: false, reason: 'Erro ao carregar imagens' }; } } async function criarBlocoFantasma(blocoInfo, paraSlotT = false) {         const fantasma = document.createElement('div');         fantasma.classList.add('bloco-fantasma-preview');         applyStyles(fantasma, {             ...context.estilosGlobais.blocoVisorBase,             margin: '0',             minHeight: '50px'         });         const tipoBase = blocoInfo.tipo.charAt(0);         if (tipoBase === 'L') applyStyles(fantasma, context.estilosGlobais.blocoL);         else if (tipoBase === 'P') applyStyles(fantasma, context.estilosGlobais.blocoP);         else if (tipoBase === 'T') applyStyles(fantasma, context.estilosGlobais.blocoT);         else if (tipoBase === 'S') applyStyles(fantasma, context.estilosGlobais.blocoS);         else if (tipoBase === 'O') applyStyles(fantasma, context.estilosGlobais.blocoO || context.estilosGlobais.blocoS);         else if (tipoBase === 'U') applyStyles(fantasma, context.estilosGlobais.blocoU || context.estilosGlobais.blocoS);         else if (tipoBase === 'R') applyStyles(fantasma, context.estilosGlobais.blocoU || context.estilosGlobais.blocoS);         else if (tipoBase === 'E') applyStyles(fantasma, context.estilosGlobais.blocoE);         else if (tipoBase === 'C') applyStyles(fantasma, context.estilosGlobais.blocoC);         else if (tipoBase === 'X') applyStyles(fantasma, context.estilosGlobais.blocoX);         applyStyles(fantasma, context.estilosGlobais.blocoFantasmaEstilo);         const nomeEl = document.createElement('div');         nomeEl.classList.add(context.editorId + '_nome-bloco-interno');         applyStyles(nomeEl, {             fontWeight: 'bold',             fontSize: '0.85em',             color: '#333',             marginBottom: '4px',             textAlign: 'center',             width: '100%'         });         const {             displayName         } = parseBlockName(blocoInfo.nome);         nomeEl.innerHTML = displayName || (tipoBase === 'T' ? 'Container T (Prévia)' : 'Bloco (Prévia)');         if (tipoBase === 'E' || tipoBase === 'C') {             let numBlocos = tipoBase === 'E' ? 3 : 2;             if (blocoInfo.subtipo) {                 const match = String(blocoInfo.subtipo).match(/\d+/);                 if (match && match[0]) {                     const n = parseInt(match[0], 10);                     if (!isNaN(n)) {                         if (tipoBase === 'E') numBlocos = n + 1;                         else if (tipoBase === 'C') numBlocos = 2;                     }                 }             }             nomeEl.textContent = `${displayName} (${numBlocos} blocos)`;         }         fantasma.appendChild(nomeEl);         let urlImagemValida = null;         if (context.listaImagens && context.listaImagens.size > 0 && blocoInfo.tipo !== 'X') {             const nomeBaseImagem = String(blocoInfo.texto).replace(/\s+/g, '_').toLowerCase();             if (blocoInfo.camposDefinidos && blocoInfo.valoresCampos) {                 for (const campoDef of blocoInfo.camposDefinidos) {                     if (campoDef.nome.endsWith('!')) {                         // AJUSTE CIRÚRGICO                         const valorParametro = getValorCampoNormalizado(blocoInfo.valoresCampos, campoDef.nome);                         if (valorParametro !== undefined && valorParametro !== null && String(valorParametro).trim() !== "") {                             const sufixoImagem = String(valorParametro).split('~')[0].trim();                             if (sufixoImagem) {                                 const nomeArquivoDinamico = `${nomeBaseImagem}${sufixoImagem}.png`;                                 if (context.listaImagens.has(nomeArquivoDinamico)) {                                     urlImagemValida = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoDinamico)}`;                                     break;                                 }                             }                         }                     }                 }             }             if (!urlImagemValida) {                 const nomeArquivoPadrao = `${nomeBaseImagem}.png`;                 if (context.listaImagens.has(nomeArquivoPadrao)) {                     urlImagemValida = `imagenssistema/blocos/${context.listaImagens.get(nomeArquivoPadrao)}`;                 }             }         }         if (urlImagemValida) {             const imgTest = await new Promise(resolve => {                 const i = new Image();                 i.onload = () => resolve(i);                 i.onerror = () => resolve(null);                 i.src = urlImagemValida;             });             if (imgTest) {                 applyStyles(fantasma, {                     backgroundImage: `url('${urlImagemValida}')`,                     backgroundSize: 'contain',                     backgroundRepeat: 'no-repeat',                     backgroundPosition: 'center center',                 });                 if (nomeEl) nomeEl.style.display = 'none';             }         }         if (['L', 'S', 'O', 'U', 'R', 'E', 'C'].includes(tipoBase)) {             applyStyles(fantasma, context.estilosGlobais.blocoRenderizadoL);         } else if (tipoBase === 'X') {             applyStyles(fantasma, context.estilosGlobais.blocoRenderizadoX);         } else if (tipoBase === 'P') {             applyStyles(fantasma, {                 flex: '0 0 100px'             });         } else if (tipoBase === 'T') {             applyStyles(fantasma, context.estilosGlobais.blocoRenderizadoTContainer);         }         return fantasma;     }     function limparFantasmasAtivos() {         document.querySelectorAll('.bloco-fantasma-preview, .fantasma-linha-p-preview').forEach(el => el.remove());         if (context.insertionMarkerEl && context.insertionMarkerEl.parentNode) {             context.insertionMarkerEl.parentNode.removeChild(context.insertionMarkerEl);         }     }     function criarFantasmaLinhaP() {         const fantasmaContainer = document.createElement('div');         applyStyles(fantasmaContainer, {             ...context.estilosGlobais.editorLinhaGrid,             padding: '4px',             border: '2px dashed #a0c4ff',             backgroundColor: 'rgba(200, 220, 255, 0.3)',             minHeight: '80px',             pointerEvents: 'none',             width: '100%'         });         const criarSlotFantasma = (texto) => {             const slot = document.createElement('div');             applyStyles(slot, {                 ...context.estilosGlobais.slotLinhaP,                 border: '1px dashed #90b4ef',                 backgroundColor: 'rgba(220, 235, 255, 0.5)',                 color: '#333',                 fontSize: '0.8em',                 alignItems: 'center',                 justifyContent: 'center',                 pointerEvents: 'auto'             });             slot.textContent = texto;             return slot;         };         const slotEsquerda = criarSlotFantasma('Solte na Esquerda');         const slotDireita = criarSlotFantasma('Solte na Direita');         slotEsquerda.dataset.ladoAlvo = 'esquerda';         slotDireita.dataset.ladoAlvo = 'direita';         fantasmaContainer.appendChild(slotEsquerda);         fantasmaContainer.appendChild(slotDireita);         return fantasmaContainer;     } function criarElementoBloco(bloco, contexto = {}) {     const divBloco = document.createElement('div');     divBloco.classList.add('bloco-renderizado');     applyStyles(divBloco, context.estilosGlobais.blocoRenderizadoBase);     divBloco.dataset.blocoId = bloco.id;     if (bloco.groupId) divBloco.dataset.groupId = bloco.groupId;     const blocoVisor = document.createElement('div');     blocoVisor.className = 'bloco-visor';     applyStyles(blocoVisor, context.estilosGlobais.blocoVisorBase);     divBloco.appendChild(blocoVisor);     if (!blocoEstaValido(bloco)) {         divBloco.classList.add('bloco-invalido');     }     const isBlockType2x = bloco.camposDefinidos && bloco.camposDefinidos.some(c => c.nome.includes('$[21]'));          let estiloLayout = {};     const tipoBase = bloco.tipo.charAt(0);     if (tipoBase === 'P') {         if (contexto.idDoTPai) {             estiloLayout = { flex: '0 0 auto', height: '100%', maxWidth: '160px' };         } else if (contexto.dentroDeLinhaP || contexto.dentroDeColunaE) {             estiloLayout = { flex: '1 1 auto', width: '100%', maxWidth: '100%', height: 'auto' };         }         applyStyles(blocoVisor, context.estilosGlobais.blocoP);     } else if (['L', 'S', 'O', 'U', 'R'].includes(tipoBase)) {         estiloLayout = { ...context.estilosGlobais.blocoRenderizadoL };         if (tipoBase === 'L' && contexto.dentroDeColunaE) {             Object.assign(estiloLayout, {                 flexBasis: '100%',                  flexShrink: '0'              });         }         applyStyles(blocoVisor, context.estilosGlobais[`bloco${tipoBase}`] || context.estilosGlobais.blocoS);     } else if (tipoBase === 'E') {         estiloLayout = context.estilosGlobais.blocoRenderizadoE;         applyStyles(blocoVisor, context.estilosGlobais.blocoE);     } else if (tipoBase === 'C') {         estiloLayout = context.estilosGlobais.blocoRenderizadoE;         applyStyles(blocoVisor, context.estilosGlobais.blocoC);     } else if (tipoBase === 'T') {         estiloLayout = context.estilosGlobais.blocoRenderizadoTContainer;         const isBlockType4x = bloco.camposDefinidos && bloco.camposDefinidos.some(c => c.nome.includes('$[4'));         const visorStyle = { ...context.estilosGlobais.blocoT };         if (isBlockType4x) visorStyle.justifyContent = 'space-between';         applyStyles(blocoVisor, visorStyle);     } else if (tipoBase === 'X') {         estiloLayout = context.estilosGlobais.blocoRenderizadoX;         applyStyles(blocoVisor, context.estilosGlobais.blocoX);     }          applyStyles(divBloco, estiloLayout);          if (tipoBase === 'P' && contexto.dentroDeColunaE) {         divBloco.classList.add('bloco-p-dentro-de-e');     }     if (isBlockType2x && contexto.dentroDeColunaE) {         divBloco.classList.add('bloco-2x-dentro-de-e');     }     if (contexto.dentroDeColunaE) {         divBloco.classList.add(`${context.editorId}_bloco-dentro-coluna-e`);         if (bloco.tipo.startsWith('T')) divBloco.classList.add('bloco-t-em-coluna');     }     divBloco.draggable = true;     const isGroupHeader = (bloco.tipo.startsWith('E') || bloco.tipo.startsWith('C')) && bloco.groupIndex === 0;     const isInMainList = !contexto.idDoTPai && !contexto.dentroDeLinhaP && !contexto.dentroDeColunaE;     const contentWrapper = document.createElement('div');     contentWrapper.className = 'bloco-content-wrapper';     applyStyles(contentWrapper, { display: 'flex', flexDirection: 'row', alignItems: 'center', width: '100%' });     let toggle = null;     if (isGroupHeader) {         divBloco.classList.add('bloco-grupo-cabecalho');         toggle = document.createElement('div');         toggle.className = 'accordion-toggle';         toggle.textContent = bloco.isCollapsed ? '▶' : '▼';         applyStyles(toggle, context.estilosGlobais.accordionToggle);         contentWrapper.appendChild(toggle);     } else if (isInMainList) {         const placeholder = document.createElement('div');         placeholder.className = 'accordion-placeholder';         applyStyles(placeholder, context.estilosGlobais.accordionToggle);         placeholder.style.visibility = 'hidden';         contentWrapper.appendChild(placeholder);     }     const nomeEl = document.createElement('div');     nomeEl.classList.add(context.editorId + '_nome-bloco-interno');     const { displayName } = parseBlockName(bloco.nome);     nomeEl.innerHTML = displayName;     if ((bloco.tipo.startsWith('E') || bloco.tipo.startsWith('C')) && bloco.groupSize > 0) {         if ((bloco.tipo.startsWith('E') && bloco.groupIndex === 0)) {             nomeEl.textContent = `${displayName} (Grupo de ${bloco.groupSize - 1} colunas)`;         } else if (bloco.tipo.startsWith('E') && bloco.groupIndex > 0) {             nomeEl.textContent = `${displayName} (Marcador ${bloco.groupIndex}/${bloco.groupSize - 1})`;         }     }     contentWrapper.appendChild(nomeEl);     blocoVisor.appendChild(contentWrapper);     if (isGroupHeader) { toggle.addEventListener('click', e => { e.stopPropagation(); bloco.isCollapsed = !bloco.isCollapsed; renderizarEditor(); }); }     if (bloco.camposDefinidos && Array.isArray(bloco.camposDefinidos) && bloco.camposDefinidos.length > 0) {         blocoVisor.style.cursor = 'pointer';         divBloco.title = 'Clique para editar parâmetros';         blocoVisor.addEventListener('click', (e) => {             if (e.target.classList.contains('accordion-toggle')) return;             e.stopPropagation();             if (typeof context.callbacks.abrir === 'function') {                 if (bloco.tipo === 'X' || !contexto.idDoTPai) {                     context.callbacks.abrir(bloco, null, null, null);                 } else {                     context.callbacks.abrir(bloco, contexto.idDoTPai, String(contexto.indiceLinhaT), contexto.posicaoSlotT);                 }             } else {                 console.error("[EditorDeBlocos] A função de callback 'abrir' não foi encontrada.");             }         });     } else if (divBloco.draggable && !isGroupHeader) {         divBloco.style.cursor = 'grab';     }     if (divBloco.draggable) {         // --- INÍCIO DA ALTERAÇÃO (Ícone ao arrastar para fora) ---         const handleDragOverForDelete = (e) => {             e.preventDefault();             e.dataTransfer.dropEffect = 'move'; // Muda o cursor de 'proibido' para 'mover'         };         divBloco.addEventListener('dragstart', async (e) => {             e.stopPropagation();             document.body.addEventListener('dragover', handleDragOverForDelete); // Adiciona listener global                          let dragData = { ...bloco, origem: 'editor_principal', id: bloco.id };             if (contexto.idDoTPai) {                 dragData.origem = 'slot_T';                 dragData.idDoTPai = contexto.idDoTPai;                 dragData.indiceLinhaT = contexto.indiceLinhaT;                 dragData.posicaoSlotT = contexto.posicaoSlotT;             } else if (contexto.dentroDeLinhaP) {                 dragData.origem = 'slot_P';                 dragData.idLinhaOrigem = contexto.idLinha;                 dragData.ladoSlotOrigem = contexto.ladoSlot;             } else if (bloco.tipo === 'X') {                 dragData.origem = 'x_container';             }             e.dataTransfer.setData('text/plain', JSON.stringify(dragData));             context.dadosArrastados = dragData;             context.elementoArrastadoOriginalDOM = divBloco;             setTimeout(() => { divBloco.classList.add('dragging-original-hidden'); }, 0);         });         divBloco.addEventListener('dragend', (e) => {             e.stopPropagation();             document.body.removeEventListener('dragover', handleDragOverForDelete); // Remove listener global                          if (context.elementoArrastadoOriginalDOM) {                 context.elementoArrastadoOriginalDOM.classList.remove('dragging-original-hidden');             }             limparFantasmasAtivos();             if (!context.dropOccurredInEditor && context.dadosArrastados) {                 excluirBloco(context.dadosArrastados.id);             }             context.dadosArrastados = null;             context.elementoArrastadoOriginalDOM = null;             context.dropOccurredInEditor = false;         });         // --- FIM DA ALTERAÇÃO ---     }     if (bloco.tipo.startsWith('T')) {         const isBlockType4x = bloco.camposDefinidos && bloco.camposDefinidos.some(c => c.nome.includes('$[4'));         for (let i = 0; i < 3; i++) {             const linhaInternaDivT = document.createElement('div'); const estiloLinhaInterna = { ...context.estilosGlobais.linhaInternaT }; if (isBlockType4x) { const minHeightValue = parseInt(estiloLinhaInterna.minHeight, 10) || 50; estiloLinhaInterna.maxHeight = `${minHeightValue * 2}px`; } applyStyles(linhaInternaDivT, estiloLinhaInterna);             const slotEsquerdoT = document.createElement('div');             let estiloSlotEsquerdo = { ...context.estilosGlobais.slotT, ...context.estilosGlobais.slotTInicio };             if (isBlockType4x) {                 estiloSlotEsquerdo.flexBasis = '45%';                 estiloSlotEsquerdo.minWidth = '45%';                 estiloSlotEsquerdo.maxWidth = '45%';             }             applyStyles(slotEsquerdoT, estiloSlotEsquerdo);             slotEsquerdoT.classList.add('slot-t'); slotEsquerdoT.dataset.idTPai = bloco.id; slotEsquerdoT.dataset.indiceLinhaT = String(i); slotEsquerdoT.dataset.posicaoSlotT = 'inicio'; configurarDropZoneSlotT(slotEsquerdoT); ((bloco.linhasInternas[i] && bloco.linhasInternas[i]['inicio']) || []).forEach(blocoP => { slotEsquerdoT.appendChild(criarElementoBloco(blocoP, { idLinha: contexto.idLinha, idDoTPai: bloco.id, indiceLinhaT: i, posicaoSlotT: 'inicio' })); }); linhaInternaDivT.appendChild(slotEsquerdoT);             const espacador = document.createElement('div'); applyStyles(espacador, { flexGrow: '1', minWidth: '10px' }); linhaInternaDivT.appendChild(espacador);             const slotDireitoT = document.createElement('div');             let estiloSlotDireito = { ...context.estilosGlobais.slotT, ...context.estilosGlobais.slotTFim };             if (isBlockType4x) {                 estiloSlotDireito.flexBasis = '45%';                 estiloSlotDireito.minWidth = '45%';                 estiloSlotDireito.maxWidth = '45%';             }             applyStyles(slotDireitoT, estiloSlotDireito);             slotDireitoT.classList.add('slot-t'); slotDireitoT.dataset.idTPai = bloco.id; slotDireitoT.dataset.indiceLinhaT = String(i); slotDireitoT.dataset.posicaoSlotT = 'fim'; configurarDropZoneSlotT(slotDireitoT); ((bloco.linhasInternas[i] && bloco.linhasInternas[i]['fim']) || []).forEach(blocoP => { slotDireitoT.appendChild(criarElementoBloco(blocoP, { idLinha: contexto.idLinha, idDoTPai: bloco.id, indiceLinhaT: i, posicaoSlotT: 'fim' })); }); linhaInternaDivT.appendChild(slotDireitoT);             blocoVisor.appendChild(linhaInternaDivT);         }     }     bloco._renderContext = { dentroDeColunaE: !!contexto.dentroDeColunaE };     setTimeout(() => carregarImagemParaBloco(blocoVisor, bloco, contexto), 0);     return divBloco; } function aplicarCorrecoesDeTamanhoFinais() { const editorId = context.editorId; if (!editorId) return; const ALTURA_FIXA_PX = 50; const colunasE = document.querySelectorAll(`#${editorId}_container .${context.editorId}_coluna-bloco-e`); colunasE.forEach(coluna => { const slotsPnaColuna = coluna.querySelectorAll('.slot-p-dentro-de-e'); slotsPnaColuna.forEach(slotContainer => { slotContainer.style.setProperty('height', `${ALTURA_FIXA_PX}px`, 'important'); slotContainer.style.setProperty('min-height', `${ALTURA_FIXA_PX}px`, 'important'); const blocosP = slotContainer.querySelectorAll('.bloco-p-dentro-de-e'); blocosP.forEach(blocoP_El => { const larguraExata = 'calc(100% / 3)'; blocoP_El.style.setProperty('flex-basis', larguraExata, 'important'); blocoP_El.style.setProperty('width', larguraExata, 'important'); blocoP_El.style.setProperty('flex-shrink', '1', 'important'); blocoP_El.style.setProperty('flex-grow', '0', 'important'); blocoP_El.style.setProperty('height', '100%', 'important'); }); }); const blocosLnaColuna = coluna.querySelectorAll(`.${editorId}_bloco-dentro-coluna-e`); blocosLnaColuna.forEach(blocoRenderizadoEl => { const blocoId = blocoRenderizadoEl.dataset.blocoId; if (!blocoId) return; const blocoObjeto = findBlockInContext(blocoId); if (blocoObjeto && blocoObjeto.tipo.startsWith('L')) { blocoRenderizadoEl.style.setProperty('width', '100%', 'important'); blocoRenderizadoEl.style.setProperty('flex-basis', '100%', 'important'); blocoRenderizadoEl.style.setProperty('flex-shrink', '0', 'important'); blocoRenderizadoEl.style.setProperty('margin-left', '0', 'important'); blocoRenderizadoEl.style.setProperty('margin-right', '0', 'important'); const temSinal3x = blocoObjeto.camposDefinidos?.some(c => c.nome.includes('$[31]')); if (temSinal3x) { // AJUSTE CIRÚRGICO: Removida a imposição de altura fixa (50px). // Isso causava a distorção (esticamento) dos outros botões, pois o botão // editado assumia a proporção natural ('auto') que é o visual correto. // blocoRenderizadoEl.style.setProperty('height', `${ALTURA_FIXA_PX}px`, 'important'); // const visor = blocoRenderizadoEl.querySelector('.bloco-visor'); // if(visor) { // visor.style.setProperty('height', '100%', 'important'); // } } } }); }); const blocos2xParaAjustar = document.querySelectorAll(`#${editorId}_container .bloco-2x-dentro-de-e`); blocos2xParaAjustar.forEach(bloco2x => { const colunaContainer = bloco2x.closest(`.${editorId}_coluna-bloco-e`); if (colunaContainer) { const blocoId = bloco2x.dataset.blocoId; const blocoObjeto = findBlockInContext(blocoId); if (blocoObjeto && !blocoObjeto.tipo.startsWith('L')) { const larguraIdealPx = Math.floor(colunaContainer.getBoundingClientRect().width * 0.5); bloco2x.style.setProperty('flex-grow', '0', 'important'); bloco2x.style.setProperty('flex-shrink', '0', 'important'); bloco2x.style.setProperty('width', `${larguraIdealPx}px`, 'important'); bloco2x.style.setProperty('flex-basis', `${larguraIdealPx}px`, 'important'); let alinhamento = '0'; if (blocoObjeto && blocoObjeto.camposDefinidos && blocoObjeto.valoresCampos) { const campoAlinhamentoDef = blocoObjeto.camposDefinidos.find(c => c.nome.includes('$[22]')); if (campoAlinhamentoDef) { const valorAlinhamentoRaw = getValorCampoNormalizado(blocoObjeto.valoresCampos, campoAlinhamentoDef.nome); if (valorAlinhamentoRaw) { alinhamento = String(valorAlinhamentoRaw).split('~')[0].trim(); } } } if (alinhamento === '1' || alinhamento === '3') { bloco2x.style.setProperty('margin-left', '0', 'important'); bloco2x.style.setProperty('margin-right', 'auto', 'important'); } else if (alinhamento === '2' || alinhamento === '4') { bloco2x.style.setProperty('margin-left', 'auto', 'important'); bloco2x.style.setProperty('margin-right', '0', 'important'); } else { bloco2x.style.setProperty('margin-left', 'auto', 'important'); bloco2x.style.setProperty('margin-right', 'auto', 'important'); } } } }); } function renderizarLinhaUnica(linhaObj, originalIndex, linhasIndentadas, dentroDeColunaE = false) {     const editorLinhaDiv = document.createElement('div');     const blocoDaLinha = linhaObj.blocos && linhaObj.blocos[0];     if (blocoDaLinha && blocoDaLinha.groupId) {         const cabecalhoDoGrupo = context.linhasDoEditor.flatMap(l => l.blocos || []).find(b => b.groupId === blocoDaLinha.groupId && b.groupIndex === 0);         if (cabecalhoDoGrupo && cabecalhoDoGrupo.tipo.startsWith('C') && !dentroDeColunaE) {             if (linhasIndentadas.has(linhaObj.idLinha)) {                 editorLinhaDiv.style.marginLeft = `${INDENTATION_SIZE_PX}px`;                 editorLinhaDiv.style.width = `calc(100% - ${INDENTATION_SIZE_PX}px)`;             }         }     }     applyStyles(editorLinhaDiv, linhaObj.tipoLinhaOrigem === 'P' ? context.estilosGlobais.editorLinhaGrid : context.estilosGlobais.editorLinhaFlex);     editorLinhaDiv.dataset.idLinha = linhaObj.idLinha;     editorLinhaDiv.dataset.tipoLinha = linhaObj.tipoLinhaOrigem;     if (['S', 'O', 'U', 'R'].includes(linhaObj.tipoLinhaOrigem)) {         const blocoDef = context.blocosDisponiveis.find(b => b.tipo === linhaObj.tipoLinhaOrigem);         if (blocoDef) {             const dummyBlock = { ...blocoDef, id: linhaObj.idLinha, valoresCampos: {} };             const elementoBloco = criarElementoBloco(dummyBlock, { idLinha: linhaObj.idLinha, dentroDeColunaE: dentroDeColunaE });             editorLinhaDiv.appendChild(elementoBloco);         }     } else if (linhaObj.tipoLinhaOrigem === 'P') {         const slotEsquerdaDiv = document.createElement('div');         slotEsquerdaDiv.classList.add('slot-linha-p', 'slot-esquerda');                  // [MODIFICAÇÃO 1] Aplica um estilo base que pode ser ajustado         const estiloBaseSlot = { ...context.estilosGlobais.slotLinhaP };         if (dentroDeColunaE) {             estiloBaseSlot.gap = '0px'; // Remove o espaçamento entre os blocos P         }         applyStyles(slotEsquerdaDiv, { ...estiloBaseSlot, justifyContent: 'flex-start' });                  const slotDireitaDiv = document.createElement('div');         slotDireitaDiv.classList.add('slot-linha-p', 'slot-direita');         applyStyles(slotDireitaDiv, { ...estiloBaseSlot, justifyContent: 'flex-end' });         if (dentroDeColunaE) {             slotEsquerdaDiv.classList.add('slot-p-dentro-de-e');             slotDireitaDiv.classList.add('slot-p-dentro-de-e');         }         slotEsquerdaDiv.dataset.ladoSlot = 'esquerda';         // [MODIFICAÇÃO 2] Passa o contexto 'dentroDeColunaE' para a função de drop zone         configurarDropZoneSlotP(slotEsquerdaDiv, linhaObj, 'esquerda', dentroDeColunaE);         (linhaObj.slots.esquerda || []).forEach(blocoP => {             const elemBlocoP = criarElementoBloco(blocoP, { idLinha: linhaObj.idLinha, dentroDeLinhaP: true, ladoSlot: 'esquerda', dentroDeColunaE: dentroDeColunaE });             slotEsquerdaDiv.appendChild(elemBlocoP);         });         // [MODIFICAÇÃO 3] O espaçador que empurra os blocos só é adicionado FORA de uma coluna E         if (!dentroDeColunaE) {             const spacerEsq = document.createElement('div');             applyStyles(spacerEsq, { flex: '1 1 auto', minWidth: '5px' });             slotEsquerdaDiv.appendChild(spacerEsq);         }         editorLinhaDiv.appendChild(slotEsquerdaDiv);         slotDireitaDiv.dataset.ladoSlot = 'direita';         configurarDropZoneSlotP(slotDireitaDiv, linhaObj, 'direita', dentroDeColunaE);         if (!dentroDeColunaE) {             const spacerDir = document.createElement('div');             applyStyles(spacerDir, { flex: '1 1 auto', minWidth: '5px' });             slotDireitaDiv.appendChild(spacerDir);         }         (linhaObj.slots.direita || []).forEach(blocoP => {             const elemBlocoP = criarElementoBloco(blocoP, { idLinha: linhaObj.idLinha, dentroDeLinhaP: true, ladoSlot: 'direita', dentroDeColunaE: dentroDeColunaE });             slotDireitaDiv.appendChild(elemBlocoP);         });         editorLinhaDiv.appendChild(slotDireitaDiv);     } else if (linhaObj.blocos && linhaObj.blocos.length > 0) {         linhaObj.blocos.forEach(bloco => {             const elemBloco = criarElementoBloco(bloco, { idLinha: linhaObj.idLinha, dentroDeColunaE: dentroDeColunaE });             editorLinhaDiv.appendChild(elemBloco);         });     }     return editorLinhaDiv; }     function renderizarEditor(source = 'internal') {     const scrollTop = context.painelEditorWrapperEl.scrollTop;     context.painelEditorEl.innerHTML = '';     context.xBlocksContainerEl = document.createElement('div');     applyStyles(context.xBlocksContainerEl, context.estilosGlobais.xContainer);     configurarDropZoneContainerX(context.xBlocksContainerEl);     context.painelEditorEl.appendChild(context.xBlocksContainerEl);     context.xBlocks.forEach(blocoX => {         context.xBlocksContainerEl.appendChild(criarElementoBloco(blocoX));     });     const groupHeaders = {};     context.linhasDoEditor.forEach(linha => {         const bloco = linha.blocos && linha.blocos[0];         if (bloco && bloco.groupId && bloco.groupIndex === 0) {             groupHeaders[bloco.groupId] = bloco;         }     });     const indicesOcultos = new Set();     const linhasIndentadas = new Set();     Object.values(groupHeaders).forEach(header => {         if (!header.tipo.startsWith('C') && !header.tipo.startsWith('E')) return;         const groupLinesInfo = context.linhasDoEditor.map((linha, index) => ({ linha, index }))             .filter(item => item.linha.blocos && item.linha.blocos[0] && item.linha.blocos[0].groupId === header.groupId);         if (groupLinesInfo.length > 0) {             const startIndex = groupLinesInfo[0].index;             const endIndex = groupLinesInfo[groupLinesInfo.length - 1].index;             for (let i = startIndex + 1; i < endIndex; i++) {                 if (context.linhasDoEditor[i]) {                     linhasIndentadas.add(context.linhasDoEditor[i].idLinha);                     if (header.isCollapsed) {                         indicesOcultos.add(i);                     }                 }             }             if (header.isCollapsed) {                 indicesOcultos.add(endIndex);             }         }     });     const linhasVisiveis = context.linhasDoEditor.map((l, i) => ({ ...l, originalIndex: i })).filter((_, index) => !indicesOcultos.has(index));     if (linhasVisiveis.length === 0 && context.xBlocks.length === 0) {         const emptyEl = document.createElement('p');         emptyEl.textContent = 'Arraste blocos para começar';         applyStyles(emptyEl, { textAlign: 'center', color: '#888', margin: '20px 0', fontSize: '0.8em' });         context.painelEditorEl.appendChild(emptyEl);     }     const linhasJaRenderizadas = new Set();     for (let i = 0; i < linhasVisiveis.length; i++) {         const linhaObj = linhasVisiveis[i];         if (linhasJaRenderizadas.has(linhaObj.idLinha)) {             continue;         }         const blocoPrincipal = linhaObj.blocos && linhaObj.blocos[0];         if (blocoPrincipal && blocoPrincipal.tipo.startsWith('E') && blocoPrincipal.groupIndex === 0) {             const grupoEWrapper = document.createElement('div');             grupoEWrapper.className = `${context.editorId}_grupo-bloco-e-wrapper`;             applyStyles(grupoEWrapper, context.estilosGlobais.blocoEGrupoWrapper);             grupoEWrapper.dataset.groupId = blocoPrincipal.groupId;             if (!blocoEstaValido(blocoPrincipal)) {                 grupoEWrapper.classList.add('bloco-invalido');             }             context.painelEditorEl.appendChild(criarPlaceholderDrop(linhaObj.originalIndex));             const elementoCabecalho = criarElementoBloco(blocoPrincipal, { idLinha: linhaObj.idLinha });             grupoEWrapper.appendChild(elementoCabecalho);             linhasJaRenderizadas.add(linhaObj.idLinha);             if (!blocoPrincipal.isCollapsed) {                 const colunasContainer = document.createElement('div');                 applyStyles(colunasContainer, context.estilosGlobais.blocoEColunasContainer);                 grupoEWrapper.appendChild(colunasContainer);                 const groupId = blocoPrincipal.groupId;                 const groupMarkers = context.linhasDoEditor.map((linha, index) => ({ linha, index }))                     .filter(item => item.linha.blocos ?.[0]?.groupId === groupId)                     .sort((a, b) => a.linha.blocos[0].groupIndex - b.linha.blocos[0].groupIndex);                 groupMarkers.forEach(markerInfo => linhasJaRenderizadas.add(markerInfo.linha.idLinha));                 for (let j = 0; j < groupMarkers.length - 1; j++) {                     const colunaDiv = document.createElement('div');                     colunaDiv.className = `${context.editorId}_coluna-bloco-e`;                     applyStyles(colunaDiv, context.estilosGlobais.blocoEColuna);                     colunasContainer.appendChild(colunaDiv);                     const startIndexConteudo = groupMarkers[j].index + 1;                     const endIndexConteudo = groupMarkers[j + 1].index;                     colunaDiv.dataset.targetIndex = endIndexConteudo;                     colunaDiv.addEventListener('dragover', (e) => { e.preventDefault(); e.stopPropagation(); const dados = context.dadosArrastados; if (dados && !['X', 'P'].includes(dados.tipo.charAt(0))) { colunaDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.05)'; } });                     colunaDiv.addEventListener('dragleave', (e) => { e.preventDefault(); e.stopPropagation(); colunaDiv.style.backgroundColor = 'transparent'; });                     colunaDiv.addEventListener('drop', (e) => { context.dropOccurredInEditor = true; e.preventDefault(); e.stopPropagation(); colunaDiv.style.backgroundColor = 'transparent'; const dados = context.dadosArrastados; if (dados && e.target === colunaDiv) { processarDadosTransferidos(dados, parseInt(colunaDiv.dataset.targetIndex)); } });                     colunaDiv.appendChild(criarPlaceholderDrop(startIndexConteudo));                     for (let k = startIndexConteudo; k < endIndexConteudo; k++) {                         if (indicesOcultos.has(k)) continue;                         const linhaConteudo = context.linhasDoEditor[k];                         linhasJaRenderizadas.add(linhaConteudo.idLinha);                         const linhaRenderizada = renderizarLinhaUnica(linhaConteudo, k, linhasIndentadas, true);                         colunaDiv.appendChild(linhaRenderizada);                         colunaDiv.appendChild(criarPlaceholderDrop(k + 1));                     }                 }             }             context.painelEditorEl.appendChild(grupoEWrapper);         } else {             context.painelEditorEl.appendChild(criarPlaceholderDrop(linhaObj.originalIndex));             const editorLinhaDiv = renderizarLinhaUnica(linhaObj, linhaObj.originalIndex, linhasIndentadas);             context.painelEditorEl.appendChild(editorLinhaDiv);             linhasJaRenderizadas.add(linhaObj.idLinha);         }     }     const placeholderFinal = criarPlaceholderDrop(context.linhasDoEditor.length);     applyStyles(placeholderFinal, { ...context.estilosGlobais.dragPlaceholder, padding: '10px 0', minHeight: '30px', opacity: '0' });     placeholderFinal.dataset.isFinal = 'true';     context.painelEditorEl.appendChild(placeholderFinal);     if (source === 'internal') {         atualizarControle();     }     context.painelEditorWrapperEl.scrollTop = scrollTop;     // ============================ CHAMADA DA NOVA FUNÇÃO DE CORREÇÃO ============================     // Usamos setTimeout para garantir que esta função rode DEPOIS que o navegador     // renderizou todos os elementos e podemos medir seus tamanhos corretamente.     setTimeout(() => aplicarCorrecoesDeTamanhoFinais(), 0);     // ============================ FIM DA CHAMADA ============================ }     function atualizarParametrosDeLado(bloco, contexto) {         if (bloco.tipo !== 'P' || !bloco.camposDefinidos) {             return;         }         const estaEmT = !!contexto.idDoTPai;         const lado = contexto.ladoSlot || contexto.posicaoSlotT;         let novoValor;         if (estaEmT) {             novoValor = (lado === 'inicio') ? '3' : '4';         } else {             novoValor = (lado === 'esquerda') ? '3' : '4';         }         bloco.camposDefinidos.forEach(campoDef => {             if (campoDef.nome.includes('&')) {                 if (!bloco.valoresCampos) {                     bloco.valoresCampos = {};                 }                 bloco.valoresCampos[campoDef.nome] = novoValor;             }         });     }     function isDroppingInsideGroup(insertionIndex, draggedBlock) {         const draggedType = draggedBlock.tipo.charAt(0);         if (draggedType !== 'C' && draggedType !== 'E') {             return false;         }         const draggedGroupId = draggedBlock.groupId;         let draggedGroupingId = draggedBlock.groupingId;         if (draggedType === 'C' && !draggedGroupId) {             const groupingIdMatch = String(draggedBlock.subtipo).match(/\d+/);             draggedGroupingId = groupingIdMatch ? groupingIdMatch[0] : null;         }         const groups = {};         context.linhasDoEditor.forEach((linha, index) => {             const bloco = linha.blocos && linha.blocos[0];             if (bloco && (bloco.tipo.startsWith('E') || bloco.tipo.startsWith('C')) && bloco.groupId) {                 if (!groups[bloco.groupId]) {                     groups[bloco.groupId] = {                         indices: [],                         type: bloco.tipo.charAt(0),                         groupingId: bloco.groupingId                     };                 }                 groups[bloco.groupId].indices.push(index);             }         });         for (const groupId in groups) {             if (groupId === draggedGroupId) {                 continue;             }             const groupInfo = groups[groupId];             const indices = groupInfo.indices.sort((a, b) => a - b);             if (indices.length > 0) {                 const minIndex = indices[0];                 const maxIndex = indices[indices.length - 1];                 if (insertionIndex > minIndex && insertionIndex <= maxIndex) {                     if (draggedType === 'C' && groupInfo.type === 'C') {                         if (String(draggedGroupingId) === String(groupInfo.groupingId)) {                             return true;                         }                     }                 }             }         }         return false;     } function configurarDropZoneSlotT(slotDiv) {     const originalBgColor = getEditorColor(context.config.cores.SLOT_T_FUNDO);     slotDiv.addEventListener('dragover', (e) => {         e.preventDefault();         e.stopPropagation();         const dados = context.dadosArrastados;         if (!dados || dados.tipo !== 'P') {             e.dataTransfer.dropEffect = 'none';             return;         }         const idTPaiAlvo = slotDiv.dataset.idTPai;         const indiceLinhaTAlvo = parseInt(slotDiv.dataset.indiceLinhaT);         const posicaoSlotTAlvo = slotDiv.dataset.posicaoSlotT;         let blocoPaiTAlvo = context.linhasDoEditor.flatMap(l => l.blocos).find(b => b.id === idTPaiAlvo);         if (!blocoPaiTAlvo || !blocoPaiTAlvo.linhasInternas || !blocoPaiTAlvo.linhasInternas[indiceLinhaTAlvo]) {             e.dataTransfer.dropEffect = 'none'; return;         }         const slotAlvoArray = blocoPaiTAlvo.linhasInternas[indiceLinhaTAlvo][posicaoSlotTAlvo] || [];         const isMovingFromSameSlot = dados.origem === 'slot_T' && dados.idDoTPai === idTPaiAlvo && String(dados.indiceLinhaT) === String(indiceLinhaTAlvo) && dados.posicaoSlotT === posicaoSlotTAlvo;         if (slotAlvoArray.length >= context.config.maxBlocosPorSlotT && !isMovingFromSameSlot) {             e.dataTransfer.dropEffect = 'none'; return;         }         e.dataTransfer.dropEffect = 'move';         slotDiv.style.backgroundColor = 'rgba(187, 222, 251, 0.7)';         // ALTERAÇÃO: Adiciona o indicador visual (a barra azul)         updateInsertionMarkerInSlotT(e, slotDiv);     });     slotDiv.addEventListener('dragleave', (e) => {         e.stopPropagation();         if (!slotDiv.contains(e.relatedTarget)) {             slotDiv.style.backgroundColor = originalBgColor;             limparFantasmasAtivos(); // Limpa o marcador ao sair         }     });     slotDiv.addEventListener('drop', (e) => {         // ... (o restante da sua função drop original permanece igual)         context.dropOccurredInEditor = true; e.preventDefault(); e.stopPropagation(); slotDiv.style.backgroundColor = originalBgColor; const dropTargetId = slotDiv.dataset.dropTargetIdInSlot; delete slotDiv.dataset.dropTargetIdInSlot;         limparFantasmasAtivos(); // Limpa o marcador no drop         const dadosTransferidos = context.dadosArrastados; if (!dadosTransferidos || dadosTransferidos.tipo !== 'P') { context.dadosArrastados = null; context.elementoArrastadoOriginalDOM = null; renderizarEditor(); return; }         const idTPaiAlvo = slotDiv.dataset.idTPai; const indiceLinhaTAlvo = parseInt(slotDiv.dataset.indiceLinhaT); const posicaoSlotTAlvo = slotDiv.dataset.posicaoSlotT; let blocoTAlvo = context.linhasDoEditor.flatMap(l => l.blocos).find(b => b.id === idTPaiAlvo); if (!blocoTAlvo || !blocoTAlvo.linhasInternas || !blocoTAlvo.linhasInternas[indiceLinhaTAlvo]) { context.dadosArrastados = null; context.elementoArrastadoOriginalDOM = null; renderizarEditor(); return; }         const slotAlvoArray = blocoTAlvo.linhasInternas[indiceLinhaTAlvo][posicaoSlotTAlvo] || []; let numBlocosNoSlot = slotAlvoArray.length; const isMovingFromSameSlot = dadosTransferidos.origem === 'slot_T' && dadosTransferidos.idDoTPai === idTPaiAlvo && String(dadosTransferidos.indiceLinhaT) === String(indiceLinhaTAlvo) && dadosTransferidos.posicaoSlotT === posicaoSlotTAlvo; let canDrop = true; if (numBlocosNoSlot >= context.config.maxBlocosPorSlotT) { if (isMovingFromSameSlot) { canDrop = true; } else if (dadosTransferidos.origem === 'paleta') { canDrop = false; } else if (!slotAlvoArray.find(b => b.id === dadosTransferidos.id)) { canDrop = false; } }         if (!canDrop) { renderizarEditor(); return; }         if (dadosTransferidos.origem === 'slot_T' && dadosTransferidos.idDoTPai && dadosTransferidos.id) { let tOriginario = context.linhasDoEditor.flatMap(l => l.blocos).find(b => b.id === dadosTransferidos.idDoTPai); if (tOriginario && tOriginario.linhasInternas && tOriginario.linhasInternas[dadosTransferidos.indiceLinhaT] && tOriginario.linhasInternas[dadosTransferidos.indiceLinhaT][dadosTransferidos.posicaoSlotT]) { tOriginario.linhasInternas[dadosTransferidos.indiceLinhaT][dadosTransferidos.posicaoSlotT] = tOriginario.linhasInternas[dadosTransferidos.indiceLinhaT][dadosTransferidos.posicaoSlotT].filter(p => p.id !== dadosTransferidos.id); } } else if (dadosTransferidos.origem === 'editor_principal' && dadosTransferidos.id) { removerBlocoDaEstruturaPrincipal(dadosTransferidos.id); } else if (dadosTransferidos.origem === 'slot_P' && dadosTransferidos.idLinhaOrigem && dadosTransferidos.id) { const linhaPOrigem = context.linhasDoEditor.find(l => l.idLinha === dadosTransferidos.idLinhaOrigem); if (linhaPOrigem && linhaPOrigem.slots && linhaPOrigem.slots[dadosTransferidos.ladoSlotOrigem]) { linhaPOrigem.slots[dadosTransferidos.ladoSlotOrigem] = linhaPOrigem.slots[dadosTransferidos.ladoSlotOrigem].filter(b => b.id !== dadosTransferidos.id); if (linhaPOrigem.slots.esquerda.length === 0 && linhaPOrigem.slots.direita.length === 0) { context.linhasDoEditor = context.linhasDoEditor.filter(l => l.idLinha !== linhaPOrigem.idLinha); } } }         let blocoParaSlot; if (dadosTransferidos.origem === 'paleta') { blocoParaSlot = { ...dadosTransferidos, id: gerarIdUnico(`${context.editorId}_blocoP_interno_`), tipo: 'P', valoresCampos: {} }; } else { blocoParaSlot = { ...dadosTransferidos }; }         atualizarParametrosDeLado(blocoParaSlot, { idDoTPai: idTPaiAlvo, posicaoSlotT: posicaoSlotTAlvo }); if (!Array.isArray(blocoTAlvo.linhasInternas[indiceLinhaTAlvo][posicaoSlotTAlvo])) { blocoTAlvo.linhasInternas[indiceLinhaTAlvo][posicaoSlotTAlvo] = []; }         const slotDestinoArray = blocoTAlvo.linhasInternas[indiceLinhaTAlvo][posicaoSlotTAlvo]; const jaExisteIdx = slotDestinoArray.findIndex(b => b.id === blocoParaSlot.id); if (jaExisteIdx !== -1) { slotDestinoArray.splice(jaExisteIdx, 1); }         if (dropTargetId) { const targetIndex = slotDestinoArray.findIndex(b => b.id === dropTargetId); if (targetIndex !== -1) { const jaArrastado = slotDestinoArray.findIndex(b=>b.id === blocoParaSlot.id); if(jaArrastado > -1 && jaArrastado < targetIndex){ slotDestinoArray.splice(targetIndex, 0, blocoParaSlot); } else { slotDestinoArray.splice(targetIndex + 1, 0, blocoParaSlot); } } else slotDestinoArray.push(blocoParaSlot); } else { slotDestinoArray.push(blocoParaSlot); }         context.dadosArrastados = null; context.elementoArrastadoOriginalDOM = null; recarregarImagemDoBloco(idTPaiAlvo); setTimeout(() => renderizarEditor(), 0);     }); }     function configurarDropZoneContainerX(container) {         container.addEventListener('dragover', (e) => {             e.preventDefault();             e.stopPropagation();             const dados = context.dadosArrastados;             if (!dados || dados.tipo !== 'X') {                 e.dataTransfer.dropEffect = 'none';                 container.style.backgroundColor = '';                 return;             }             e.dataTransfer.dropEffect = 'move';             container.style.backgroundColor = 'rgba(0, 0, 0, 0.05)';         });         container.addEventListener('dragleave', (e) => {             e.preventDefault();             e.stopPropagation();             container.style.backgroundColor = '';         });         container.addEventListener('drop', (e) => {             context.dropOccurredInEditor = true;             e.preventDefault();             e.stopPropagation();             container.style.backgroundColor = '';             const dadosParaProcessar = context.dadosArrastados;             if (!dadosParaProcessar || dadosParaProcessar.tipo !== 'X') {                 return;             }             processarDadosTransferidos(dadosParaProcessar, -1);             context.dadosArrastados = null;             context.elementoArrastadoOriginalDOM = null;         });     }     function configurarPlaceholderDropX(placeholder) {         placeholder.addEventListener('dragover', (e) => {             e.preventDefault();             e.stopPropagation();             const dados = context.dadosArrastados;             if (!dados || dados.tipo !== 'X') {                 e.dataTransfer.dropEffect = 'none';                 return;             }             e.dataTransfer.dropEffect = 'move';             applyStyles(placeholder, { ...context.estilosGlobais.dragPlaceholderVisibleBase,                 padding: '10px 0',                 minHeight: '30px',                 backgroundColor: 'rgba(200,200,200,0.5)'             });         });         placeholder.addEventListener('dragleave', (e) => {             e.preventDefault();             e.stopPropagation();             applyStyles(placeholder, { ...context.estilosGlobais.dragPlaceholder,                 minHeight: '20px'             });         });         placeholder.addEventListener('drop', (e) => {             context.dropOccurredInEditor = true;             e.preventDefault();             e.stopPropagation();             applyStyles(placeholder, { ...context.estilosGlobais.dragPlaceholder,                 minHeight: '20px'             });             const dadosParaProcessar = context.dadosArrastados;             if (!dadosParaProcessar || dadosParaProcessar.tipo !== 'X') {                 return;             }             processarDadosTransferidos(dadosParaProcessar, -1);             context.dadosArrastados = null;             context.elementoArrastadoOriginalDOM = null;         });     }     function criarPlaceholderDrop(targetIndex) {         const dropPlaceholder = document.createElement('div');         applyStyles(dropPlaceholder, context.estilosGlobais.dragPlaceholder);         dropPlaceholder.dataset.targetLinhaIndex = String(targetIndex);         dropPlaceholder.addEventListener('dragover', (e) => {             e.preventDefault();             e.stopPropagation();             limparFantasmasAtivos();             const dados = context.dadosArrastados;             if (!dados || dados.tipo === 'X' || isDroppingInsideGroup(targetIndex, dados)) {                 e.dataTransfer.dropEffect = 'none';                 return;             }             e.dataTransfer.dropEffect = 'move';             if (dados.tipo === 'P' && dados.origem === 'paleta') {                 const fantasmaLinhaP = criarFantasmaLinhaP();                 fantasmaLinhaP.classList.add('fantasma-linha-p-preview');                 dropPlaceholder.appendChild(fantasmaLinhaP);                 fantasmaLinhaP.querySelectorAll('[data-lado-alvo]').forEach(slot => {                     slot.addEventListener('dragover', (ev) => {                         ev.preventDefault();                         ev.stopPropagation();                         dropPlaceholder.dataset.ladoAlvo = slot.dataset.ladoAlvo;                         applyStyles(slot, {                             backgroundColor: 'rgba(150, 190, 255, 0.7)'                         });                     });                     slot.addEventListener('dragleave', (ev) => {                         ev.stopPropagation();                         applyStyles(slot, {                             backgroundColor: 'rgba(220, 235, 255, 0.5)'                         });                     });                 });                 applyStyles(dropPlaceholder, { ...context.estilosGlobais.dragPlaceholderVisibleBase,                     minHeight: 'auto',                     padding: '0',                     opacity: '1',                     width: '100%'                 });             } else {                 criarBlocoFantasma(dados).then(fantasma => {                     if (!fantasma) return;                     dropPlaceholder.appendChild(fantasma);                 });                 applyStyles(dropPlaceholder, { ...context.estilosGlobais.dragPlaceholderVisibleBase,                     padding: '4px 0',                     minHeight: 'auto',                     opacity: '1'                 });             }         });         dropPlaceholder.addEventListener('dragleave', (e) => {             e.preventDefault();             e.stopPropagation();             if (!dropPlaceholder.contains(e.relatedTarget)) {                 limparFantasmasAtivos();                 delete dropPlaceholder.dataset.ladoAlvo;                 const estiloInativo = { ...context.estilosGlobais.dragPlaceholder                 };                 if (dropPlaceholder.dataset.isFinal === 'true') {                     if (context.linhasDoEditor.length === 0 && parseInt(dropPlaceholder.dataset.targetLinhaIndex) === 0) estiloInativo.minHeight = '30px';                     else estiloInativo.minHeight = '1px';                 }                 applyStyles(dropPlaceholder, estiloInativo);             }         });         dropPlaceholder.addEventListener('drop', (e) => {             context.dropOccurredInEditor = true;             e.preventDefault();             e.stopPropagation();             const indiceAlvo = parseInt(dropPlaceholder.dataset.targetLinhaIndex);             const ladoAlvo = dropPlaceholder.dataset.ladoAlvo || 'esquerda';             limparFantasmasAtivos();             delete dropPlaceholder.dataset.ladoAlvo;             const estiloInativo = { ...context.estilosGlobais.dragPlaceholder             };             if (dropPlaceholder.dataset.isFinal === 'true') {                 if (context.linhasDoEditor.length === 0 && indiceAlvo === 0) estiloInativo.minHeight = '30px';                 else estiloInativo.minHeight = '1px';             }             applyStyles(dropPlaceholder, estiloInativo);             document.querySelectorAll('.dragging-original-hidden').forEach(el => el.classList.remove('dragging-original-hidden'));             const dadosParaProcessar = context.dadosArrastados;             if (!dadosParaProcessar || typeof dadosParaProcessar.tipo === 'undefined' || isDroppingInsideGroup(indiceAlvo, dadosParaProcessar)) {                 context.dadosArrastados = null;                 context.elementoArrastadoOriginalDOM = null;                 renderizarEditor();                 return;             }             processarDadosTransferidos(dadosParaProcessar, indiceAlvo, ladoAlvo);             context.dadosArrastados = null;             context.elementoArrastadoOriginalDOM = null;         });         return dropPlaceholder;     }     function updateInsertionMarkerInSlotP(e, slotDiv) {         limparFantasmasAtivos();         const children = Array.from(slotDiv.querySelectorAll('[data-bloco-id]'));         let targetElement = null;         let insertBefore = false;         for (const child of children) {             const rect = child.getBoundingClientRect();             const midX = rect.left + rect.width / 2;             if (e.clientX < midX) {                 targetElement = child;                 insertBefore = true;                 break;             }             targetElement = child;             insertBefore = false;         }         if (targetElement) {             if (insertBefore) {                 slotDiv.insertBefore(context.insertionMarkerEl, targetElement);                 slotDiv.dataset.dropTargetId = targetElement.dataset.blocoId;                 slotDiv.dataset.insertBefore = "true";             } else {                 slotDiv.insertBefore(context.insertionMarkerEl, targetElement.nextSibling);                 slotDiv.dataset.dropTargetId = targetElement.dataset.blocoId;                 slotDiv.dataset.insertBefore = "false";             }         } else {             const spacer = slotDiv.querySelector('div[style*="flex: 1 1 auto"]');             if (spacer) {                 slotDiv.insertBefore(context.insertionMarkerEl, spacer);             } else {                 slotDiv.appendChild(context.insertionMarkerEl);             }             delete slotDiv.dataset.dropTargetId;             delete slotDiv.dataset.insertBefore;         }     }     function configurarDropZoneSlotP(slotDiv, linhaPaiObj, ladoSlot, dentroDeColunaE = false) {     const originalBgColor = 'transparent';     const hoverBgColor = 'rgba(227, 242, 253, 0.7)';     slotDiv.addEventListener('dragover', (e) => {         e.preventDefault();         e.stopPropagation();         const dados = context.dadosArrastados;         if (!dados || dados.tipo !== 'P' || (dados.origem === 'slot_P' && dados.id === e.target.closest('[data-bloco-id]')?.dataset.blocoId)) {             e.dataTransfer.dropEffect = 'none';             return;         }         const slotAlvoArray = linhaPaiObj.slots[ladoSlot] || [];         const isMovingFromSameSlotP = dados.id && dados.origem === 'slot_P' && dados.idLinhaOrigem === linhaPaiObj.idLinha && dados.ladoSlotOrigem === ladoSlot;                  // [CORREÇÃO] Limite de 3 blocos quando dentro de uma coluna E.         const maxBlocos = dentroDeColunaE ? 3 : Math.floor(context.config.maxBlocosPorLinha / 2);         if (slotAlvoArray.length >= maxBlocos && !isMovingFromSameSlotP) {             e.dataTransfer.dropEffect = 'none';             limparFantasmasAtivos();             return;         }         e.dataTransfer.dropEffect = 'move';         slotDiv.style.backgroundColor = hoverBgColor;         updateInsertionMarkerInSlotP(e, slotDiv);     });     slotDiv.addEventListener('dragleave', (e) => {         e.stopPropagation();         if (!slotDiv.contains(e.relatedTarget)) {             limparFantasmasAtivos();             slotDiv.style.backgroundColor = originalBgColor;             delete slotDiv.dataset.dropTargetId;             delete slotDiv.dataset.insertBefore;         }     });     slotDiv.addEventListener('drop', (e) => {         context.dropOccurredInEditor = true;         e.preventDefault();         e.stopPropagation();         const targetId = slotDiv.dataset.dropTargetId;         const insertBefore = slotDiv.dataset.insertBefore === "true";         limparFantasmasAtivos();         slotDiv.style.backgroundColor = originalBgColor;         delete slotDiv.dataset.dropTargetId;         delete slotDiv.dataset.insertBefore;         const dadosTransferidos = context.dadosArrastados;         if (!dadosTransferidos || dadosTransferidos.tipo !== 'P') {             return;         }         processarDropEmSlotP(dadosTransferidos, linhaPaiObj.idLinha, ladoSlot, targetId, insertBefore);         context.dadosArrastados = null;         context.elementoArrastadoOriginalDOM = null;     }); }     function processarDropEmSlotP(dados, idLinhaPai, ladoSlotAlvo, targetId, insertBefore) {         const linhaPAlvo = context.linhasDoEditor.find(l => l.idLinha === idLinhaPai);         if (!linhaPAlvo || linhaPAlvo.tipoLinhaOrigem !== 'P' || !linhaPAlvo.slots) {             renderizarEditor();             return;         }         const slotAlvoArray = linhaPAlvo.slots[ladoSlotAlvo];         if (!slotAlvoArray) {             renderizarEditor();             return;         }         let blocoRemovido = null;         if (dados.id && dados.origem !== 'paleta') {             if (dados.origem === 'slot_P') {                 const linhaOrigem = context.linhasDoEditor.find(l => l.idLinha === dados.idLinhaOrigem);                 if (linhaOrigem && linhaOrigem.slots && linhaOrigem.slots[dados.ladoSlotOrigem]) {                     const idx = linhaOrigem.slots[dados.ladoSlotOrigem].findIndex(b => b.id === dados.id);                     if (idx !== -1) {                         [blocoRemovido] = linhaOrigem.slots[dados.ladoSlotOrigem].splice(idx, 1);                         const isMoveWithinSameLine = linhaOrigem.idLinha === linhaPAlvo.idLinha;                         if (!isMoveWithinSameLine && linhaOrigem.slots.esquerda.length === 0 && linhaOrigem.slots.direita.length === 0) {                             context.linhasDoEditor = context.linhasDoEditor.filter(l => l.idLinha !== linhaOrigem.idLinha);                         }                     }                 }             } else if (dados.origem === 'slot_T') {                 let tOriginario = context.linhasDoEditor.flatMap(l => l.blocos.filter(b => b.tipo.startsWith('T'))).find(b => b.id === dados.idDoTPai);                 if (tOriginario && tOriginario.linhasInternas && tOriginario.linhasInternas[dados.indiceLinhaT] && tOriginario.linhasInternas[dados.indiceLinhaT][dados.posicaoSlotT]) {                     const idx = tOriginario.linhasInternas[dados.indiceLinhaT][dados.posicaoSlotT].findIndex(b => b.id === dados.id);                     if (idx !== -1) tOriginario.linhasInternas[dados.indiceLinhaT][dados.posicaoSlotT].splice(idx, 1);                 }             } else if (dados.origem === 'editor_principal') {                 removerBlocoDaEstruturaPrincipal(dados.id);             }         }         let blocoParaAdicionar;         if (dados.origem === 'paleta') {             blocoParaAdicionar = {                 ...dados,                 id: gerarIdUnico(`${context.editorId}_blocoP_slot_`),                 tipo: 'P',                 valoresCampos: {}             };         } else {             blocoParaAdicionar = blocoRemovido || { ...dados             };         }         atualizarParametrosDeLado(blocoParaAdicionar, {             ladoSlot: ladoSlotAlvo         });         if (targetId) {             const targetIndex = slotAlvoArray.findIndex(b => b.id === targetId);             if (targetIndex !== -1) {                 const insertIndex = insertBefore ? targetIndex : targetIndex + 1;                 slotAlvoArray.splice(insertIndex, 0, blocoParaAdicionar);             } else {                 slotAlvoArray.push(blocoParaAdicionar);             }         } else {             slotAlvoArray.push(blocoParaAdicionar);         }         setTimeout(() => renderizarEditor(), 0);     }     function removerBlocoDaEstruturaPrincipal(idBloco) {         let removido = false;         for (let i = context.linhasDoEditor.length - 1; i >= 0; i--) {             const linha = context.linhasDoEditor[i];             if (linha.tipoLinhaOrigem === 'P') continue;             if (linha.blocos && Array.isArray(linha.blocos)) {                 const blocoIdx = linha.blocos.findIndex(b => b.id === idBloco);                 if (blocoIdx !== -1) {                     linha.blocos.splice(blocoIdx, 1);                     if (linha.blocos.length === 0) {                         context.linhasDoEditor.splice(i, 1);                     }                     removido = true;                     break;                 }             }         }         return removido;     }     function processarDadosTransferidos(dadosBlocoDrag, targetIndexLinha, ladoAlvo = 'esquerda') {         if (!dadosBlocoDrag || typeof dadosBlocoDrag.tipo === 'undefined') {             console.error("processarDadosTransferidos: dados inválidos.");             return;         }         if (dadosBlocoDrag.origem === 'slot_P') {             const linhaOrigem = context.linhasDoEditor.find(l => l.idLinha === dadosBlocoDrag.idLinhaOrigem);             if (linhaOrigem && linhaOrigem.slots && linhaOrigem.slots[dadosBlocoDrag.ladoSlotOrigem]) {                 const idx = linhaOrigem.slots[dadosBlocoDrag.ladoSlotOrigem].findIndex(b => b.id === dadosBlocoDrag.id);                 if (idx > -1) {                     linhaOrigem.slots[dadosBlocoDrag.ladoSlotOrigem].splice(idx, 1);                     if (linhaOrigem.slots.esquerda.length === 0 && linhaOrigem.slots.direita.length === 0) {                         const linhaIdx = context.linhasDoEditor.findIndex(l => l.idLinha === linhaOrigem.idLinha);                         if (linhaIdx > -1) {                             context.linhasDoEditor.splice(linhaIdx, 1);                             if (linhaIdx < targetIndexLinha) {                                 targetIndexLinha--;                             }                         }                     }                 }             }         }         if (dadosBlocoDrag.tipo === 'X') {             let blocoParaAdicionar;             if (dadosBlocoDrag.origem !== 'paleta') {                 blocoParaAdicionar = { ...dadosBlocoDrag                 };                 const index = context.xBlocks.findIndex(b => b.id === blocoParaAdicionar.id);                 if (index > -1) {                     context.xBlocks.splice(index, 1);                 }             } else {                 blocoParaAdicionar = {                     ...dadosBlocoDrag,                     id: gerarIdUnico(`${context.editorId}_blocoX_`),                     valoresCampos: {}                 };             }             context.xBlocks.push(blocoParaAdicionar);             renderizarEditor();             return;         }         if (dadosBlocoDrag.groupId && dadosBlocoDrag.origem !== 'paleta') {             const groupId = dadosBlocoDrag.groupId;             const grupoLinhas = [];             const outrosLinhas = [];             let originalIndexStart = -1;             context.linhasDoEditor.forEach((linha, index) => {                 const bloco = linha.blocos && linha.blocos[0];                 if (bloco && bloco.groupId === groupId) {                     if (originalIndexStart === -1) originalIndexStart = index;                     grupoLinhas.push(linha);                 } else {                     outrosLinhas.push(linha);                 }             });             if (grupoLinhas.length > 0) {                 if (originalIndexStart < targetIndexLinha) {                     targetIndexLinha -= grupoLinhas.length;                 }                 outrosLinhas.splice(targetIndexLinha, 0, ...grupoLinhas);                 context.linhasDoEditor = outrosLinhas;                 renderizarEditor();                 return;             }         }         if (dadosBlocoDrag.origem !== 'paleta' && dadosBlocoDrag.origem !== 'slot_P' && dadosBlocoDrag.id) {             let linhaMovida = null;             let indiceOriginal = -1;             const isSpacer = ['S', 'O', 'U', 'R'].includes(dadosBlocoDrag.tipo);             if (isSpacer) {                 indiceOriginal = context.linhasDoEditor.findIndex(l => l.idLinha === dadosBlocoDrag.id);             } else {                 indiceOriginal = context.linhasDoEditor.findIndex(l => l.blocos && l.blocos[0] && l.blocos[0].id === dadosBlocoDrag.id);             }             if (indiceOriginal > -1) {                 [linhaMovida] = context.linhasDoEditor.splice(indiceOriginal, 1);                 if (indiceOriginal < targetIndexLinha) {                     targetIndexLinha--;                 }                 context.linhasDoEditor.splice(targetIndexLinha, 0, linhaMovida);                 renderizarEditor();                 return;             }         }         const blocoInfo = dadosBlocoDrag;         if (blocoInfo.tipo.startsWith('E')) {             let numBlocos = 3;             if (blocoInfo.subtipo) {                 const match = String(blocoInfo.subtipo).match(/\d+/);                 if (match && match[0]) {                     const n = parseInt(match[0], 10);                     if (!isNaN(n)) numBlocos = n + 1;                 }             }             const groupId = gerarIdUnico('grupoE_');             const novasLinhas = [];             for (let i = 0; i < numBlocos; i++) {                 const isHeader = i === 0;                 const blocoIndividual = {                     ...blocoInfo,                     id: gerarIdUnico('blocoE_'),                     groupId: groupId,                     groupIndex: i,                     groupSize: numBlocos,                     valoresCampos: isHeader ? (blocoInfo.valoresCampos || {}) : {},                     isCollapsed: isHeader ? false : undefined                 };                 novasLinhas.push({                     idLinha: gerarIdUnico('linha_E_'),                     tipoLinhaOrigem: 'E',                     blocos: [blocoIndividual]                 });             }             context.linhasDoEditor.splice(targetIndexLinha, 0, ...novasLinhas);         } else if (blocoInfo.tipo.startsWith('C')) {             const groupId = gerarIdUnico('grupoC_');             const groupingIdMatch = String(blocoInfo.subtipo).match(/\d+/);             const groupingId = groupingIdMatch ? groupingIdMatch[0] : '0';             const novasLinhas = [];             for (let i = 0; i < 2; i++) {                 const isHeader = i === 0;                 const blocoIndividual = {                     ...blocoInfo,                     id: gerarIdUnico('blocoC_'),                     groupId: groupId,                     groupingId: groupingId,                     groupIndex: i,                     groupSize: 2,                     valoresCampos: isHeader ? (blocoInfo.valoresCampos || {}) : {},                     isCollapsed: isHeader ? false : undefined                 };                 novasLinhas.push({                     idLinha: gerarIdUnico('linha_C_'),                     tipoLinhaOrigem: 'C',                     blocos: [blocoIndividual]                 });             }             context.linhasDoEditor.splice(targetIndexLinha, 0, ...novasLinhas);         } else if (blocoInfo.tipo === 'P') {             const novoBlocoP = {                 ...blocoInfo,                 id: dadosBlocoDrag.origem === 'paleta' ? gerarIdUnico(`${context.editorId}_blocoP_`) : dadosBlocoDrag.id,             };             atualizarParametrosDeLado(novoBlocoP, {                 ladoSlot: ladoAlvo             });             const novaLinhaObj = {                 idLinha: gerarIdUnico('linhaP_'),                 tipoLinhaOrigem: 'P',                 slots: {                     esquerda: ladoAlvo === 'esquerda' ? [novoBlocoP] : [],                     direita: ladoAlvo === 'direita' ? [novoBlocoP] : []                 },                 blocos: []             };             context.linhasDoEditor.splice(targetIndexLinha, 0, novaLinhaObj);         } else {             const novoBloco = {                 ...blocoInfo,                 id: gerarIdUnico(`${context.editorId}_bloco_`),             };             if (novoBloco.tipo.startsWith('T') && blocoInfo.origem === 'paleta') {                 novoBloco.linhasInternas = [{                     inicio: [],                     fim: []                 }, {                     inicio: [],                     fim: []                 }, {                     inicio: [],                     fim: []                 }];             }             const novaLinhaObj = {                 idLinha: gerarIdUnico('linha_'),                 tipoLinhaOrigem: novoBloco.tipo,                 blocos: [novoBloco]             };             context.linhasDoEditor.splice(targetIndexLinha, 0, novaLinhaObj);         }         renderizarEditor();     } function excluirBloco(idBlocoExcluir) {         let foiRemovido = false;         let groupIdParaExcluir = null;         let tBlockParaAtualizar = null;         // 1. Tenta remover de xBlocks         const xIndex = context.xBlocks.findIndex(b => b.id === idBlocoExcluir);         if (xIndex !== -1) {             context.xBlocks.splice(xIndex, 1);             foiRemovido = true;         }         // Se já removeu, renderiza e termina         if (foiRemovido) {             renderizarEditor();             return;         }         // 2. Itera sobre as linhas para encontrar o bloco e seu contexto         for (let i = context.linhasDoEditor.length - 1; i >= 0; i--) {             if (foiRemovido) break; // Se já encontrou e removeu, para o loop             const linha = context.linhasDoEditor[i];             // A. Bloco de espaçamento (S,O,U,R) - o ID é o da própria linha             if (['S', 'O', 'U', 'R'].includes(linha.tipoLinhaOrigem) && linha.idLinha === idBlocoExcluir) {                 context.linhasDoEditor.splice(i, 1);                 foiRemovido = true;                 break;             }             // B. Bloco em uma linha principal (L, T, ou cabeçalho de grupo E, C)             const blocoPrincipal = linha.blocos?.[0];             if (blocoPrincipal && blocoPrincipal.id === idBlocoExcluir) {                 if (blocoPrincipal.groupId) {                     // É um grupo, marca o groupId para remover todas as linhas relacionadas depois                     groupIdParaExcluir = blocoPrincipal.groupId;                 } else {                     // É um bloco simples (L ou T), remove a linha inteira                     context.linhasDoEditor.splice(i, 1);                 }                 foiRemovido = true;                 break;             }             // C. Bloco dentro de um container T             if (blocoPrincipal?.tipo.startsWith('T') && blocoPrincipal.linhasInternas) {                 for (const linhaInterna of blocoPrincipal.linhasInternas) {                     for (const lado of ['inicio', 'fim']) {                         const slot = linhaInterna[lado];                         const indexInterno = slot?.findIndex(b => b.id === idBlocoExcluir);                         if (indexInterno > -1) {                             slot.splice(indexInterno, 1);                             tBlockParaAtualizar = blocoPrincipal.id;                             foiRemovido = true;                             break;                         }                     }                     if (foiRemovido) break;                 }             }                          // D. Bloco dentro de uma linha P             if (linha.tipoLinhaOrigem === 'P' && linha.slots) {                 for (const lado of ['esquerda', 'direita']) {                     const slot = linha.slots[lado];                     const indexP = slot?.findIndex(b => b.id === idBlocoExcluir);                     if (indexP > -1) {                         slot.splice(indexP, 1);                         foiRemovido = true;                         // Se a linha P ficar vazia após a remoção, marca-a para exclusão                         if (linha.slots.esquerda.length === 0 && linha.slots.direita.length === 0) {                             context.linhasDoEditor.splice(i, 1);                         }                         break;                     }                 }             }         }         // Passo final: se um grupo foi marcado para exclusão, remove todas as suas linhas agora         if (groupIdParaExcluir) {             context.linhasDoEditor = context.linhasDoEditor.filter(l => l.blocos?.[0]?.groupId !== groupIdParaExcluir);             foiRemovido = true;         }         // Renderiza apenas se algo foi efetivamente removido         if (foiRemovido) {             if (tBlockParaAtualizar) {                 recarregarImagemDoBloco(tBlockParaAtualizar);             }             renderizarEditor();         }     }     function excluirBlocoDeSlotT(idTPai, indiceLinhaT, posicaoSlotT, idBloco) {         let blocoT = context.linhasDoEditor.flatMap(l => l.blocos.filter(b => b.tipo.startsWith('T'))).find(b => b.id === idTPai);         if (blocoT && blocoT.linhasInternas && blocoT.linhasInternas[indiceLinhaT] && blocoT.linhasInternas[indiceLinhaT][posicaoSlotT]) {             const slotArray = blocoT.linhasInternas[indiceLinhaT][posicaoSlotT];             const blocoIdx = slotArray.findIndex(b => b.id === idBloco);             if (blocoIdx !== -1) {                 slotArray.splice(blocoIdx, 1);                  // ALTERADO: Adiciona a chamada para recarregar a imagem do bloco pai                 recarregarImagemDoBloco(idTPai);                  renderizarEditor();             }         }     }     function carregarEditorDoTexto() {         const controlador = document.getElementById(context.controleId);         if (!controlador) return;         const textoEntrada = controlador.value;         if (textoEntrada.trim() === '') {             if (context.linhasDoEditor.length > 0 || context.xBlocks.length > 0) {                 context.linhasDoEditor = [];                 context.xBlocks = [];                 renderizarEditor('text');             }             return;         }         const novasLinhasDoEditor = [];         const novosXBlocks = [];         const parseTag = (tagCompleta, tipoEsperado = null, isEncoded = false) => {             let tagInterna;             let paramSeparator;             if (isEncoded) {                 tagInterna = tagCompleta.slice(2, -2);                 paramSeparator = '£1';             } else {                 tagInterna = tagCompleta.slice(1, -1);                 paramSeparator = ',';             }             const [identificadorTag, paramsString] = tagInterna.split(/:(.*)/s);             const paramsArray = paramsString ? paramsString.split(paramSeparator) : [];             const {                 tagName             } = parseBlockName(identificadorTag);             const identificadorNormalizado = normalizarString(tagName);             let codigoPosicao = null;             let estadoAccordion = null;             if (paramsArray.length > 0) {                 let ultimoParam = paramsArray[paramsArray.length - 1];                 if (typeof ultimoParam === 'string' && ultimoParam.length > 0) {                     const ultimoChar = ultimoParam.slice(-1);                     if (ultimoChar === 'C' || ultimoChar === 'O') {                         estadoAccordion = ultimoChar;                         ultimoParam = ultimoParam.slice(0, -1);                     }                     if (/^[A-Z][EDC]\d$/.test(ultimoParam)) {                         codigoPosicao = ultimoParam;                         paramsArray.pop();                     }                 }             }             let tipoDoCodigo = codigoPosicao ? codigoPosicao.charAt(0) : tipoEsperado;             let possibleDefs = context.blocosDisponiveis.filter(b => {                 const parsedDefName = parseBlockName(b.nome);                 const tagNameToCompare = parsedDefName.tagName;                 return normalizarString(tagNameToCompare) === identificadorNormalizado;             });             if (possibleDefs.length === 0) return null;             let blocoDefFinal = null;             if (tipoDoCodigo) {                 blocoDefFinal = possibleDefs.find(b => b.tipo.startsWith(tipoDoCodigo));             }             if (!blocoDefFinal) {                 blocoDefFinal = possibleDefs[0];             }             if (!blocoDefFinal) return null;             const novoBloco = JSON.parse(JSON.stringify(blocoDefFinal));             novoBloco.id = gerarIdUnico(context.editorId + '_bload_');             novoBloco.valoresCampos = novoBloco.valoresCampos || {};             novoBloco.codigoPosicao = codigoPosicao;             if (estadoAccordion) {                 novoBloco.isCollapsed = (estadoAccordion === 'C');             }             if (novoBloco.tipo.startsWith('T')) {                 const campoPlusDef = novoBloco.camposDefinidos.find(c => c.nome.includes('+'));                 const campoPlusIndex = novoBloco.camposDefinidos.findIndex(c => c.nome.includes('+'));                 if (campoPlusDef && campoPlusIndex > -1 && paramsArray[campoPlusIndex]) {                     const conteudoCodificado = paramsArray[campoPlusIndex];                     const innerEncodedTagRegex = /£6(.*?)£7/g;                     const innerEncodedTags = conteudoCodificado.match(innerEncodedTagRegex) || [];                     const textoPuroCodificado = conteudoCodificado.replace(innerEncodedTagRegex, '').trim();                     novoBloco.valoresCampos[campoPlusDef.nome] = reverterCaracteresEspeciais(textoPuroCodificado);                     novoBloco.linhasInternas = [{                         inicio: [],                         fim: []                     }, {                         inicio: [],                         fim: []                     }, {                         inicio: [],                         fim: []                     }];                     const innerBlocks = innerEncodedTags.map(t => parseTag(t, null, true)).filter(Boolean);                     innerBlocks.forEach(blocoInterno => {                         if (blocoInterno && blocoInterno.codigoPosicao) {                             const tipoBloco = blocoInterno.codigoPosicao.charAt(0);                             const posHorizontal = blocoInterno.codigoPosicao.charAt(1);                             const posVertical = parseInt(blocoInterno.codigoPosicao.charAt(2), 10);                             if ((tipoBloco === 'P' || tipoBloco === 'E') && posVertical > 0) {                                 const indiceLinhaT = posVertical - 1;                                 const ladoSlot = posHorizontal === 'E' ? 'inicio' : 'fim';                                 if (indiceLinhaT >= 0 && indiceLinhaT < 3) {                                     if (!novoBloco.linhasInternas[indiceLinhaT]) {                                         novoBloco.linhasInternas[indiceLinhaT] = {                                             inicio: [],                                             fim: []                                         };                                     }                                     if (!novoBloco.linhasInternas[indiceLinhaT][ladoSlot]) {                                         novoBloco.linhasInternas[indiceLinhaT][ladoSlot] = [];                                     }                                     novoBloco.linhasInternas[indiceLinhaT][ladoSlot].push(blocoInterno);                                 }                             }                         }                     });                 }                 novoBloco.camposDefinidos.forEach((campo, index) => {                     if (index === campoPlusIndex) return;                     if (paramsArray[index] !== undefined) {                         novoBloco.valoresCampos[campo.nome] = reverterCaracteresEspeciais(paramsArray[index].replace(/\|/g, ','));                     }                 });             } else {                 if (novoBloco.camposDefinidos) {                     novoBloco.camposDefinidos.forEach((campo, index) => {                         if (paramsArray[index] !== undefined) {                             novoBloco.valoresCampos[campo.nome] = reverterCaracteresEspeciais(paramsArray[index].replace(/\|/g, ','));                         }                     });                 }             }             if (novoBloco.tipo.startsWith('C')) {                 const groupingIdMatch = String(novoBloco.subtipo).match(/\d+/);                 novoBloco.groupingId = groupingIdMatch ? groupingIdMatch[0] : null;             }             return novoBloco;         };         const linhasTexto = textoEntrada.split('\n').filter(l => l.trim() !== '');         function processarLinhas(startIndex, endConditionFn) {             let i = startIndex;             while (i < linhasTexto.length) {                 const linha = linhasTexto[i].trim();                 if (endConditionFn && endConditionFn(linha)) {                     return i;                 }                 const eGroupStartMatch = linha.match(/(\{.*?\})(\[(?:esquerda|meio|direita) inicio\].*)/);                 const cGroupStartMatch = linha.match(/^\[\s*([^[]+?)\s+inicio\s*\]$/);                 if (eGroupStartMatch) {                     const headerBlock = parseTag(eGroupStartMatch[1]);                     if (!headerBlock) {                         i++;                         continue;                     }                     const blocoDef = context.blocosDisponiveis.find(b => b.nome === headerBlock.nome && b.tipo === headerBlock.tipo);                     let groupSize = 3;                     if (blocoDef && blocoDef.subtipo) {                         const match = String(blocoDef.subtipo).match(/\d+/);                         if (match && match[0]) groupSize = parseInt(match[0], 10) + 1;                     }                     const groupId = gerarIdUnico('grupoE_parsed_');                     const groupBlocks = [headerBlock];                     for (let j = 1; j < groupSize; j++) {                         const memberBlock = JSON.parse(JSON.stringify(blocoDef));                         memberBlock.id = gerarIdUnico('blocoE_');                         memberBlock.valoresCampos = {};                         groupBlocks.push(memberBlock);                     }                     groupBlocks.forEach((b, index) => {                         b.groupId = groupId;                         b.groupIndex = index;                         b.groupSize = groupSize;                     });                     novasLinhasDoEditor.push({                         idLinha: gerarIdUnico(),                         tipoLinhaOrigem: 'E',                         blocos: [groupBlocks[0]]                     });                     let currentMemberIndex = 1;                     i++;                     while (currentMemberIndex < groupSize && i < linhasTexto.length) {                         const nextLine = linhasTexto[i].trim();                         const nextLineMarkers = nextLine.match(/\[(esquerda|meio|direita) (inicio|fim)\]/g);                         if (nextLineMarkers) {                             novasLinhasDoEditor.push({                                 idLinha: gerarIdUnico(),                                 tipoLinhaOrigem: 'E',                                 blocos: [groupBlocks[currentMemberIndex]]                             });                             currentMemberIndex++;                             i++;                         } else {                             i = processarLinhas(i, (l) => /\[(esquerda|meio|direita) (inicio|fim)\]/g.test(l)) - 1;                             i++;                         }                     }                     i--;                 } else if (cGroupStartMatch) {                     const nomeCompleto = cGroupStartMatch[1].trim();                     const isAberto = nomeCompleto.endsWith('!');                     const nomeBase = isAberto ? nomeCompleto.slice(0, -1) : nomeCompleto;                     const isCollapsed = !isAberto;                     const blocoDef = context.blocosDisponiveis.find(b => b.tipo.startsWith('C') && normalizarString(parseBlockName(b.nome).tagName) === normalizarString(nomeBase));                     if (blocoDef) {                         const groupId = gerarIdUnico('grupoC_parsed_');                         const groupingIdMatch = String(blocoDef.subtipo).match(/\d+/);                         const groupingId = groupingIdMatch ? groupingIdMatch[0] : null;                         const headerBlock = { ...JSON.parse(JSON.stringify(blocoDef)),                             id: gerarIdUnico(),                             groupId,                             groupingId,                             groupIndex: 0,                             groupSize: 2,                             valoresCampos: {},                             isCollapsed                         };                         const footerBlock = { ...JSON.parse(JSON.stringify(blocoDef)),                             id: gerarIdUnico(),                             groupId,                             groupingId,                             groupIndex: 1,                             groupSize: 2,                             valoresCampos: {}                         };                         novasLinhasDoEditor.push({                             idLinha: gerarIdUnico(),                             tipoLinhaOrigem: 'C',                             blocos: [headerBlock]                         });                         i = processarLinhas(i + 1, (l) => {                             const cGroupEndMatch = l.match(/^\[\s*([^[\]!]+)\s+fim\s*\]$/);                             return cGroupEndMatch && normalizarString(cGroupEndMatch[1]) === normalizarString(nomeBase);                         });                         novasLinhasDoEditor.push({                             idLinha: gerarIdUnico(),                             tipoLinhaOrigem: 'C',                             blocos: [footerBlock]                         });                     }                 } else {                     processarLinhaNormal(linha, novasLinhasDoEditor, novosXBlocks, parseTag);                 }                 i++;             }             return i;         }         processarLinhas(0, null);         context.xBlocks = novosXBlocks;         context.linhasDoEditor = novasLinhasDoEditor;         renderizarEditor('text');     }     function processarLinhaNormal(linha, linhasEditor, xBlocks, parseTagFn) {         if (linha.match(/^\[.*(inicio|fim)\]$/) || linha.match(/(\{.*?\})(\[.*(inicio|fim)\])/)) {             return;         }         const isSpacerSRegex = /^\s*]*>\s*( |\u00A0| )?\s*<\/p>\s*$/i;         const isSpacerORegex = /^\s*\s*$/i;         const isSpacerRRegex = /^\s*\s*( |\s*| )?\s*<\/div>\s*$/i;         const isSpacerURegex = /^\s*\s*( |\s*| )?\s*<\/div>\s*$/i;         if (isSpacerRRegex.test(linha)) {             linhasEditor.push({                 idLinha: gerarIdUnico('linha_r_'),                 tipoLinhaOrigem: 'R',                 blocos: []             });             return;         } else if (isSpacerSRegex.test(linha)) {             linhasEditor.push({                 idLinha: gerarIdUnico('linha_s_'),                 tipoLinhaOrigem: 'S',                 blocos: []             });             return;         } else if (isSpacerORegex.test(linha)) {             linhasEditor.push({                 idLinha: gerarIdUnico('linha_o_'),                 tipoLinhaOrigem: 'O',                 blocos: []             });             return;         } else if (isSpacerURegex.test(linha)) {             linhasEditor.push({                 idLinha: gerarIdUnico('linha_u_'),                 tipoLinhaOrigem: 'U',                 blocos: []             });             return;         }         const blocosDaLinha = (linha.match(/\{([^{}]+)\}/g) || []).map(t => parseTagFn(t)).filter(Boolean);         if (blocosDaLinha.length > 0) {             const xBlocksNestaLinha = blocosDaLinha.filter(b => b.tipo === 'X');             const outrosBlocosNestaLinha = blocosDaLinha.filter(b => b.tipo !== 'X');             if (xBlocksNestaLinha.length > 0) {                 xBlocks.push(...xBlocksNestaLinha);             }             if (outrosBlocosNestaLinha.length > 0) {                 const primeiroBloco = outrosBlocosNestaLinha[0];                 if (primeiroBloco.tipo === 'P') {                     const linhaP = {                         idLinha: gerarIdUnico('linha_p_'),                         tipoLinhaOrigem: 'P',                         slots: {                             esquerda: [],                             direita: []                         },                         blocos: []                     };                     outrosBlocosNestaLinha.forEach(blocoP => {                         const lado = (blocoP.codigoPosicao && blocoP.codigoPosicao.charAt(1) === 'D') ? 'direita' : 'esquerda';                         linhaP.slots[lado].push(blocoP);                     });                     linhaP.slots.direita.reverse();                     linhasEditor.push(linhaP);                 } else {                     linhasEditor.push({                         idLinha: gerarIdUnico('linha_'),                         tipoLinhaOrigem: primeiroBloco.tipo.charAt(0),                         blocos: [primeiroBloco]                     });                 }             }         }     }     function inicializarSincronizacaoReversa() {         const controlador = document.getElementById(context.controleId);         if (!controlador) return;         context.ultimoTextoProcessado = controlador.value;         carregarEditorDoTexto();         setInterval(() => {             const textoAtual = controlador.value;             if (textoAtual !== context.ultimoTextoProcessado) {                 context.ultimoTextoProcessado = textoAtual;                 carregarEditorDoTexto();             }         }, 500);     }     function fecharMenuHamburguer() {         if (context.paletaBlocosEl && context.paletaBlocosEl.classList.contains('paleta-visivel')) {             context.paletaBlocosEl.classList.remove('paleta-visivel');         }     }     function findBlockInContext(blockId) {         let foundBlock = null;         foundBlock = context.xBlocks.find(b => b.id === blockId);         if (foundBlock) return foundBlock;         for (const linha of context.linhasDoEditor) {             if (linha.blocos) {                 foundBlock = linha.blocos.find(b => b.id === blockId);                 if (foundBlock) return foundBlock;                 const tBlock = linha.blocos.find(b => b.tipo.startsWith('T') && b.linhasInternas);                 if (tBlock) {                     for (const linhaInterna of tBlock.linhasInternas) {                         if (linhaInterna.inicio) {                             foundBlock = linhaInterna.inicio.find(b => b.id === blockId);                             if (foundBlock) return foundBlock;                         }                         if (linhaInterna.fim) {                             foundBlock = linhaInterna.fim.find(b => b.id === blockId);                             if (foundBlock) return foundBlock;                         }                     }                 }             }             if (linha.slots) {                 if (linha.slots.esquerda) {                     foundBlock = linha.slots.esquerda.find(b => b.id === blockId);                     if (foundBlock) return foundBlock;                 }                 if (linha.slots.direita) {                     foundBlock = linha.slots.direita.find(b => b.id === blockId);                     if (foundBlock) return foundBlock;                 }             }         }         return null;     } function recarregarImagemDoBloco(idDoBloco) {     if (!idDoBloco) return;     setTimeout(() => {         const blocoObjeto = findBlockInContext(idDoBloco);         const elementoDOM = context.painelEditorEl.querySelector(`[data-bloco-id="${idDoBloco}"] .bloco-visor`);         // =============================== INÍCIO DO AJUSTE CIRÚRGICO ===============================         let idPaiT = null;         for (const linha of context.linhasDoEditor) {             if (linha.blocos) {                 const tBlock = linha.blocos.find(b => b.tipo.startsWith('T') && b.linhasInternas);                 if (tBlock) {                     for (const linhaInterna of tBlock.linhasInternas) {                         if (linhaInterna.inicio && linhaInterna.inicio.some(b => b.id === idDoBloco)) idPaiT = tBlock.id;                         if (linhaInterna.fim && linhaInterna.fim.some(b => b.id === idDoBloco)) idPaiT = tBlock.id;                     }                 }             }         }         // ================================ FIM DO AJUSTE CIRÚRGICO =================================         if (blocoObjeto && elementoDOM) {             blocoObjeto.imagemUrlCache = null;             blocoObjeto.imgWidthCache = null;             blocoObjeto.imgHeightCache = null;             blocoObjeto.imagemGeradaCache = null;             blocoObjeto.textoGeradoCache = null;             blocoObjeto.alinhamentoGeradoCache = null;             blocoObjeto.tamanhoFonteGeradoCache = null;             blocoObjeto.corTextoGeradoCache = null;             blocoObjeto.corFundoGeradoCache = null;             blocoObjeto.larguraGeradoCache = null;             blocoObjeto.cacheParams4x = null;             const dentroDeColunaE = !!elementoDOM.closest(`.${context.editorId}_coluna-bloco-e`);             const contextoRenderizacao = { dentroDeColunaE: dentroDeColunaE };             carregarImagemParaBloco(elementoDOM, blocoObjeto, contextoRenderizacao);                          // =============================== INÍCIO DO AJUSTE CIRÚRGICO ===============================             if (idPaiT) {                 recarregarImagemDoBloco(idPaiT);             } else {                 atualizarControle();             }             // ================================ FIM DO AJUSTE CIRÚRGICO =================================         }     }, 0); } function init(config, callbacks) {         context.config = config;         context.editorId = config.editorId;         context.controleId = config.controleId;         context.callbacks = callbacks;         let listaDeImagensArray = [];         if (Array.isArray(config.listaDeImagensDisponiveis)) {             listaDeImagensArray = config.listaDeImagensDisponiveis;         } else if (typeof config.listaDeImagensDisponiveis === 'string') {             try {                 listaDeImagensArray = JSON.parse(config.listaDeImagensDisponiveis);             } catch (e) {                 console.error("Falha ao decodificar a string 'listaDeImagensDisponiveis'. Verifique o formato.", e);                 listaDeImagensArray = [];             }         }         if (Array.isArray(listaDeImagensArray) && listaDeImagensArray.length > 0) {             context.listaImagens = new Map(listaDeImagensArray.map(f => [f, f]));         } else {             context.listaImagens = new Map();         }         const oldWarning = document.getElementById(context.editorId + '_mobile_warning');         if (oldWarning) {             oldWarning.remove();         }         const editorContainerEl = document.getElementById(context.editorId + '_main_wrapper');         if (editorContainerEl) {             editorContainerEl.style.display = 'block';         }         try {             context.blocosDisponiveis = JSON.parse(config.jsonDisponiveisBlocos);         } catch (e) {             console.error("Erro ao parsear JSON de blocos disponíveis:", e, 'String JSON:', config.jsonDisponiveisBlocos);             context.blocosDisponiveis = [];         }         context.insertionMarkerEl = document.createElement('div');         applyStyles(context.insertionMarkerEl, {             width: '4px',             backgroundColor: '#0d6efd',             borderRadius: '2px',             alignSelf: 'stretch',             pointerEvents: 'none'         });         context.containerPrincipalEl = document.getElementById(context.editorId + '_container');         context.paletaBlocosEl = document.getElementById(context.editorId + '_paleta-puzzle');         context.painelEditorWrapperEl = document.getElementById(context.editorId + '_painel_editor_wrapper');         context.painelEditorEl = document.createElement('div');         context.painelEditorEl.id = context.editorId + '_editor';         context.painelParamsEl = document.getElementById(context.editorId + '_painel_parametros');         context.paramsTituloEl = document.getElementById(context.editorId + '_params_titulo');         context.paramsCamposEl = document.getElementById(context.editorId + '_params_campos');         context.paramsOkBtn = document.getElementById(context.editorId + '_params_ok');         context.paramsCancelarBtn = document.getElementById(context.editorId + '_params_cancelar');         if (context.painelEditorWrapperEl) {             context.painelEditorWrapperEl.appendChild(context.painelEditorEl);         } else {             console.error('Editor de Blocos: ERRO CRÍTICO - painelEditorWrapperEl não encontrado.');             return;         }         const nomeBlocoInternoClassName = context.editorId + '_nome-bloco-interno';         const styleEl = document.createElement('style');         styleEl.innerHTML = `                                              .bloco-renderizado { box-sizing: border-box; }                                              .bloco-visor { box-sizing: border-box; width: 100%; height: 100%; border: 2px solid transparent; }                                              .bloco-t-em-coluna .bloco-visor { display: flex; flex-direction: column; }                                              @keyframes carregar-fundo {                                                  0% { background-position: -200% 0; }                                                  100% { background-position: 200% 0; }                                              }                                              .bloco-carregando-imagem .bloco-visor {                                                  background: linear-gradient(90deg, #f0f0f0, #e0e0e0, #f0f0f0) !important;                                                  background-size: 200% 100% !important;                                                  animation: carregar-fundo 1.5s infinite linear !important;                                              }                                              .bloco-grupo-cabecalho { cursor: default !important; }                                              .accordion-toggle {                                                  margin-right: 8px; font-size: 0.8em; color: #555;                                                  transition: transform 0.2s; user-select: none; cursor: pointer;                                              }                                              .dragging-original-hidden { opacity: 0.3 !important; }                                              .${nomeBlocoInternoClassName} { font-weight: bold; font-size: 0.85em; color: #333; flex-grow: 1;}                                              .bloco-invalido .bloco-visor {                                                   border: 2px solid #e53935 !important;                                              }                                              .bloco-t-em-coluna { min-height: 250px !important; }                                              #${context.editorId}_main_wrapper { position: relative; }                                              #${context.editorId}_container { overflow: hidden; position: relative; }                                              .editor-toolbar {                                                  display: flex; justify-content: space-between; align-items: center;                                                  padding: 5px 10px; border: 1px solid #ccc; background-color: #f0f0f0;                                                  border-bottom: none; flex-wrap: nowrap; gap: 15px;                                              }                                              .editor-switch-label-group {                                                  display: flex; align-items: center; gap: 8px;                                                  flex-shrink: 1; min-width: 0;                                              }                                              .editor-switch-label-group > span { flex-shrink: 0; }                                              .hamburger-menu {                                                  display: none; width: 34px; height: 34px; cursor: pointer;                                                  padding: 4px; box-sizing: border-box; z-index: 1002; flex-shrink: 0;                                              }                                              .hamburger-menu span {                                                  display: block; width: 100%; height: 3px; background-color: #333;                                                  margin: 5px 0; transition: all 0.3s;                                              }                                                                                           @media (max-width: 992px) {                                                  .hamburger-menu { display: block; }                                                  #${context.editorId}_container { flex-direction: column; height: auto; max-height: none; }                                                  #${context.editorId}_paleta-puzzle {                                                      position: absolute; top: 0; right: 0; bottom: 0;                                                      width: 280px; max-width: 80%; height: auto; max-height: none;                                                      transform: translateX(100%); transition: transform 0.3s ease-in-out;                                                      z-index: 1001; box-shadow: -2px 0 5px rgba(0,0,0,0.2);                                                      flex-direction: row; flex-wrap: wrap; overflow-y: auto;                                                      align-content: flex-start; gap: 8px;                                                  }                                                  #${context.editorId}_paleta-puzzle.paleta-visivel { transform: translateX(0); }                                                  #${context.editorId}_paleta-puzzle > div[draggable="true"] { width: calc(50% - 8px); margin: 0; }                                                  #${context.editorId}_painel_editor_wrapper { width: 100%; min-height: 500px; max-height: none; aspect-ratio: unset; }                                              }                                        `;         document.head.appendChild(styleEl);         const estilosBase = {             fontFamily: 'Arial, sans-serif',             boxSizing: 'border-box'         };         context.estilosGlobais = {             base: estilosBase,             container: { display: 'flex', flexDirection: 'row', gap: '15px', border: '1px solid #ccc', borderTop: 'none', padding: '10px', backgroundColor: 'transparent', height: 'auto', ...estilosBase, fontSize: '0.85em' },             paletaBlocos: { width: config.larguraPaleta, minWidth: config.larguraMinimaPaleta, border: '1px solid #ddd', padding: '10px', backgroundColor: '#fff', overflowY: 'auto', boxShadow: '0 0 5px rgba(0,0,0,0.1)', display: 'flex', flexDirection: 'row', flexWrap: 'wrap', gap: '4px', alignContent: 'flex-start', maxHeight: '500px' },             painelEditorWrapper: { flexGrow: '1', border: '1px solid #ddd', backgroundColor: '#fff', padding: '10px', overflowY: 'auto', overflowX: 'hidden', position: 'relative', minHeight: '400px', maxHeight: '80vh', aspectRatio: '32 / 9', width: '100%' },             xContainer: { display: 'flex', flexWrap: 'wrap', gap: '4px', marginBottom: '10px', padding: '5px', border: '1px dashed #ccc', minHeight: '42px', alignItems: 'stretch', alignContent: 'flex-start', transition: 'background-color 0.2s' },             editorLinhaFlex: { display: 'flex', flexWrap: 'nowrap', marginBottom: '4px', position: 'relative', gap: '4px', alignItems: 'stretch' },             editorLinhaGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr', marginBottom: '4px', position: 'relative', gap: '4px', alignItems: 'stretch' },             blocoPaletaBase: { padding: '6px 8px', borderRadius: '4px', cursor: 'grab', fontSize: '0.7em', textAlign: 'center', boxShadow: '0 1px 3px rgba(0,0,0,0.1)', ...estilosBase, width: 'calc(50% - 2px)', wordBreak: 'break-word' },             blocoRenderizadoBase: { margin: '0', position: 'relative', ...estilosBase, transition: 'transform 0.1s, opacity 0.2s', display: 'flex', flexGrow: '1' },             blocoVisorBase: { padding: '8px', borderRadius: '4px', wordBreak: 'break-word', display: 'flex', flexDirection: 'column', justifyContent: 'center', height: '100%', width: '100%', border: '2px solid transparent' },             blocoL: { backgroundColor: getEditorColor(config.cores.L_FUNDO) },             blocoP: { backgroundColor: getEditorColor(config.cores.P_FUNDO), minWidth: '20px' },             blocoT: { backgroundColor: getEditorColor(config.cores.T_FUNDO) },             blocoS: { backgroundColor: getEditorColor(config.cores.S_FUNDO) },             blocoO: { backgroundColor: getEditorColor(config.cores.O_FUNDO || config.cores.S_FUNDO) },             blocoU: { backgroundColor: getEditorColor(config.cores.U_FUNDO || config.cores.S_FUNDO) },             blocoR: { backgroundColor: getEditorColor(config.cores.U_FUNDO || config.cores.S_FUNDO) },             blocoE: { backgroundColor: getEditorColor(config.cores.E_FUNDO) },             blocoC: { width: '100%', marginLeft: '0px', backgroundColor: getEditorColor(config.cores.C_FUNDO || '#F5DAF5'), height: '15px', flexGrow: 0, justifyContent: 'center' },             blocoX: { backgroundColor: '#E0E0E0' },             blocoEGrupoWrapper: { width: '100%', marginBottom: '4px', borderRadius: '4px', overflow: 'hidden' },             blocoEColunasContainer: { display: 'flex', flexDirection: 'row', gap: '4px', padding: '4px', backgroundColor: getEditorColor(config.cores.E_FUNDO) },             blocoEColuna: { flex: '1 1 0', minWidth: '0', minHeight: '80px', backgroundColor: 'rgba(255,255,255,0.5)', borderRadius: '3px', border: '1px dashed #e1bee7', display: 'flex', flexDirection: 'column', gap: '4px', transition: 'background-color 0.2s' },             blocoPDentroTOverride: { backgroundColor: '#ffffff', height: '100%' },             blocoRenderizadoL: { width: '100%' },             blocoRenderizadoE: { width: '100%' },             blocoRenderizadoX: { flex: '1 1 80px', minWidth: '80px', maxWidth: '180px' },             blocoRenderizadoTContainer: { width: '100%', minHeight: '150px' },             linhaInternaT: { display: 'flex', flex: '1', minHeight: '50px', alignItems: 'stretch', gap: '5px' },             // ### AJUSTE 3: LARGURA DO SLOT T (Base) ###             // Define min-width e max-width para serem iguais ao flex-basis.             // Isso força o slot a ter uma largura fixa de 33%, impedindo que ele             // encolha ou estique, resolvendo a instabilidade de tamanho.             slotT: { display: 'flex', flexWrap: 'nowrap', alignItems: 'flex-start', flexGrow: 0, flexShrink: 0, flexBasis: '33%', minWidth: '33%', maxWidth: '33%', minHeight: '40px', padding: '2px', border: '1px dashed rgba(0,0,0,0.2)', backgroundColor: getEditorColor(config.cores.SLOT_T_FUNDO), borderRadius: '3px', overflow: 'hidden', position: 'relative', gap: '2px' }, slotLinhaP: { display: 'flex', flexWrap: 'nowrap', alignItems: 'center', padding: '0', border: '1px dashed #e0e0e0', backgroundColor: 'transparent', borderRadius: '3px', gap: '4px', boxSizing: 'border-box', width: '100%', minHeight: '80px', minWidth: '0' },             slotTInicio: { justifyContent: 'flex-start' },             slotTFim: { justifyContent: 'flex-end' },             accordionToggle: { padding: '0 8px 0 4px', minWidth: '1em', textAlign: 'center' },             dragPlaceholder: { height: 'auto', minHeight: '1px', padding: '1px 0', margin: '0', backgroundColor: 'transparent', border: 'none', width: '100%', opacity: '0', transition: 'opacity 0.1s ease-out, padding 0.1s ease-out, min-height 0.1s ease-out, background-color 0.2s', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '0.75em', color: '#333', textAlign: 'center', overflow: 'hidden', lineHeight: 'normal' },             dragPlaceholderVisibleBase: { opacity: '1', border: 'none', margin: '0', backgroundColor: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'flex-start' },             blocoFantasmaEstilo: { opacity: '0.6', transform: 'scale(1)', pointerEvents: 'none', boxSizing: 'border-box', margin: '0 !important' }         };         applyStyles(context.containerPrincipalEl, context.estilosGlobais.container);         applyStyles(context.paletaBlocosEl, context.estilosGlobais.paletaBlocos);         applyStyles(context.painelEditorWrapperEl, context.estilosGlobais.painelEditorWrapper);         const mainWrapperEl = document.getElementById(context.editorId + '_main_wrapper');         const viewSwitchEl = document.getElementById(context.editorId + '_view_switch');         const editorViewEl = document.getElementById(context.editorId + '_container');         const textareaControlEl = document.getElementById(context.controleId);         if (mainWrapperEl && viewSwitchEl && editorViewEl && textareaControlEl) {             const toolbarEl = document.createElement('div');             toolbarEl.className = 'editor-toolbar';             const switchLabelGroup = document.createElement('div');             switchLabelGroup.className = 'editor-switch-label-group';             const labelTexto = document.createElement('span');             labelTexto.textContent = 'Texto\u00A0\u00A0';             const labelVisual = document.createElement('span');             labelVisual.textContent = '\u00A0\u00A0Visual';             const switchContainer = viewSwitchEl.parentElement;             switchLabelGroup.appendChild(labelTexto);             if (switchContainer) {                 switchLabelGroup.appendChild(switchContainer);             }             switchLabelGroup.appendChild(labelVisual);             toolbarEl.appendChild(switchLabelGroup);             context.hamburgerBtn = document.createElement('div');             context.hamburgerBtn.className = 'hamburger-menu';             context.hamburgerBtn.innerHTML = '';             toolbarEl.appendChild(context.hamburgerBtn);             mainWrapperEl.insertBefore(toolbarEl, editorViewEl);             editorViewEl.appendChild(context.paletaBlocosEl);             const toggleMenu = () => {                 context.paletaBlocosEl.classList.toggle('paleta-visivel');             };             context.hamburgerBtn.addEventListener('click', toggleMenu);             if (textareaControlEl.parentNode !== mainWrapperEl) {                 mainWrapperEl.appendChild(textareaControlEl);             }             const toggleView = () => {                 if (viewSwitchEl.checked) {                     toolbarEl.style.display = 'flex';                     editorViewEl.style.display = 'flex';                     textareaControlEl.style.display = 'none';                     carregarEditorDoTexto();                 } else {                     toolbarEl.style.display = 'flex';                     editorViewEl.style.display = 'none';                     textareaControlEl.style.display = 'block';                     const editorHeight = editorViewEl.offsetHeight;                     textareaControlEl.style.height = editorHeight > 100 ? `${editorHeight}px` : '620px';                     textareaControlEl.style.width = '100%';                     textareaControlEl.style.boxSizing = 'border-box';                     textareaControlEl.style.border = '1px solid #ccc';                 }             };             viewSwitchEl.addEventListener('change', toggleView);             toggleView();         }         if (Array.isArray(context.blocosDisponiveis)) {             context.blocosDisponiveis.forEach(bloco => {                 const key = `${bloco.nome}-${bloco.tipo}`;                 const divBlocoPaleta = document.createElement('div');                 divBlocoPaleta.dataset.key = key;                 applyStyles(divBlocoPaleta, context.estilosGlobais.blocoPaletaBase);                 let corFundo = '#f0f0f0';                 let corBorda = '#ccc';                 const tipoBase = bloco.tipo.charAt(0);                 if (tipoBase === 'L') {                     corFundo = getPaletteColor(config.cores.L_FUNDO);                     corBorda = getPaletteColor(config.cores.L_BORDA);                 } else if (tipoBase === 'P') {                     corFundo = getPaletteColor(config.cores.P_FUNDO);                     corBorda = getPaletteColor(config.cores.P_BORDA);                 } else if (tipoBase === 'T') {                     corFundo = getPaletteColor(config.cores.T_FUNDO);                     corBorda = getPaletteColor(config.cores.T_BORDA);                 } else if (tipoBase === 'S') {                     corFundo = getPaletteColor(config.cores.S_FUNDO);                     corBorda = getPaletteColor(config.cores.S_BORDA);                 } else if (tipoBase === 'O') {                     corFundo = getPaletteColor(config.cores.O_FUNDO || config.cores.S_FUNDO);                     corBorda = getPaletteColor(config.cores.O_BORDA || config.cores.S_BORDA);                 } else if (tipoBase === 'U') {                     corFundo = getPaletteColor(config.cores.U_FUNDO || config.cores.S_FUNDO);                     corBorda = getPaletteColor(config.cores.U_BORDA || config.cores.S_BORDA);                 } else if (tipoBase === 'R') {                     corFundo = getPaletteColor(config.cores.U_FUNDO || config.cores.S_FUNDO);                     corBorda = getPaletteColor(config.cores.U_BORDA || config.cores.S_BORDA);                 } else if (tipoBase === 'E') {                     corFundo = getPaletteColor(config.cores.E_FUNDO);                     corBorda = getPaletteColor(config.cores.E_BORDA);                 } else if (tipoBase === 'C') {                     corFundo = getPaletteColor(config.cores.C_FUNDO || '#F5DAF5');                     corBorda = getPaletteColor(config.cores.C_BORDA || '#E1BEE7');                 } else if (tipoBase === 'X') {                     corFundo = context.estilosGlobais.blocoX.backgroundColor;                     corBorda = '#9E9E9E';                 }                 applyStyles(divBlocoPaleta, {                     backgroundColor: corFundo,                     border: `1px solid ${corBorda}`                 });                 divBlocoPaleta.innerHTML = parseBlockName(bloco.nome).displayName;                 divBlocoPaleta.draggable = true;                 divBlocoPaleta.addEventListener('dragstart', async (e) => {                     fecharMenuHamburguer();                     const dragData = {                         ...bloco,                         origem: 'paleta'                     };                     try {                         e.dataTransfer.setData('text/plain', JSON.stringify(dragData));                         context.dadosArrastados = dragData;                     } catch (err) {                         console.error("Erro em setData ou ao setar dadosArrastados:", err, dragData);                         e.preventDefault();                         return;                     }                     applyStyles(e.target, {                         opacity: '0.5'                     });                     const clone = await criarBlocoFantasma(dragData);                     if (!clone) return;                     applyStyles(clone, {                         position: 'absolute',                         top: '-9999px',                         left: '-9999px'                     });                     document.body.appendChild(clone);                     try {                         const rect = e.target.getBoundingClientRect();                         const offsetX = e.clientX - rect.left;                         const offsetY = e.clientY - rect.top;                         e.dataTransfer.setDragImage(clone, offsetX, offsetY);                     } catch (err) {                         console.warn("Paleta dragstart: setDragImage falhou:", err);                     }                     setTimeout(() => {                         if (document.body.contains(clone)) document.body.removeChild(clone);                     }, 0);                 });                 divBlocoPaleta.addEventListener('dragend', (e) => {                     if (e.target && typeof e.target.style !== 'undefined') {                         applyStyles(e.target, {                             opacity: '1'                         });                     }                     if (context.dadosArrastados && context.dadosArrastados.origem === 'paleta') {                         context.dadosArrastados = null;                     }                     limparFantasmasAtivos();                     document.querySelectorAll('[data-id-linha]').forEach(ld => {                         if (ld.dataset.tipoLinha !== 'P') {                             applyStyles(ld, context.estilosGlobais.editorLinhaFlex);                         } else {                             applyStyles(ld, context.estilosGlobais.editorLinhaGrid);                         }                         ld.querySelectorAll('.slot-t, .slot-linha-p').forEach(slot => {                             if (slot.classList.contains('slot-t')) {                                 applyStyles(slot, context.estilosGlobais.slotT);                                 if (slot.dataset.posicaoSlotT === 'inicio') applyStyles(slot, context.estilosGlobais.slotTInicio);                                 if (slot.dataset.posicaoSlotT === 'fim') applyStyles(slot, context.estilosGlobais.slotTFim);                             } else if (slot.classList.contains('slot-linha-p')) {                                 applyStyles(slot, context.estilosGlobais.slotLinhaP);                                 if (slot.classList.contains('slot-direita')) {                                     applyStyles(slot, {                                         justifyContent: 'flex-end'                                     });                                 } else {                                     applyStyles(slot, {                                         justifyContent: 'flex-start'                                     });                                 }                             }                         });                     });                     document.querySelectorAll(`#${context.editorId}_editor > div[data-target-linha-index]`).forEach(ph => {                         const estiloInativo = { ...context.estilosGlobais.dragPlaceholder                         };                         if (ph.dataset.isFinal === 'true') {                             if (context.linhasDoEditor.length === 0) estiloInativo.minHeight = '30px';                             else estiloInativo.minHeight = '1px';                         }                         applyStyles(ph, estiloInativo);                         ph.innerHTML = '';                     });                 });                 context.paletaBlocosEl.appendChild(divBlocoPaleta);             });         }         context.painelEditorWrapperEl.addEventListener('dragover', (e) => {             e.preventDefault();         });         context.painelEditorWrapperEl.addEventListener('drop', (e) => {             context.dropOccurredInEditor = true;             e.preventDefault();             e.stopPropagation();             if (e.target === context.painelEditorWrapperEl || e.target === context.painelEditorEl) {                 const dados = context.dadosArrastados;                 if (!dados) return;                 const targetIndex = dados.tipo === 'X' ? -1 : context.linhasDoEditor.length;                 processarDadosTransferidos(dados, targetIndex);             }         });         if (context.containerPrincipalEl && context.paletaBlocosEl && context.painelEditorWrapperEl && context.painelEditorEl) {             inicializarSincronizacaoReversa();         } else {             console.error("Falha na inicialização do editor.");         }     }     return {         init: init,         recarregarImagemDoBloco: recarregarImagemDoBloco,         getContext: () => ({             getEditorColor: getEditorColor,             getLinhasEditor: () => context.linhasDoEditor,             getXBlocks: () => context.xBlocks,             renderizarEditor: renderizarEditor,             painelParamsEl: context.painelParamsEl,             paramsTituloEl: context.paramsTituloEl,             paramsCamposEl: context.paramsCamposEl,             paramsOkBtn: context.paramsOkBtn,             paramsCancelarBtn: context.paramsCancelarBtn,             paletaBlocosEl: context.paletaBlocosEl,         })     }; })();