{"id":2354,"date":"2025-12-03T14:56:58","date_gmt":"2025-12-03T14:56:58","guid":{"rendered":"https:\/\/pkfcabrera.com\/?page_id=2354"},"modified":"2025-12-03T20:41:16","modified_gmt":"2025-12-03T20:41:16","slug":"generador-newsletter","status":"publish","type":"page","link":"https:\/\/pkfcabrera.com\/en\/generador-newsletter\/","title":{"rendered":"Generador Newsletter PKF Cabrera"},"content":{"rendered":"<section class=\"l-section wpb_row height_custom\"><div class=\"l-section-h i-cf\"><div class=\"g-cols vc_row via_grid cols_1 laptops-cols_inherit tablets-cols_inherit mobiles-cols_1 valign_top type_default stacking_default\"><div class=\"wpb_column vc_column_container\"><div class=\"vc_column-inner\"><div class=\"w-html\"><!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Generador Newsletter | PKF Cabrera<\/title>\n    \n    <!-- 1. Tailwind CSS -->\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <script src=\"https:\/\/cdn.tailwindcss.com?plugins=typography\"><\/script>\n    \n    <!-- 2. React & ReactDOM -->\n    <script crossorigin src=\"https:\/\/unpkg.com\/react@18\/umd\/react.production.min.js\"><\/script>\n    <script crossorigin src=\"https:\/\/unpkg.com\/react-dom@18\/umd\/react-dom.production.min.js\"><\/script>\n    \n    <!-- 3. Babel -->\n    <script src=\"https:\/\/unpkg.com\/@babel\/standalone\/babel.min.js\"><\/script>\n\n    <style>\n        body { background-color: #f1f5f9; margin: 0; padding: 0; }\n        \n        \/* Editor Rico - Estilos de Entrada *\/\n        .rich-editor {\n            min-height: 300px;\n            outline: none;\n            background: white;\n            color: #334155;\n        }\n        \/* Estilos visuales dentro del editor *\/\n        .rich-editor ul { list-style-type: disc; margin-left: 1.5rem; margin-bottom: 1rem; }\n        .rich-editor p { margin-bottom: 0.75rem; }\n        .rich-editor b, .rich-editor strong { font-weight: 700; }\n        .rich-editor i, .rich-editor em { font-style: italic; }\n\n        \/* --- ESTILOS CR\u00cdTICOS PARA EL CUERPO DEL NEWSLETTER (SALIDA) --- *\/\n        #newsletter-body {\n            font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n            color: #334155; \/* Slate 700 *\/\n            width: 100%;\n            \/* Por defecto (M\u00f3vil) *\/\n            font-size: 1.125rem;       \/* ~18px en m\u00f3vil *\/\n            line-height: 1.35;         \n            text-align: left;          \/* Izquierda en m\u00f3vil para evitar r\u00edos *\/\n        }\n        \n        #newsletter-body p, \n        #newsletter-body div {\n            margin-bottom: 0.8em;\n            width: 100%;\n            display: block;\n            text-align: left;          \/* Izquierda en m\u00f3vil *\/\n        }\n        \n        \/* --- RESPONSIVIDAD: PANTALLAS MEDIANAS Y GRANDES --- *\/\n        @media (min-width: 768px) {\n            #newsletter-body {\n                font-size: 1.25rem;    \/* ~20px en escritorio *\/\n                line-height: 1.3;\n                text-align: justify;   \/* Justificado en escritorio *\/\n            }\n            #newsletter-body p, \n            #newsletter-body div {\n                text-align: justify;   \/* Justificado en escritorio *\/\n            }\n        }\n        \n        #newsletter-body ul {\n            list-style-type: disc;\n            padding-left: 1.5em;\n            margin-bottom: 1em;\n            text-align: left;\n        }\n        \n        #newsletter-body strong { font-weight: 800; color: #0f172a; }\n        #newsletter-body em { font-style: italic; }\n        \n        #newsletter-body img {\n            max-width: 100%;\n            height: auto;\n            margin: 1.5rem auto;\n            border-radius: 0.5rem;\n        }\n\n        \/* Scrollbar *\/\n        .custom-scrollbar::-webkit-scrollbar { width: 6px; }\n        .custom-scrollbar::-webkit-scrollbar-track { background: #1e293b; }\n        .custom-scrollbar::-webkit-scrollbar-thumb { background: #475569; border-radius: 3px; }\n        .custom-scrollbar::-webkit-scrollbar-thumb:hover { background: #64748b; }\n\n        @media print {\n            body * { visibility: hidden; }\n            .print-hidden { display: none !important; }\n            #printable-area, #printable-area * { visibility: visible; }\n            #printable-area {\n                position: absolute;\n                left: 0; top: 0; width: 100%; margin: 0; padding: 0;\n            }\n            \/* Reset de estilos para impresi\u00f3n *\/\n            #newsletter-content {\n                box-shadow: none !important;\n                margin: 0 !important;\n                width: 100% !important;\n                max-width: 100% !important;\n            }\n            * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }\n        }\n    <\/style>\n<\/head>\n<body>\n    \n    <div id=\"root\"><\/div>\n\n    <script type=\"text\/babel\">\n        const { useState, useRef, useEffect } = React;\n\n        \/\/ --- DATOS ---\n        const PREDEFINED_COLUMNISTS = [\n            { name: \"Karen Estefany Giraldo Paz\", role: \"Directora Jur\u00eddico Laboral\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/karen-1.webp\" },\n            { name: \"Carolina Rojas Olivares\", role: \"Directora Administrativa, Financiera y Gesti\u00f3n Humana\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/carolina-1.webp\" },\n            { name: \"Luis Angel Giraldo Pach\u00f3n\", role: \"Supervisor de Auditor\u00eda\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/luis.webp\" },\n            { name: \"Daniela Silva Madro\u00f1ero\", role: \"Supervisora de Auditor\u00eda\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/daniela-silva-bolita.webp\" },\n            { name: \"Francisco Antonio Rodriguez Balcazar\", role: \"Director de Impuestos\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/francisco-rodriguez-circulo.webp\" },\n            { name: \"Oscar Dar\u00edo Montoya Torres\", role: \"Director de Compliance\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/oscar.webp\" },\n            { name: \"Andr\u00e9s Olaya Cantor\", role: \"Director Departamento Legal\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/cristhian.webp\" },\n            { name: \"Gloria Cristina Blanco Giraldo\", role: \"Directora de Auditor\u00eda\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/gloria-blanco-circulo.webp\" },\n            { name: \"Jos\u00e9 Alberto Galvis Araque\", role: \"Director de Auditor\u00eda\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/jose-galvis-circulo.webp\" },\n            { name: \"Carlos Andr\u00e9s Parrado\", role: \"Supervisor de Auditor\u00eda\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/andres.webp\" },\n            { name: \"Julieth Stephania Sarria Bedoya\", role: \"Auditor Senior TI\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/julieth.webp\" }\n        ];\n\n        \/\/ --- ICONOS ---\n        const Icon = ({ path, size = 18 }) => (\n            <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">{path}<\/svg>\n        );\n        const icons = {\n            bold: <path d=\"M6 12h8a4 4 0 0 0 0-8H6v8Zm0 0h9a4 4 0 0 1 0 8H6v-8Z\" \/>,\n            italic: <path d=\"M19 4h-9M14 20H5M15 4L9 20\" \/>,\n            list: <><line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"\/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"\/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"\/><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"\/><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"\/><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"\/><\/>,\n            alignLeft: <><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"\/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"\/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"\/><\/>,\n            alignCenter: <><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"\/><line x1=\"19\" y1=\"12\" x2=\"5\" y2=\"12\"\/><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"\/><\/>,\n            alignJustify: <><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"\/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"\/><line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\"\/><\/>,\n            download: <><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"\/><polyline points=\"7 10 12 15 17 10\"\/><line x1=\"12\" x2=\"12\" y1=\"15\" y2=\"3\"\/><\/>,\n            code: <><polyline points=\"16 18 22 12 16 6\"\/><polyline points=\"8 6 2 12 8 18\"\/><\/>,\n            trash: <><path d=\"M3 6h18\"\/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"\/><path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"\/><\/>,\n            userPlus: <><path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"\/><circle cx=\"9\" cy=\"7\" r=\"4\"\/><line x1=\"19\" x2=\"19\" y1=\"8\" y2=\"14\"\/><line x1=\"22\" x2=\"16\" y1=\"11\" y2=\"11\"\/><\/>,\n            settings: <><path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.1a2 2 0 0 1-1-1.74v-.47a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/>,\n            chevronDown: <path d=\"m6 9 6 6 6-6\"\/>,\n            chevronUp: <path d=\"m18 15-6-6-6 6\"\/>\n        };\n\n        \/\/ --- EDITOR DE TEXTO ---\n        const RichTextEditor = ({ value, onChange }) => {\n            const editorRef = useRef(null);\n            \n            useEffect(() => { \n                \/\/ SEO: Forzar uso de P\u00e1rrafos <p>\n                document.execCommand('defaultParagraphSeparator', false, 'p');\n                if (editorRef.current && editorRef.current.innerHTML !== value) {\n                    editorRef.current.innerHTML = value; \n                }\n            }, []);\n\n            const exec = (cmd) => { document.execCommand(cmd, false, null); if (editorRef.current) onChange(editorRef.current.innerHTML); };\n            const handleInput = () => { if (editorRef.current) onChange(editorRef.current.innerHTML); };\n\n            \/\/ Funci\u00f3n para limpiar el pegado (Paste)\n            const handlePaste = (e) => {\n                e.preventDefault();\n                const text = (e.originalEvent || e).clipboardData.getData('text\/plain');\n                document.execCommand('insertText', false, text);\n            };\n\n            return (\n                <div className=\"border border-slate-600 rounded-lg overflow-hidden bg-white focus-within:ring-2 focus-within:ring-blue-500 transition-shadow\">\n                    <div className=\"flex items-center gap-1 p-2 bg-slate-100 border-b border-slate-200 text-slate-700\">\n                        <button onClick={() => exec('bold')} className=\"p-1.5 hover:bg-slate-300 rounded\" title=\"Negrita\"><Icon path={icons.bold} size={16}\/><\/button>\n                        <button onClick={() => exec('italic')} className=\"p-1.5 hover:bg-slate-300 rounded\" title=\"Cursiva\"><Icon path={icons.italic} size={16}\/><\/button>\n                        <div className=\"w-px h-4 bg-slate-300 mx-1\"><\/div>\n                        <button onClick={() => exec('insertUnorderedList')} className=\"p-1.5 hover:bg-slate-300 rounded\" title=\"Vi\u00f1etas\"><Icon path={icons.list} size={16}\/><\/button>\n                        <div className=\"w-px h-4 bg-slate-300 mx-1\"><\/div>\n                        <button onClick={() => exec('justifyLeft')} className=\"p-1.5 hover:bg-slate-300 rounded\" title=\"Izquierda\"><Icon path={icons.alignLeft} size={16}\/><\/button>\n                        <button onClick={() => exec('justifyCenter')} className=\"p-1.5 hover:bg-slate-300 rounded\" title=\"Centro\"><Icon path={icons.alignCenter} size={16}\/><\/button>\n                        <button onClick={() => exec('justifyFull')} className=\"p-1.5 hover:bg-slate-300 rounded\" title=\"Justificar\"><Icon path={icons.alignJustify} size={16}\/><\/button>\n                    <\/div>\n                    <div \n                        ref={editorRef} \n                        contentEditable \n                        className=\"rich-editor p-4 text-sm font-sans leading-relaxed\" \n                        onInput={handleInput} \n                        onBlur={handleInput}\n                        onPaste={handlePaste} \n                    ><\/div>\n                <\/div>\n            );\n        };\n\n        \/\/ --- APP PRINCIPAL ---\n        const PKFNewsletterApp = () => {\n            const [isConfigOpen, setIsConfigOpen] = useState(true);\n            const [activeTab, setActiveTab] = useState('config');\n\n            const [config, setConfig] = useState({\n                department: 'Departamento de Auditor\u00eda',\n                date: new Date().toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' }),\n                title: 'Actualizaci\u00f3n Normativa y Perspectivas Fiscales',\n                subtitle: 'An\u00e1lisis mensual sobre el impacto de las nuevas regulaciones en el sector empresarial.',\n                bodyText: `<p>Estimados clientes y colaboradores,<\/p><p>En este bolet\u00edn abordamos los cambios recientes en la normativa fiscal que impactar\u00e1n el cierre del a\u00f1o fiscal en curso. Es fundamental revisar las provisiones y asegurar el cumplimiento de los nuevos requisitos de informaci\u00f3n financiera.<\/p><p>La transformaci\u00f3n digital sigue siendo un pilar clave en nuestra estrategia de asesoramiento, permiti\u00e9ndonos ofrecer soluciones m\u00e1s \u00e1giles y precisas.<\/p>`,\n                mainImage: null,\n                logoUrl: 'https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/LOGO_RGB_2-LINES_coloured-pequeno.png'\n            });\n\n            const [columnists, setColumnists] = useState([\n                { id: 1, name: \"Karen Estefany Giraldo Paz\", role: \"Directora Jur\u00eddico Laboral\", image: \"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/karen-1.webp\" }\n            ]);\n\n            const handleConfigChange = (e) => setConfig({ ...config, [e.target.name]: e.target.value });\n            const handleBodyChange = (html) => setConfig({ ...config, bodyText: html });\n\n            const addColumnist = () => setColumnists(prev => [...prev, { id: Date.now(), name: 'Nuevo', role: 'Cargo', image: null }]);\n            const removeColumnist = (id) => setColumnists(prev => prev.filter(c => c.id !== id));\n            \n            const updateColumnist = (id, field, val) => {\n                setColumnists(prev => prev.map(c => c.id === id ? { ...c, [field]: val } : c));\n            };\n\n            const handlePredefinedSelection = (id, selectedName) => {\n                const person = PREDEFINED_COLUMNISTS.find(p => p.name === selectedName);\n                if (person) {\n                    setColumnists(prev => prev.map(col => \n                        col.id === id ? { ...col, name: person.name, role: person.role, image: person.image } : col\n                    ));\n                }\n            };\n\n            const handleImageUpload = (e, callback) => {\n                const file = e.target.files[0];\n                if (file) {\n                    const reader = new FileReader();\n                    reader.onloadend = () => callback(reader.result);\n                    reader.readAsDataURL(file);\n                }\n            };\n\n            const handlePrint = () => window.print();\n            const handleDownloadHTML = () => {\n                const content = document.getElementById('newsletter-content');\n                if (!content) return;\n                const html = `<!DOCTYPE html><html lang=\"es\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>${config.title} - PKF Cabrera<\/title><meta name=\"description\" content=\"${config.subtitle || ''}\"><script src=\"https:\/\/cdn.tailwindcss.com?plugins=typography\"><\\\/script><style>body{background:#f1f5f9;margin:0}#newsletter-content{max-width:100%!important;margin:0!important;box-shadow:none!important}#newsletter-body{font-family:ui-sans-serif,system-ui,sans-serif;width:100%;font-size:1.125rem;line-height:1.35;text-align:left;}#newsletter-body p{margin-bottom:1em;width:100%;display:block;}#newsletter-body ul{list-style:disc;margin-left:1.5em;text-align:left;}@media(min-width:768px){#newsletter-body{font-size:1.25rem;line-height:1.3;text-align:justify;}}<\/style><\/head><body><article itemscope itemtype=\"http:\/\/schema.org\/NewsArticle\">${content.outerHTML}<\/article><\/body><\/html>`;\n                const blob = new Blob([html], { type: 'text\/html' });\n                const url = URL.createObjectURL(blob);\n                const a = document.createElement('a');\n                a.href = url;\n                a.download = `Newsletter_PKF_${config.date.replace(\/\\\/\/g,'-')}.html`;\n                a.click();\n            };\n\n            return (\n                <div className=\"min-h-screen flex flex-col font-sans bg-slate-900\">\n                    \n                    {\/* --- HEADER FIJO --- *\/}\n                    <div className=\"print-hidden bg-slate-900 text-white sticky top-0 z-50 shadow-md border-b border-slate-700\">\n                        <div className=\"max-w-7xl mx-auto px-4\">\n                            <div className=\"flex items-center justify-between py-2\">\n                                <div className=\"font-bold text-lg tracking-tight flex items-center gap-2 text-slate-100\">\n                                    PKF Cabrera <span className=\"font-normal text-slate-500 text-sm hidden sm:inline\">| Newsletter Generator<\/span>\n                                <\/div>\n                            <\/div>\n                            <div className=\"flex flex-wrap items-center justify-between gap-4 pb-2 border-t border-slate-800 pt-2\">\n                                <div className=\"flex gap-4\">\n                                    <button onClick={() => { setActiveTab('config'); setIsConfigOpen(true); }} className={`text-xs font-bold tracking-wide transition-colors uppercase ${activeTab === 'config' && isConfigOpen ? 'text-blue-400' : 'text-slate-400 hover:text-white'}`}>Contenido y Datos<\/button>\n                                    <button onClick={() => { setActiveTab('columnists'); setIsConfigOpen(true); }} className={`text-xs font-bold tracking-wide transition-colors uppercase ${activeTab === 'columnists' && isConfigOpen ? 'text-blue-400' : 'text-slate-400 hover:text-white'}`}>Columnistas<\/button>\n                                <\/div>\n                                <div className=\"flex items-center gap-2\">\n                                    <button onClick={handleDownloadHTML} className=\"text-xs bg-slate-800 hover:bg-slate-700 border border-slate-600 text-white px-3 py-1 rounded flex items-center gap-1 font-medium transition-colors\" title=\"Descargar c\u00f3digo\"><Icon path={icons.code} size={14}\/> <span className=\"hidden sm:inline\">HTML<\/span><\/button>\n                                    <button onClick={handlePrint} className=\"text-xs bg-blue-600 hover:bg-blue-500 text-white px-3 py-1 rounded flex items-center gap-1 font-medium transition-colors\" title=\"Imprimir\"><Icon path={icons.download} size={14}\/> <span className=\"hidden sm:inline\">PDF<\/span><\/button>\n                                    <div className=\"w-px h-4 bg-slate-700 mx-1\"><\/div>\n                                    <button onClick={() => setIsConfigOpen(!isConfigOpen)} className=\"text-xs text-slate-400 hover:text-white flex items-center gap-1 px-1\">{isConfigOpen ? <Icon path={icons.chevronUp} size={16}\/> : <Icon path={icons.chevronDown} size={16}\/>}<\/button>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    {\/* --- CONFIGURACI\u00d3N --- *\/}\n                    {isConfigOpen && (\n                        <div className=\"print-hidden bg-slate-800 border-b border-slate-700 shadow-inner animate-in fade-in slide-in-from-top-1 duration-200\">\n                            <div className=\"max-w-7xl mx-auto px-4 py-6\">\n                                {activeTab === 'config' && (\n                                    <div className=\"grid grid-cols-1 lg:grid-cols-12 gap-8 text-slate-300\">\n                                        <div className=\"lg:col-span-3 space-y-4\">\n                                            <h4 className=\"text-xs font-bold text-slate-500 uppercase border-b border-slate-700 pb-1 mb-2\">General<\/h4>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">Departamento<\/label><input type=\"text\" name=\"department\" value={config.department} onChange={handleConfigChange} className=\"w-full bg-slate-900 border border-slate-600 rounded p-2 text-white outline-none text-sm focus:border-blue-500\"\/><\/div>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">Fecha<\/label><input type=\"text\" name=\"date\" value={config.date} onChange={handleConfigChange} className=\"w-full bg-slate-900 border border-slate-600 rounded p-2 text-white outline-none text-sm focus:border-blue-500\"\/><\/div>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">Logo<\/label><select name=\"logoUrl\" value={config.logoUrl} onChange={handleConfigChange} className=\"w-full bg-slate-900 border border-slate-600 rounded p-2 text-white outline-none text-sm focus:border-blue-500\"><option value=\"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/11\/LOGO_RGB_2-LINES_coloured-pequeno.png\">Logo Color 2 L\u00edneas<\/option><option value=\"https:\/\/pkfcabrera.com\/wp-content\/uploads\/2025\/10\/LOGO_RGB_2.png\">Logo Alternativo<\/option><\/select><\/div>\n                                        <\/div>\n                                        <div className=\"lg:col-span-6 space-y-4\">\n                                            <h4 className=\"text-xs font-bold text-slate-500 uppercase border-b border-slate-700 pb-1 mb-2\">Contenido Principal<\/h4>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">T\u00edtulo (H1)<\/label><input type=\"text\" name=\"title\" value={config.title} onChange={handleConfigChange} className=\"w-full bg-slate-900 border border-slate-600 rounded p-2 text-white font-bold outline-none focus:border-blue-500\"\/><\/div>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">Cuerpo (Editor)<\/label><div className=\"text-slate-900\"><RichTextEditor value={config.bodyText} onChange={handleBodyChange} \/><\/div><\/div>\n                                        <\/div>\n                                        <div className=\"lg:col-span-3 space-y-4\">\n                                            <h4 className=\"text-xs font-bold text-slate-500 uppercase border-b border-slate-700 pb-1 mb-2\">Detalles<\/h4>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">Subt\u00edtulo (H2)<\/label><textarea name=\"subtitle\" value={config.subtitle} onChange={handleConfigChange} rows=\"3\" className=\"w-full bg-slate-900 border border-slate-600 rounded p-2 text-white outline-none text-sm focus:border-blue-500\"><\/textarea><\/div>\n                                            <div><label className=\"block text-[10px] uppercase font-bold text-slate-500 mb-1\">Imagen de Apoyo<\/label><input type=\"text\" placeholder=\"URL de imagen...\" value={config.mainImage || ''} onChange={(e) => setConfig({...config, mainImage: e.target.value})} className=\"w-full bg-slate-900 border border-slate-600 rounded p-2 text-xs text-white mb-2 focus:border-blue-500\"\/><label className=\"block w-full bg-slate-900 hover:bg-slate-700 border border-dashed border-slate-600 rounded p-2 text-center cursor-pointer text-xs transition-colors\">Subir archivo local<input type=\"file\" className=\"hidden\" accept=\"image\/*\" onChange={(e) => handleImageUpload(e, (val) => setConfig({...config, mainImage: val}))} \/><\/label><\/div>\n                                        <\/div>\n                                    <\/div>\n                                )}\n                                {activeTab === 'columnists' && (\n                                    <div className=\"space-y-4\">\n                                        <div className=\"flex justify-between items-center mb-4\"><h4 className=\"text-xs font-bold text-slate-500 uppercase\">Gesti\u00f3n de Firmas<\/h4><button onClick={addColumnist} className=\"text-xs bg-blue-600 hover:bg-blue-500 px-3 py-1.5 rounded flex items-center gap-1 font-bold transition-colors text-white\"><Icon path={icons.userPlus} size={14}\/> Agregar Nuevo<\/button><\/div>\n                                        <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n                                            {columnists.map((col) => {\n                                                const isPredefined = PREDEFINED_COLUMNISTS.some(p => p.name === col.name);\n                                                return (\n                                                    <div key={col.id} className=\"bg-slate-700 p-4 rounded border border-slate-600 relative group hover:border-slate-500 transition-colors\">\n                                                        <button onClick={() => removeColumnist(col.id)} className=\"absolute top-3 right-3 text-slate-400 hover:text-red-400 transition-colors\"><Icon path={icons.trash} size={16}\/><\/button>\n                                                        <label className=\"block text-[10px] uppercase font-bold text-slate-400 mb-1\">Cargar desde lista<\/label>\n                                                        <select value={isPredefined ? col.name : \"\"} onChange={(e) => handlePredefinedSelection(col.id, e.target.value)} className=\"w-full bg-slate-800 border border-slate-600 rounded p-2 text-xs text-white mb-4 outline-none focus:border-blue-500\"><option value=\"\">-- Manual \/ Personalizado --<\/option>{PREDEFINED_COLUMNISTS.map((p, i) => <option key={i} value={p.name}>{p.name}<\/option>)}<\/select>\n                                                        <div className=\"flex gap-4 items-center\">\n                                                            <div className=\"w-14 h-14 bg-slate-600 rounded-full overflow-hidden flex-shrink-0 border border-slate-500 relative group\/img\">\n                                                                {col.image ? (<img key={col.image} src={col.image} className=\"w-full h-full object-cover\" onError={(e) => {e.target.style.display='none'; e.target.nextSibling.style.display='flex'}} \/>) : null}\n                                                                <div className=\"absolute inset-0 bg-slate-600 flex items-center justify-center text-slate-400\" style={{display: col.image ? 'none' : 'flex'}}><Icon path={icons.userPlus} size={20}\/><\/div>\n                                                                <label className=\"absolute inset-0 bg-black\/60 hidden group-hover\/img:flex items-center justify-center cursor-pointer text-white text-[9px] font-bold\">CAMBIAR<input type=\"file\" className=\"hidden\" onChange={(e) => handleImageUpload(e, (val) => updateColumnist(col.id, 'image', val))}\/><\/label>\n                                                            <\/div>\n                                                            <div className=\"w-full space-y-2\">\n                                                                <input type=\"text\" placeholder=\"Nombre Completo\" value={col.name} onChange={(e) => updateColumnist(col.id, 'name', e.target.value)} className=\"w-full bg-transparent border-b border-slate-500 focus:border-blue-500 text-sm text-white outline-none pb-1 placeholder-slate-400\"\/>\n                                                                <input type=\"text\" placeholder=\"Cargo\" value={col.role} onChange={(e) => updateColumnist(col.id, 'role', e.target.value)} className=\"w-full bg-transparent border-b border-slate-500 focus:border-blue-500 text-xs text-slate-300 outline-none pb-1 placeholder-slate-400\"\/>\n                                                            <\/div>\n                                                        <\/div>\n                                                    <\/div>\n                                                );\n                                            })}\n                                        <\/div>\n                                    <\/div>\n                                )}\n                            <\/div>\n                        <\/div>\n                    )}\n\n                    {\/* --- VISTA PREVIA --- *\/}\n                    <div className=\"flex-grow bg-slate-200 p-8 overflow-y-auto flex justify-center items-start\">\n                        <div id=\"newsletter-content\" className=\"bg-white shadow-2xl w-full max-w-[800px] min-h-[1123px] flex flex-col relative shrink-0 print:w-full\">\n                            \n                            {\/* Brand Strip *\/}\n                            <div className=\"w-full h-2 bg-[#0B2341]\"><\/div>\n\n                            {\/* Header (Responsive Padding: px-4 en m\u00f3vil, px-8 en md) *\/}\n                            <header className=\"px-4 md:px-8 py-6 md:py-10 flex items-start justify-between border-b border-gray-100\">\n                                <div className=\"w-32 md:w-48\"><img src={config.logoUrl} alt=\"PKF Logo\" className=\"w-full h-auto object-contain\" \/><\/div>\n                                <div className=\"text-right\">\n                                    <div className=\"inline-flex items-center gap-2 text-[#0B2341] font-bold text-xs md:text-sm uppercase tracking-wide bg-slate-50 px-2 md:px-3 py-1 rounded-full mb-2\"><Icon path={icons.settings} size={14}\/><span>{config.department}<\/span><\/div>\n                                    <div className=\"flex items-center justify-end gap-2 text-slate-500 text-xs md:text-sm\"><span>{config.date}<\/span><\/div>\n                                <\/div>\n                            <\/header>\n\n                            {\/* Main Content (Responsive Padding y Text Sizes) *\/}\n                            <main className=\"flex-grow px-4 md:px-8 py-6 md:py-8\">\n                                {config.mainImage && (<div className=\"mb-6 md:mb-8 w-full h-48 md:h-64 rounded-xl overflow-hidden shadow-sm\"><img src={config.mainImage} alt=\"Main\" className=\"w-full h-full object-cover\" \/><\/div>)}\n                                <div className=\"mb-6 md:mb-8\">\n                                    <h1 className=\"text-2xl md:text-4xl font-extrabold text-slate-900 leading-tight mb-3 md:mb-4 tracking-tight\">{config.title}<\/h1>\n                                    {config.subtitle && (<h2 className=\"text-lg md:text-xl text-slate-600 font-light border-l-4 border-[#0B2341] pl-4 italic\">{config.subtitle}<\/h2>)}\n                                <\/div>\n\n                                {\/* MANEJO MANUAL DE ESTILOS DE CUERPO *\/}\n                                <div id=\"newsletter-body\" dangerouslySetInnerHTML={{ __html: config.bodyText }}><\/div>\n                            <\/main>\n\n                            {\/* Footer *\/}\n                            <section className=\"px-4 md:px-8 py-6 md:py-8 bg-slate-50 mt-8 border-t border-slate-200\">\n                                <h3 className=\"text-xs font-bold text-slate-400 uppercase tracking-widest mb-6 text-center\">An\u00e1lisis realizado por<\/h3>\n                                {\/* Responsive Grid: 1 col en m\u00f3vil, 2 en md *\/}\n                                <div className={`grid gap-6 md:gap-8 grid-cols-1 ${columnists.length > 1 ? 'md:grid-cols-2' : 'max-w-md mx-auto'}`}>\n                                    {columnists.map((col) => (\n                                        <div key={col.id} className=\"flex items-center gap-4 bg-white p-4 rounded-lg shadow-sm border border-slate-100\">\n                                            <div className=\"w-16 h-16 flex-shrink-0 rounded-full overflow-hidden border-2 border-slate-100 bg-white relative\">\n                                                {col.image ? (<img key={col.image} src={col.image} alt={col.name} className=\"w-full h-full object-cover\" onError={(e) => {e.target.style.display='none'; e.target.nextSibling.style.display='flex'}} \/>) : null}\n                                                <div className=\"absolute inset-0 bg-slate-100 flex items-center justify-center text-slate-300\" style={{display: col.image ? 'none' : 'flex'}}><Icon path={icons.userPlus} size={24}\/><\/div>\n                                            <\/div>\n                                            <div>\n                                                <h4 className=\"font-bold text-slate-900 text-lg leading-none mb-1\">{col.name}<\/h4>\n                                                <p className=\"text-[#0B2341] font-medium text-sm\">{col.role}<\/p>\n                                            <\/div>\n                                        <\/div>\n                                    ))}\n                                <\/div>\n                            <\/section>\n                            <footer className=\"bg-[#0B2341] text-white px-4 md:px-8 py-6 md:py-8 mt-auto\">\n                                <div className=\"flex flex-col md:flex-row justify-between items-center gap-4 md:gap-0\">\n                                    <div className=\"text-xs text-slate-300 max-w-lg text-center md:text-left\"><p className=\"font-semibold mb-1\">PKF Cabrera Internacional S.A. BIC<\/p><p className=\"opacity-70 leading-relaxed\">Esta informaci\u00f3n es de car\u00e1cter general y no sustituye el asesoramiento profesional. PKF Cabrera es miembro de PKF Global.<\/p><\/div>\n                                    <div className=\"text-center md:text-right\"><div className=\"text-white font-bold text-lg tracking-wider\">PKF<\/div><a href=\"https:\/\/pkfcabrera.com\" className=\"text-xs text-slate-400 hover:text-white transition-colors\">www.pkfcabrera.com<\/a><\/div>\n                                <\/div>\n                            <\/footer>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            );\n        };\n\n        const root = ReactDOM.createRoot(document.getElementById('root'));\n        root.render(<PKFNewsletterApp \/>);\n    <\/script>\n<\/body>\n<\/html><\/div><\/div><\/div><\/div><\/div><\/section>\n","protected":false},"excerpt":{"rendered":"Generador Newsletter | PKF Cabrera","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"googlesitekit_rrm_CAow3_3dCw:productID":"","rs_blank_template":"","rs_page_bg_color":"","slide_template_v7":"","footnotes":""},"class_list":["post-2354","page","type-page","status-publish","hentry"],"acf":[],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/pages\/2354","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/comments?post=2354"}],"version-history":[{"count":31,"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/pages\/2354\/revisions"}],"predecessor-version":[{"id":2364,"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/pages\/2354\/revisions\/2364"}],"wp:attachment":[{"href":"https:\/\/pkfcabrera.com\/en\/wp-json\/wp\/v2\/media?parent=2354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}