Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28cce9a68c | ||
|
|
0a88f4df20 | ||
|
|
3b38b9b760 | ||
|
|
e36ec1e8ca | ||
|
|
82816cb680 | ||
|
|
cfb97b486e |
@@ -0,0 +1,132 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es" data-theme="light">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Responder el mismo mensaje 50 veces al día no es escalable. Las automatizaciones bien hechas te permiten captar prospectos calificados mientras dormís.">
|
||||
<meta name="keywords" content="automatizaciones, Instagram, chatbots, leads, ManyChat, Amor y Roma">
|
||||
<meta property="og:title" content="Automatizaciones en Instagram: de 0 a 100 leads/mes">
|
||||
<meta property="og:description" content="Responder el mismo mensaje 50 veces al día no es escalable. Las automatizaciones bien hechas te permiten captar prospectos.">
|
||||
<meta property="og:image" content="../assets/blog/automatizacion.jpg">
|
||||
<title>Automatizaciones en Instagram | Blog Amor y Roma</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="../style/main.css">
|
||||
<link rel="stylesheet" href="../style/blog.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
<article class="articulo-completo">
|
||||
<div class="articulo-header">
|
||||
<a href="../blog.html" class="volver-link">← Volver al blog</a>
|
||||
<span class="badge-filosofia">Automatizaciones</span>
|
||||
<h1>Automatizaciones en Instagram: de 0 a 100 leads/mes sin volverte loco</h1>
|
||||
<div class="articulo-meta">
|
||||
<span>📅 12 de Agosto de 2026</span>
|
||||
<span>⏱ 9 min de lectura</span>
|
||||
<span>✍️ Amor y Roma</span>
|
||||
</div>
|
||||
<img src="../assets/blog/automatizacion.jpg" alt="Automatizaciones en Instagram" class="articulo-imagen">
|
||||
</div>
|
||||
|
||||
<div class="articulo-contenido">
|
||||
<p>Si tenés un negocio y usás Instagram para vender, probablemente vivís esto:</p>
|
||||
<ul>
|
||||
<li>Te escriben por DM preguntando lo mismo una y otra vez</li>
|
||||
<li>Se te escapan mensajes entre medio de otras tareas</li>
|
||||
<li>Perdé ventas por no responder a tiempo</li>
|
||||
<li>Pasás horas al día pegado al celular</li>
|
||||
</ul>
|
||||
<p><strong>Hay una forma mejor.</strong></p>
|
||||
|
||||
<h2>¿Qué son las automatizaciones (y qué no son)?</h2>
|
||||
<p>No son robots fríos que responden "Hola, en breve te atendemos". Eso es lo que la gente ODIA.</p>
|
||||
<p>Las automatizaciones bien hechas son flujos conversacionales inteligentes que:</p>
|
||||
<ul>
|
||||
<li>Responden al instante, 24/7</li>
|
||||
<li>Hacen preguntas para entender qué necesita la persona</li>
|
||||
<li>Filtran y cualifican leads automáticamente</li>
|
||||
<li>Derivan a WhatsApp o agendan llamadas solo cuando corresponde</li>
|
||||
<li>Recopilan datos (nombre, email, teléfono) sin que vos pidas nada</li>
|
||||
</ul>
|
||||
|
||||
<h2>El sistema de 0 a 100 leads/mes</h2>
|
||||
|
||||
<h3>Paso 1: Identificá las preguntas repetitivas</h3>
|
||||
<p>¿Qué te preguntan siempre?</p>
|
||||
<ul>
|
||||
<li>"¿Cuál es el precio?"</li>
|
||||
<li>"¿Hacés envíos a...?"</li>
|
||||
<li>"¿Tienen disponibilidad para...?"</li>
|
||||
</ul>
|
||||
<p>Esas son tus primeras automatizaciones.</p>
|
||||
|
||||
<h3>Paso 2: Creá flujos por palabras clave</h3>
|
||||
<p>En Instagram podés configurar que cuando alguien comente con cierta palabra en una publicación o historia, se dispare un mensaje automático por DM.</p>
|
||||
<p><strong>Ejemplo:</strong></p>
|
||||
<ul>
|
||||
<li>Publicás: "¿Querés saber más sobre nuestro servicio? Comentá INFO"</li>
|
||||
<li>La persona comenta "INFO"</li>
|
||||
<li>Automáticamente recibe un DM con información y preguntas de cualificación</li>
|
||||
</ul>
|
||||
|
||||
<h3>Paso 3: Cualificá antes de derivar</h3>
|
||||
<p>No todos los que escriben son clientes ideales. Tu flujo debería preguntar:</p>
|
||||
<ul>
|
||||
<li>¿Qué necesitás específicamente?</li>
|
||||
<li>¿Cuándo lo necesitás?</li>
|
||||
<li>¿Tenés presupuesto definido?</li>
|
||||
</ul>
|
||||
<p>Así solo recibís notificaciones de leads calificados.</p>
|
||||
|
||||
<h3>Paso 4: Integrá con tu CRM o base de datos</h3>
|
||||
<p>Los datos que recopilás deberían ir a algún lado útil:</p>
|
||||
<ul>
|
||||
<li>Google Sheets</li>
|
||||
<li>Tu CRM</li>
|
||||
<li>Tu plataforma de email marketing</li>
|
||||
</ul>
|
||||
<p>Así no perdés ningún prospecto y podés hacer seguimiento.</p>
|
||||
|
||||
<h2>Errores que matan tus automatizaciones</h2>
|
||||
<ul>
|
||||
<li><strong>Ser demasiado robótico:</strong> Usá un tono conversacional, como si hablaras vos.</li>
|
||||
<li><strong>Pedir demasiada información de una:</strong> Pedí solo lo esencial al principio.</li>
|
||||
<li><strong>No dar opción a hablar con humano:</strong> Siempre dejá una salida: "Si preferís hablar con alguien, escribinos 'AGENTE'".</li>
|
||||
<li><strong>Configurar y olvidar:</strong> Revisá cada tanto si los flujos funcionan y ajustá según feedback.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Herramientas que usamos en Amor y Roma</h2>
|
||||
<p>Trabajamos principalmente con:</p>
|
||||
<ul>
|
||||
<li><strong>ManyChat:</strong> El más completo para Instagram y Facebook</li>
|
||||
<li><strong>Zapier:</strong> Para conectar todo entre sí</li>
|
||||
<li><strong>Google Sheets/Airtable:</strong> Para almacenar leads</li>
|
||||
</ul>
|
||||
|
||||
<h2>El resultado: tiempo + conversión</h2>
|
||||
<p>Cuando implementamos automatizaciones para un cliente, normalmente vemos:</p>
|
||||
<ul>
|
||||
<li>⏰ <strong>8-12 horas/semana</strong> ahorradas en respuestas manuales</li>
|
||||
<li>📈 <strong>40-60% más de leads</strong> cualificados (porque no se escapa nadie)</li>
|
||||
<li> <strong>Cero estrés</strong> por "no respondí a tiempo"</li>
|
||||
</ul>
|
||||
|
||||
<blockquote>Las automatizaciones bien hechas no reemplazan la atención humana: la potencian, liberándote de lo repetitivo para que te enfoques en lo que realmente importa.</blockquote>
|
||||
|
||||
<h2>¿Listo para dejar de vivir pegado al celular?</h2>
|
||||
<p>Si sentís que Instagram te consume más tiempo del que debería, o sabés que se te escapan oportunidades por no responder rápido, hablemos. En Amor y Roma diseñamos flujos de automatización que suenan humanos, cualifican solos y te avisan solo cuando hay un lead de verdad.</p>
|
||||
|
||||
<div style="text-align: center; margin-top: 3rem;">
|
||||
<a href="../contacto.html" class="btn btn-primary">Automatizá tu Instagram</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<div id="footer-container"></div>
|
||||
<script src="../scripts/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es" data-theme="light">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="No es magia, es método. Una landing page efectiva no depende de la suerte. Acá te contamos los 7 principios que aplicamos en cada proyecto.">
|
||||
<meta name="keywords" content="landing page, conversión, desarrollo web, diseño web, Amor y Roma">
|
||||
<meta property="og:title" content="Landing pages que convierten: 7 principios probados">
|
||||
<meta property="og:description" content="No es magia, es método. Una landing page efectiva no depende de la suerte ni de tendencias pasajeras.">
|
||||
<meta property="og:image" content="../assets/blog/landing-page.jpg">
|
||||
<title>Landing pages que convierten | Blog Amor y Roma</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="../style/main.css">
|
||||
<link rel="stylesheet" href="../style/blog.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
<article class="articulo-completo">
|
||||
<div class="articulo-header">
|
||||
<a href="../blog.html" class="volver-link">← Volver al blog</a>
|
||||
<span class="badge-filosofia">Web</span>
|
||||
<h1>Landing pages que convierten: 7 principios probados</h1>
|
||||
<div class="articulo-meta">
|
||||
<span> 15 de Julio de 2026</span>
|
||||
<span>⏱ 8 min de lectura</span>
|
||||
<span>✍️ Amor y Roma</span>
|
||||
</div>
|
||||
<img src="../assets/blog/landing-page.jpg" alt="Landing page que convierte" class="articulo-imagen">
|
||||
</div>
|
||||
|
||||
<div class="articulo-contenido">
|
||||
<p>Si estás invirtiendo en publicidad o generando contenido en redes, pero tu sitio web no convierte, estás tirando plata. Literal.</p>
|
||||
<p>Una landing page (página de aterrizaje) no es un lugar bonito para mostrar información. Es una herramienta estratégica diseñada con un único objetivo: conseguir que el visitante tome una acción específica.</p>
|
||||
|
||||
<h2>Los 7 principios que usamos en Amor y Roma</h2>
|
||||
|
||||
<h3>1. Claridad antes que creatividad</h3>
|
||||
<p>Tu visitante tiene 3 segundos para entender:</p>
|
||||
<ul>
|
||||
<li>Qué ofrecés</li>
|
||||
<li>Para quién es</li>
|
||||
<li>Qué tiene que hacer</li>
|
||||
</ul>
|
||||
<p>Si necesita más tiempo, perdiste. Por eso, evitamos lenguaje rebuscado y vamos directo al grano.</p>
|
||||
|
||||
<h3>2. Un solo objetivo, un solo llamado a la acción</h3>
|
||||
<p>¿Querés que agenden una llamada? ¿Que descarguen algo? ¿Que compren? Elegí UNA cosa y eliminá toda distracción. <strong>Menos es más.</strong></p>
|
||||
|
||||
<h3>3. Beneficios, no características</h3>
|
||||
<p>A nadie le importa que tu sitio tenga "diseño responsive" o "SEO optimizado". Lo que importa es:</p>
|
||||
<ul>
|
||||
<li>"Podés contactarnos desde el celular en cualquier momento"</li>
|
||||
<li>"Te van a encontrar cuando te busquen en Google"</li>
|
||||
</ul>
|
||||
<p>Traducí cada característica en un beneficio tangible.</p>
|
||||
|
||||
<h3>4. Prueba social real</h3>
|
||||
<p>Testimonios genéricos ("Excelente servicio, muy recomendado") no sirven. Necesitás:</p>
|
||||
<ul>
|
||||
<li>Nombres reales (o al menos iniciales y cargo)</li>
|
||||
<li>Resultados específicos ("Aumentamos un 40% las consultas en 2 meses")</li>
|
||||
<li>Fotos o logos que den credibilidad</li>
|
||||
</ul>
|
||||
|
||||
<h3>5. Diseño que guía la mirada</h3>
|
||||
<p>Usamos patrones visuales probados:</p>
|
||||
<ul>
|
||||
<li><strong>F-Pattern:</strong> La gente escanea en forma de F</li>
|
||||
<li><strong>Z-Pattern:</strong> Para páginas con menos contenido</li>
|
||||
</ul>
|
||||
<p>Colocamos la información clave en esos puntos calientes.</p>
|
||||
|
||||
<h3>6. Velocidad = Conversiones</h3>
|
||||
<p>Cada segundo de carga reduce tus conversiones un 7%. Por eso:</p>
|
||||
<ul>
|
||||
<li>Optimizamos cada imagen</li>
|
||||
<li>Minimizamos código</li>
|
||||
<li>Usamos hosting de calidad</li>
|
||||
<li>Evitamos plugins innecesarios</li>
|
||||
</ul>
|
||||
|
||||
<h3>7. Mobile-first, no mobile-also</h3>
|
||||
<p>El 70%+ de tu tráfico viene del celular. Si tu sitio se ve "más o menos" en móvil, no alcanza. Tiene que ser impecable.</p>
|
||||
|
||||
<h2>El método Amor y Roma: Estrategia + Ejecución</h2>
|
||||
<p>No usamos plantillas de WordPress pesadas ni constructores visuales que ralentizan todo. Desarrollamos cada landing desde cero, pensando en:</p>
|
||||
<ul>
|
||||
<li>Tu audiencia específica</li>
|
||||
<li>Tu propuesta de valor única</li>
|
||||
<li>Tus objetivos comerciales reales</li>
|
||||
</ul>
|
||||
|
||||
<blockquote>Una landing page efectiva no es un lugar bonito. Es una herramienta estratégica diseñada con un único objetivo: conseguir que el visitante tome una acción específica.</blockquote>
|
||||
|
||||
<h2>¿Tu web convierte o solo existe?</h2>
|
||||
<p>Si sentís que tu sitio actual no está generando los resultados que esperás, o estás por lanzar algo nuevo y querés hacerlo bien, conversemos. Desarrollamos landing pages y sitios web a medida que no solo se ven bien, sino que trabajan para vos 24/7.</p>
|
||||
|
||||
<div style="text-align: center; margin-top: 3rem;">
|
||||
<a href="../contacto.html" class="btn btn-primary">Desarrollá tu landing page</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<div id="footer-container"></div>
|
||||
<script src="../scripts/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es" data-theme="light">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Muchos emprendedores confunden el símbolo con la sustancia. Tener un logo bonito no es tener una marca. Acá te explicamos la diferencia.">
|
||||
<meta name="keywords" content="branding, logo, identidad de marca, diseño estratégico, Amor y Roma">
|
||||
<meta property="og:title" content="Tu logo no es tu marca (y por qué importa)">
|
||||
<meta property="og:description" content="Muchos emprendedores confunden el símbolo con la sustancia. Tener un logo bonito no es tener una marca.">
|
||||
<meta property="og:image" content="../assets/blog/logo-marca.jpg">
|
||||
<title>Tu logo no es tu marca | Blog Amor y Roma</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="../style/main.css">
|
||||
<link rel="stylesheet" href="../style/blog.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
<article class="articulo-completo">
|
||||
<div class="articulo-header">
|
||||
<a href="../blog.html" class="volver-link">← Volver al blog</a>
|
||||
<span class="badge-filosofia">Branding</span>
|
||||
<h1>Tu logo no es tu marca (y por qué importa)</h1>
|
||||
<div class="articulo-meta">
|
||||
<span>📅 10 de Junio de 2026</span>
|
||||
<span>⏱ 6 min de lectura</span>
|
||||
<span>✍️ Amor y Roma</span>
|
||||
</div>
|
||||
<img src="../assets/blog/logo-marca.jpg" alt="Logo vs Marca" class="articulo-imagen">
|
||||
</div>
|
||||
|
||||
<div class="articulo-contenido">
|
||||
<p>Cuando nos dicen "necesito un logo", en realidad escuchamos "necesito que mi marca exista". Y ahí está el primer error conceptual que puede costarte caro.</p>
|
||||
|
||||
<h2>Logo vs. Marca: la diferencia fundamental</h2>
|
||||
<p>El logo es solo la punta del iceberg. Es el símbolo visual que representa algo mucho más grande: tu promesa de valor, tu personalidad, tu forma de operar en el mundo. La marca, en cambio, es la experiencia completa que las personas tienen con tu negocio.</p>
|
||||
<p><strong>Pensalo así: el logo es tu firma. La marca es tu reputación.</strong></p>
|
||||
|
||||
<h2>¿Por qué las plantillas de branding no funcionan?</h2>
|
||||
<p>En un mundo saturado de Canva y logos pre-fabricados, la tentación de "resolver rápido" es enorme. Pero cuando usás una plantilla:</p>
|
||||
<ul>
|
||||
<li><strong>Perdés diferenciación:</strong> Si tu logo se parece al de otros 50 negocios, ¿por qué te elegirían a vos?</li>
|
||||
<li><strong>No comunicás tu esencia:</strong> Un símbolo genérico no transmite tu historia, tus valores ni tu forma única de operar.</li>
|
||||
<li><strong>Limitás tu crecimiento:</strong> Lo que funciona hoy para un emprendimiento incipiente, mañana puede quedar chico para una empresa consolidada.</li>
|
||||
</ul>
|
||||
|
||||
<h2>El branding estratégico: Amor + Roma en acción</h2>
|
||||
<p>En Amor y Roma, no empezamos dibujando. Empezamos preguntando:</p>
|
||||
<ul>
|
||||
<li>¿Qué problema resolvés?</li>
|
||||
<li>¿A quién le hablás?</li>
|
||||
<li>¿Qué te hace diferente?</li>
|
||||
<li>¿Cómo querés que se sienta la gente al interactuar con vos?</li>
|
||||
</ul>
|
||||
<p>Recién después de entender eso, construimos:</p>
|
||||
<ul>
|
||||
<li><strong>Arquetipo de marca:</strong> ¿Sos el héroe, el sabio, el creador? Esto define tu personalidad.</li>
|
||||
<li><strong>Sistema visual completo:</strong> No solo un logo, sino colores, tipografías, estilos de imagen que funcionen juntos.</li>
|
||||
<li><strong>Manual de aplicación:</strong> Para que tu marca se vea coherente en cada punto de contacto.</li>
|
||||
<li><strong>Personajes o elementos distintivos:</strong> Si aplica, creamos activos que humanicen tu comunicación.</li>
|
||||
</ul>
|
||||
|
||||
<h2>El resultado: una marca que resuena</h2>
|
||||
<p>Cuando invertís en branding estratégico, no estás comprando "un dibujo lindo". Estás construyendo:</p>
|
||||
<ul>
|
||||
<li><strong>Reconocimiento:</strong> La gente te identifica al instante.</li>
|
||||
<li><strong>Confianza:</strong> Transmitís profesionalismo y solidez.</li>
|
||||
<li><strong>Conexión emocional:</strong> Tu audiencia se siente representada por vos.</li>
|
||||
<li><strong>Base para crecer:</strong> Tenés los cimientos para escalar sin perder identidad.</li>
|
||||
</ul>
|
||||
|
||||
<blockquote>Una marca bien construida no solo se ve profesional: genera confianza, atrae clientes ideales y permite cobrar lo que realmente valés.</blockquote>
|
||||
|
||||
<h2>¿Estás listo para construir una marca, no solo un logo?</h2>
|
||||
<p>Si sentís que tu identidad actual no te representa, o estás empezando y querés hacerlo bien desde el inicio, hablemos. En Amor y Roma diseñamos identidades con esencia y estrategia, sin plantillas ni fórmulas repetidas.</p>
|
||||
|
||||
<div style="text-align: center; margin-top: 3rem;">
|
||||
<a href="../contacto.html" class="btn btn-primary">Hablemos sobre tu marca</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<div id="footer-container"></div>
|
||||
<script src="../scripts/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="64px" height="64px" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
|
||||
viewBox="0 0 5.34 5.31"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<g id="Capa_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_2347189464160">
|
||||
<path fill="#221728" fill-opacity="0.250980" d="M2.67 0c1.47,0 2.67,1.19 2.67,2.65 0,1.47 -1.2,2.66 -2.67,2.66 -1.47,0 -2.67,-1.19 -2.67,-2.66 0,-1.46 1.2,-2.65 2.67,-2.65z"/>
|
||||
<path fill="#221728" d="M0.24 3.79c0.29,0.65 0.98,1.28 1.78,1.46l0 -1.77 -0.55 0 -0.01 -0.83 0.55 0.01c0.06,-0.62 -0.02,-1.13 0.4,-1.44 0.39,-0.27 0.98,-0.27 1.5,-0.18l-0.01 0.75c-0.78,-0.05 -0.96,0.06 -0.9,0.87l0.86 -0.01 -0.16 0.83 -0.71 0.01 0 1.82c0.92,-0.08 1.72,-0.74 2.08,-1.47 0.29,-0.61 0.35,-1.32 0.15,-1.96 -0.14,-0.43 -0.36,-0.82 -0.66,-1.11 -1.06,-1.03 -2.83,-1.04 -3.86,0.05 -0.73,0.78 -0.9,2 -0.46,2.97z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="64px" height="64px" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
|
||||
viewBox="0 0 7.24 7.24"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<g id="Capa_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_2346936265280">
|
||||
<path fill="#221728" d="M2.1 0.58c0.23,-0.02 0.51,0 0.75,0 0.51,0 1.01,0 1.52,0 0.25,0 0.52,-0.01 0.76,0 0.83,0.04 1.48,0.69 1.53,1.51 0.01,0.24 0,0.52 0,0.76l0 1.52c0,0.25 0.01,0.52 0,0.76 -0.04,0.83 -0.69,1.48 -1.52,1.53 -0.23,0.01 -0.51,0 -0.75,0l-1.52 0c-0.25,0 -0.52,0.01 -0.76,0 -0.83,-0.04 -1.48,-0.69 -1.53,-1.52 -0.02,-0.23 0,-0.51 0,-0.75l0 -1.52c0,-0.53 -0.06,-0.91 0.15,-1.37 0.23,-0.51 0.75,-0.88 1.37,-0.92zm-0.02 -0.57c-1.02,0.06 -1.77,0.77 -2,1.62 -0.08,0.28 -0.08,0.51 -0.08,0.82l0 1.81c0,0.29 -0.01,0.61 0.01,0.9 0.05,1.01 0.78,1.78 1.61,2 0.29,0.07 0.52,0.07 0.83,0.07 0.6,0 1.2,0 1.81,0 0.29,0 0.61,0.02 0.9,0 1.01,-0.05 1.77,-0.77 2,-1.62 0.07,-0.28 0.07,-0.51 0.07,-0.82l0 -1.81c0,-0.29 0.01,-0.61 0,-0.9 -0.06,-1.01 -0.78,-1.78 -1.62,-2 -0.28,-0.08 -0.51,-0.07 -0.82,-0.07l-1.81 0c-0.29,0 -0.62,-0.02 -0.9,0z"/>
|
||||
<path fill="#221728" d="M3.53 2.29c0.27,-0.02 0.58,0.06 0.8,0.2 0.1,0.07 0.1,0.07 0.18,0.14 0.11,0.09 0.22,0.23 0.29,0.38 0.21,0.41 0.2,0.93 -0.05,1.32 -0.07,0.11 -0.07,0.09 -0.14,0.18 -0.1,0.11 -0.25,0.23 -0.38,0.3 -0.16,0.07 -0.32,0.12 -0.52,0.14 -0.77,0.05 -1.37,-0.54 -1.42,-1.24 -0.01,-0.21 0.02,-0.41 0.09,-0.58 0.07,-0.18 0.14,-0.27 0.25,-0.41 0.21,-0.25 0.56,-0.4 0.9,-0.43zm-0.01 -0.57c-1.02,0.06 -1.86,0.92 -1.8,2 0.05,1.01 0.92,1.86 2,1.8 1.01,-0.06 1.86,-0.92 1.8,-2.01 -0.06,-1 -0.92,-1.85 -2,-1.79z"/>
|
||||
<path fill="#221728" fill-opacity="0.250980" d="M3.53 2.29c-0.34,0.03 -0.69,0.18 -0.9,0.43 -0.11,0.14 -0.18,0.23 -0.25,0.41 -0.07,0.17 -0.1,0.37 -0.09,0.58 0.05,0.7 0.65,1.29 1.42,1.24 0.2,-0.02 0.36,-0.07 0.52,-0.14 0.13,-0.07 0.28,-0.19 0.38,-0.3 0.07,-0.09 0.07,-0.07 0.14,-0.18 0.25,-0.39 0.26,-0.91 0.05,-1.32 -0.07,-0.15 -0.18,-0.29 -0.29,-0.38 -0.08,-0.07 -0.08,-0.07 -0.18,-0.14 -0.22,-0.14 -0.53,-0.22 -0.8,-0.2zm-0.01 -0.57c1.08,-0.06 1.94,0.79 2,1.79 0.06,1.09 -0.79,1.95 -1.8,2.01 -1.08,0.06 -1.95,-0.79 -2,-1.8 -0.06,-1.08 0.78,-1.94 1.8,-2zm1.95 -0.38c0.22,-0.03 0.4,0.13 0.43,0.32 0.03,0.22 -0.13,0.41 -0.32,0.43 -0.23,0.04 -0.41,-0.13 -0.44,-0.32 -0.03,-0.23 0.14,-0.4 0.33,-0.43zm-3.37 -0.76c-0.62,0.04 -1.14,0.41 -1.37,0.92 -0.21,0.46 -0.15,0.84 -0.15,1.37l0 1.52c0,0.24 -0.02,0.52 0,0.75 0.05,0.83 0.7,1.48 1.53,1.52 0.24,0.01 0.51,0 0.76,0l1.52 0c0.24,0 0.52,0.01 0.75,0 0.83,-0.05 1.48,-0.7 1.52,-1.53 0.01,-0.24 0,-0.51 0,-0.76l0 -1.52c0,-0.24 0.01,-0.52 0,-0.76 -0.05,-0.82 -0.7,-1.47 -1.53,-1.51 -0.24,-0.01 -0.51,0 -0.76,0 -0.51,0 -1.01,0 -1.52,0 -0.24,0 -0.52,-0.02 -0.75,0z"/>
|
||||
<path fill="#221728" d="M5.47 1.34c-0.19,0.03 -0.36,0.2 -0.33,0.43 0.03,0.19 0.21,0.36 0.44,0.32 0.19,-0.02 0.35,-0.21 0.32,-0.43 -0.03,-0.19 -0.21,-0.35 -0.43,-0.32z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="64px" height="64px" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
|
||||
viewBox="0 0 4.52 4.52"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<g id="Capa_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_2346933204656">
|
||||
<polygon fill="#221728" fill-opacity="0.250980" stroke="#373435" stroke-width="0.02" stroke-miterlimit="22.9256" stroke-opacity="0.250980" points="0.28,0.35 4.19,0.35 4.19,4.2 0.28,4.2 "/>
|
||||
<path fill="#221728" d="M0.7 1.72l0.67 0c0.01,0.16 0,0.37 0,0.54l0 1.49c0,0.02 0,0.05 0,0.07 0,0.03 0.01,0.03 -0.01,0.05l-0.66 0 0 -2.15zm1.73 0.29c0.05,-0.03 0.06,-0.14 0.26,-0.25 0.31,-0.18 0.87,-0.13 1.06,0.24 0.13,0.26 0.12,0.55 0.12,0.87 0,0.33 0,0.67 0,1l-0.67 0c0,-0.33 0,-0.67 0,-1 0,-0.32 0,-0.63 -0.37,-0.62 -0.35,0.02 -0.38,0.31 -0.38,0.63 0,0.33 0,0.66 0,0.99l-0.66 0 0 -2.15 0.64 0 0 0.29zm-1.45 -1.36c0.22,-0.03 0.41,0.13 0.44,0.33 0.07,0.51 -0.69,0.61 -0.77,0.12 -0.04,-0.24 0.13,-0.42 0.33,-0.45zm-0.4 -0.64c-0.3,0.04 -0.54,0.26 -0.57,0.56 -0.02,0.15 -0.01,2.5 -0.01,2.82 0,0.16 -0.01,0.4 0.01,0.55 0.03,0.3 0.27,0.53 0.56,0.57 0.15,0.01 2.49,0 2.82,0 0.16,0 0.4,0.02 0.55,0 0.3,-0.04 0.53,-0.27 0.57,-0.57 0.01,-0.14 0,-2.49 0,-2.81 0,-0.16 0.02,-0.4 0,-0.56 -0.04,-0.29 -0.27,-0.53 -0.57,-0.56 -0.14,-0.02 -2.49,-0.01 -2.81,-0.01 -0.16,0 -0.4,-0.01 -0.55,0.01z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="40px" height="40px" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
|
||||
viewBox="0 0 10.64 10.63"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<g id="Capa_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_2348118537696">
|
||||
<path fill="#221728" d="M3.3 2.99c-0.45,0.32 -0.61,0.87 -0.5,1.4 0.19,1 1.46,2.29 2.19,2.7 0.09,0.05 0.24,0.11 0.32,0.17l0.63 0.27c0.2,0 0.52,0.22 0.99,0.11 0.21,-0.04 0.44,-0.14 0.6,-0.27 0.17,-0.16 0.34,-0.37 0.37,-0.61 0.02,-0.14 0,-0.23 -0.04,-0.29 -0.1,-0.18 -0.78,-0.61 -1.09,-0.63 -0.2,-0.01 -0.25,-0.01 -0.36,0.12 -0.02,0.05 -0.14,0.2 -0.21,0.31 -0.06,0.1 -0.12,0.24 -0.28,0.23 -0.6,-0.11 -1.43,-0.9 -1.76,-1.42 -0.09,-0.15 -0.1,-0.24 0,-0.37 0.11,-0.15 0.25,-0.26 0.31,-0.5 0.02,-0.3 -0.22,-0.88 -0.41,-1.12 -0.06,-0.07 -0.11,-0.12 -0.21,-0.16 -0.04,-0.02 -0.08,-0.03 -0.12,-0.03 -0.14,-0.02 -0.16,-0.03 -0.27,0.02l-0.16 0.07z"/>
|
||||
<path fill="#221728" fill-opacity="0.250980" stroke="#373435" stroke-width="0.03" stroke-miterlimit="22.9256" stroke-opacity="0.250980" d="M1.2 4.14c0.04,-0.15 0.15,-0.53 0.2,-0.58 0.11,-0.44 0.86,-1.29 1.14,-1.53 0.48,-0.39 1.09,-0.71 1.75,-0.89 1.46,-0.42 3.02,0.07 4.09,1.13 0.17,0.17 0.33,0.36 0.48,0.58 0.25,0.35 0.54,0.9 0.62,1.33 0.1,0.22 0.15,0.85 0.15,1.14 0,0.17 -0.02,0.44 -0.07,0.73 -0.09,0.61 -0.25,0.99 -0.56,1.51 -0.05,0.09 -0.16,0.25 -0.23,0.34 -1.27,1.7 -3.59,2.24 -5.52,1.17 -0.06,-0.03 -0.19,-0.09 -0.22,-0.14 -0.18,-0.06 -0.53,0.1 -0.73,0.14 -0.06,0.03 -0.45,0.13 -0.51,0.12 -0.06,0.06 -0.38,0.12 -0.45,0.13 0.02,-0.14 0.1,-0.37 0.11,-0.4l0.02 -0.03c-0.01,-0.08 0.24,-1 0.28,-1.1 0.01,-0.1 -0.01,-0.09 -0.04,-0.17 -0.05,-0.04 -0.24,-0.4 -0.28,-0.5 -0.41,-0.58 -0.46,-1.92 -0.33,-2.61 0.01,-0.07 0.07,-0.28 0.1,-0.37zm2.1 -1.15c-0.45,0.32 -0.61,0.87 -0.5,1.4 0.19,1 1.46,2.29 2.19,2.7 0.09,0.05 0.24,0.11 0.32,0.17l0.63 0.27c0.2,0 0.52,0.22 0.99,0.11 0.21,-0.04 0.44,-0.14 0.6,-0.27 0.17,-0.16 0.34,-0.37 0.37,-0.61 0.02,-0.14 0,-0.23 -0.04,-0.29 -0.1,-0.18 -0.78,-0.61 -1.09,-0.63 -0.2,-0.01 -0.25,-0.01 -0.36,0.12 -0.02,0.05 -0.14,0.2 -0.21,0.31 -0.06,0.1 -0.12,0.24 -0.28,0.23 -0.6,-0.11 -1.43,-0.9 -1.76,-1.42 -0.09,-0.15 -0.1,-0.24 0,-0.37 0.11,-0.15 0.25,-0.26 0.31,-0.5 0.02,-0.3 -0.22,-0.88 -0.41,-1.12 -0.06,-0.07 -0.11,-0.12 -0.21,-0.16 -0.04,-0.02 -0.08,-0.03 -0.12,-0.03 -0.14,-0.02 -0.16,-0.03 -0.27,0.02l-0.16 0.07z"/>
|
||||
<path fill="#221728" d="M1.2 4.14c0.04,-0.15 0.15,-0.53 0.2,-0.58 0.11,-0.44 0.86,-1.29 1.14,-1.53 0.48,-0.39 1.09,-0.71 1.75,-0.89 1.46,-0.42 3.02,0.07 4.09,1.13 0.17,0.17 0.33,0.36 0.48,0.58 0.25,0.35 0.54,0.9 0.62,1.33 0.1,0.22 0.15,0.85 0.15,1.14 0,0.17 -0.02,0.44 -0.07,0.73 -0.09,0.61 -0.25,0.99 -0.56,1.51 -0.05,0.09 -0.16,0.25 -0.23,0.34 -1.27,1.7 -3.59,2.24 -5.52,1.17 -0.06,-0.03 -0.19,-0.09 -0.22,-0.14 -0.18,-0.06 -0.53,0.1 -0.73,0.14 -0.06,0.03 -0.45,0.13 -0.51,0.12 -0.06,0.06 -0.38,0.12 -0.45,0.13 0.02,-0.14 0.1,-0.37 0.11,-0.4l0.02 -0.03c-0.01,-0.08 0.24,-1 0.28,-1.1 0.01,-0.1 -0.01,-0.09 -0.04,-0.17 -0.05,-0.04 -0.24,-0.4 -0.28,-0.5 -0.41,-0.58 -0.46,-1.92 -0.33,-2.61 0.01,-0.07 0.07,-0.28 0.1,-0.37zm0.59 -2.77c-0.42,0.4 -0.74,0.73 -1.05,1.28 -0.06,0.1 -0.11,0.2 -0.16,0.3 -0.06,0.11 -0.1,0.2 -0.15,0.32l-0.09 0.25c-0.03,0.07 -0.01,0.04 -0.05,0.08 0,0.09 -0.13,0.49 -0.16,0.64 -0.05,0.23 -0.08,0.47 -0.09,0.71 -0.06,0.81 0.1,1.3 0.1,1.5 0.04,0.04 0.08,0.26 0.09,0.33 0.04,0.13 0.08,0.23 0.11,0.35 0.04,0.05 0.14,0.33 0.18,0.41 0.05,0.11 0.18,0.28 0.15,0.41 -0.02,0.09 -0.23,0.9 -0.25,0.92 -0.03,0.13 -0.07,0.25 -0.1,0.37 -0.01,0.07 -0.06,0.29 -0.1,0.34 -0.32,1.01 -0.35,1.14 0.35,0.99 0.03,-0.02 0.48,-0.13 0.54,-0.13l0.64 -0.18c0.04,-0.03 0.47,-0.14 0.53,-0.14 0.01,0 0.01,-0.01 0.04,-0.02 0.03,-0.01 0.04,-0.01 0.08,-0.02 0.08,-0.03 0.21,-0.05 0.31,-0.08 0.12,-0.04 0.17,0.01 0.28,0.07 0.14,0.07 0.48,0.19 0.56,0.24 0.11,0.02 0.21,0.07 0.32,0.1 0.25,0.06 0.45,0.12 0.72,0.15 0.14,0.02 0.27,0.04 0.41,0.05 0.28,0.01 0.63,0.01 0.9,-0.03 0.95,-0.15 2.17,-0.61 2.88,-1.24 0.06,-0.06 0.02,-0.03 0.09,-0.06 0.02,-0.04 0.04,-0.05 0.08,-0.09 0.04,-0.03 0.06,-0.05 0.1,-0.09 0.55,-0.56 1.28,-1.87 1.46,-2.62 0.27,-1.19 0.02,-1.89 0.04,-2.19 -0.04,-0.05 -0.03,-0.09 -0.05,-0.18 -0.05,-0.22 -0.12,-0.38 -0.16,-0.56 -0.02,-0.03 -0.21,-0.5 -0.21,-0.54 -0.05,-0.03 -0.06,-0.08 -0.08,-0.13 -0.06,-0.08 -0.09,-0.17 -0.14,-0.25 -0.05,-0.07 -0.11,-0.16 -0.14,-0.24 -0.1,-0.11 -0.19,-0.28 -0.33,-0.43 -0.07,-0.07 -0.12,-0.14 -0.18,-0.21 -0.12,-0.15 -0.45,-0.45 -0.57,-0.55 -0.54,-0.46 -1.49,-0.87 -2.19,-1.07 -0.53,-0.09 -0.99,-0.17 -1.55,-0.11 -0.27,0.02 -0.48,0.04 -0.73,0.1 -0.51,0.11 -0.91,0.26 -1.32,0.48 -0.41,0.21 -0.78,0.45 -1.11,0.77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Enlaces oficiales de Estudio Creativo. Transformando ideas en experiencias visuales extraordinarias.">
|
||||
<title>Estudio Creativo - Enlaces</title>
|
||||
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="images/icons/favicon.png" type="image/x-icon">
|
||||
|
||||
<!-- Fuentes sincronizadas con main.css -->
|
||||
|
||||
@@ -4,29 +4,32 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Blog de Amor y Roma. Estrategia, branding, desarrollo web y marketing digital con esencia y solidez.">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css">
|
||||
<title>Blog | Amor y Roma — Recursos y Estrategias</title>
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/blog.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="fluid-bg" aria-hidden="true">
|
||||
<canvas id="fluidCanvas"></canvas>
|
||||
</div>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
<!-- SECCIÓN 1: HERO COMPACTO -->
|
||||
<!-- HERO -->
|
||||
<section class="blog-hero-compact">
|
||||
<div class="hero-compact-content">
|
||||
<span class="badge-filosofia"></span>
|
||||
<h1 class="hero-compact-title">Ideas que construyen marcas</h1>
|
||||
<span class="badge-filosofia">Ideas que construyen marcas</span>
|
||||
<h1 class="hero-compact-title">Estrategia, diseño y tecnología explicados sin tecnicismos</h1>
|
||||
<p class="hero-compact-subtitle">
|
||||
Estrategia, diseño y tecnología explicados sin tecnicismos innecesarios.
|
||||
Consejos prácticos de branding, web y marketing digital para hacer crecer tu negocio con esencia y estructura.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SECCIÓN 2: HEADER DE FILTROS (STICKY CON BUSCADOR) -->
|
||||
<section class="blog-filters-header" id="blog-filters-header">
|
||||
<div class="filters-header-container">
|
||||
|
||||
<!-- Fila superior: Buscador + Filtros principales -->
|
||||
<!-- FILTROS -->
|
||||
<section class="blog-filters-section" id="blog-filters-header">
|
||||
<div class="filters-container">
|
||||
<div class="filters-top-row">
|
||||
<div class="search-wrapper-compact">
|
||||
<span class="search-icon">
|
||||
@@ -35,13 +38,7 @@
|
||||
<path d="m21 21-4.35-4.35"/>
|
||||
</svg>
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
id="blog-search"
|
||||
placeholder="Buscá por tema: branding, web, redes..."
|
||||
autocomplete="off"
|
||||
aria-label="Buscar artículos"
|
||||
>
|
||||
<input type="text" id="blog-search" placeholder="Buscá por tema: branding, web, redes..." autocomplete="off" aria-label="Buscar artículos">
|
||||
<button class="search-clear" id="search-clear" type="button" aria-label="Limpiar búsqueda">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M18 6 6 18M6 6l12 12"/>
|
||||
@@ -55,7 +52,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fila inferior: Categorías + Ordenamiento -->
|
||||
<div class="filters-bottom-row">
|
||||
<div class="filter-categories-compact">
|
||||
<button class="category-btn active" data-category="all">Todas</button>
|
||||
@@ -72,12 +68,10 @@
|
||||
<select id="sort-select" class="sort-select-compact">
|
||||
<option value="recent">Más recientes</option>
|
||||
<option value="popular">Más populares</option>
|
||||
<option value="alphabetical">A-Z</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info de resultados -->
|
||||
<div class="results-info-compact">
|
||||
<span id="results-count">Mostrando <strong>todos</strong> los artículos</span>
|
||||
<button class="reset-filters-compact" id="reset-filters">Limpiar filtros</button>
|
||||
@@ -85,224 +79,27 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SECCIÓN 3: ARTÍCULOS DESTACADOS -->
|
||||
<section class="featured-posts" id="featured-posts">
|
||||
<!-- DESTACADOS (Se llena dinámicamente con JS) -->
|
||||
<section class="featured-posts" id="featured-posts" style="display: none;">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Más leídos</h2>
|
||||
<p class="section-subtitle">Los artículos que más están ayudando a marcas como la tuya.</p>
|
||||
</div>
|
||||
|
||||
<div class="featured-grid">
|
||||
<!-- Artículo destacado 1 -->
|
||||
<article class="featured-card" data-categories="branding estrategia" data-tags="identidad, marca, posicionamiento" data-featured="true">
|
||||
<div class="featured-image">
|
||||
<img src="../assets/blog/branding-completo.jpg" alt="Guía completa de branding">
|
||||
<span class="featured-badge">Más leído</span>
|
||||
</div>
|
||||
<div class="featured-content">
|
||||
<div class="featured-meta">
|
||||
<span class="category-tag branding">Branding</span>
|
||||
<time datetime="2024-01-15">15 Ene 2024</time>
|
||||
</div>
|
||||
<h3 class="featured-title">Guía completa: Cómo construir una identidad de marca que perdure</h3>
|
||||
<p class="featured-excerpt">
|
||||
Desde el diagnóstico inicial hasta el manual de identidad. Todo lo que necesitás saber para crear una marca con esencia y solidez estratégica.
|
||||
</p>
|
||||
<div class="featured-footer">
|
||||
<span class="reading-time">⏱ 12 min de lectura</span>
|
||||
<a href="#" class="btn-read">Leer artículo →</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Artículo destacado 2 -->
|
||||
<article class="featured-card" data-categories="web" data-tags="landing page, conversión, diseño" data-featured="true">
|
||||
<div class="featured-image">
|
||||
<img src="../assets/blog/landing-page.jpg" alt="Landing pages">
|
||||
</div>
|
||||
<div class="featured-content">
|
||||
<div class="featured-meta">
|
||||
<span class="category-tag web">Web</span>
|
||||
<time datetime="2024-01-10">10 Ene 2024</time>
|
||||
</div>
|
||||
<h3 class="featured-title">Landing pages que convierten: 7 principios probados</h3>
|
||||
<p class="featured-excerpt">
|
||||
Estructura, copy y diseño working together para transformar visitantes en clientes reales.
|
||||
</p>
|
||||
<div class="featured-footer">
|
||||
<span class="reading-time">⏱ 8 min de lectura</span>
|
||||
<a href="#" class="btn-read">Leer artículo →</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Artículo destacado 3 -->
|
||||
<article class="featured-card" data-categories="automatizaciones" data-tags="instagram, chatbots, leads" data-featured="true">
|
||||
<div class="featured-image">
|
||||
<img src="../assets/blog/automatizacion.jpg" alt="Automatizaciones">
|
||||
</div>
|
||||
<div class="featured-content">
|
||||
<div class="featured-meta">
|
||||
<span class="category-tag automatizaciones">Automatizaciones</span>
|
||||
<time datetime="2024-01-05">5 Ene 2024</time>
|
||||
</div>
|
||||
<h3 class="featured-title">Automatizaciones en Instagram: de 0 a 100 leads/mes</h3>
|
||||
<p class="featured-excerpt">
|
||||
Flujos inteligentes que trabajan 24/7 mientras vos te enfocás en lo que mejor sabés hacer.
|
||||
</p>
|
||||
<div class="featured-footer">
|
||||
<span class="reading-time"> 9 min de lectura</span>
|
||||
<a href="#" class="btn-read">Leer artículo →</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<div class="featured-grid" id="featured-grid">
|
||||
<!-- JS inyecta las tarjetas aquí -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SECCIÓN 4: GRID DE ARTÍCULOS -->
|
||||
<!-- GRID DE ARTÍCULOS (Se llena dinámicamente con JS) -->
|
||||
<section class="blog-grid-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title" id="grid-section-title">Ideas frescas</h2>
|
||||
<p class="section-subtitle">Encontrá nuestros últimos articulos de vanguardia.</p>
|
||||
</div>
|
||||
<div class="blog-grid" id="blog-grid">
|
||||
|
||||
<!-- ARTÍCULO 1 -->
|
||||
<article class="blog-card" data-categories="redes estrategia" data-tags="contenido, planificación, calendario" data-featured="false">
|
||||
<div class="card-image">
|
||||
<img src="../assets/blog/contenido-redes.jpg" alt="Contenido para redes">
|
||||
<span class="card-category redes">Redes</span>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-meta">
|
||||
<time datetime="2024-01-20">20 Ene 2024</time>
|
||||
<span class="reading-time-mini">8 min</span>
|
||||
</div>
|
||||
<h3 class="card-title">Planificación de contenido: el método de los 3 pilares</h3>
|
||||
<p class="card-excerpt">
|
||||
Cómo estructurar tu calendario editorial para mantener coherencia sin volverte loco.
|
||||
</p>
|
||||
<div class="card-tags">
|
||||
<span class="tag">Contenido</span>
|
||||
<span class="tag">Planificación</span>
|
||||
</div>
|
||||
<a href="#" class="card-link">Leer artículo</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- ARTÍCULO 2 -->
|
||||
<article class="blog-card" data-categories="branding" data-tags="logo, identidad, diseño" data-featured="false">
|
||||
<div class="card-image">
|
||||
<img src="../assets/blog/logo-design.jpg" alt="Diseño de logo">
|
||||
<span class="card-category branding">Branding</span>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-meta">
|
||||
<time datetime="2024-01-18">18 Ene 2024</time>
|
||||
<span class="reading-time-mini">6 min</span>
|
||||
</div>
|
||||
<h3 class="card-title">Tu logo no es tu marca (y por qué importa)</h3>
|
||||
<p class="card-excerpt">
|
||||
La diferencia entre un símbolo bonito y una identidad estratégica que realmente funciona.
|
||||
</p>
|
||||
<div class="card-tags">
|
||||
<span class="tag">Logo</span>
|
||||
<span class="tag">Identidad</span>
|
||||
</div>
|
||||
<a href="#" class="card-link">Leer artículo</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- ARTÍCULO 3 -->
|
||||
<article class="blog-card" data-categories="web paid" data-tags="seo, google ads, tráfico" data-featured="false">
|
||||
<div class="card-image">
|
||||
<img src="../assets/blog/seo-web.jpg" alt="SEO">
|
||||
<span class="card-category web">Web</span>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-meta">
|
||||
<time datetime="2024-01-12">12 Ene 2024</time>
|
||||
<span class="reading-time-mini">10 min</span>
|
||||
</div>
|
||||
<h3 class="card-title">SEO vs Paid Media: cuándo usar cada uno</h3>
|
||||
<p class="card-excerpt">
|
||||
No son enemigos, son complementarios. Te explicamos cómo combinarlos estratégicamente.
|
||||
</p>
|
||||
<div class="card-tags">
|
||||
<span class="tag">SEO</span>
|
||||
<span class="tag">Google Ads</span>
|
||||
</div>
|
||||
<a href="#" class="card-link">Leer artículo</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- ARTÍCULO 4 -->
|
||||
<article class="blog-card" data-categories="casos estrategia" data-tags="caso de éxito, tecnología, ecosistema" data-featured="false">
|
||||
<div class="card-image">
|
||||
<img src="../assets/blog/caso-tech.jpg" alt="Caso de éxito">
|
||||
<span class="card-category casos">Casos</span>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-meta">
|
||||
<time datetime="2024-01-08">8 Ene 2024</time>
|
||||
<span class="reading-time-mini">7 min</span>
|
||||
</div>
|
||||
<h3 class="card-title">Caso de éxito: Ecosistema digital para startup tech</h3>
|
||||
<p class="card-excerpt">
|
||||
Cómo construimos una presencia integral desde cero: branding, web y redes en 90 días.
|
||||
</p>
|
||||
<div class="card-tags">
|
||||
<span class="tag">Caso de Éxito</span>
|
||||
<span class="tag">Tecnología</span>
|
||||
</div>
|
||||
<a href="#" class="card-link">Leer artículo</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- ARTÍCULO 5 -->
|
||||
<article class="blog-card" data-categories="automatizaciones redes" data-tags="manychat, instagram, ventas" data-featured="false">
|
||||
<div class="card-image">
|
||||
<img src="../assets/blog/chatbot.jpg" alt="Chatbot">
|
||||
<span class="card-category automatizaciones">Automatizaciones</span>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-meta">
|
||||
<time datetime="2024-01-03">3 Ene 2024</time>
|
||||
<span class="reading-time-mini">9 min</span>
|
||||
</div>
|
||||
<h3 class="card-title">Chatbots que no parecen robots: la clave está en el copy</h3>
|
||||
<p class="card-excerpt">
|
||||
Cómo escribir flujos de conversación que suenen humanos y realmente vendan.
|
||||
</p>
|
||||
<div class="card-tags">
|
||||
<span class="tag">ManyChat</span>
|
||||
<span class="tag">Ventas</span>
|
||||
</div>
|
||||
<a href="#" class="card-link">Leer artículo</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- ARTÍCULO 6 -->
|
||||
<article class="blog-card" data-categories="estrategia branding" data-tags="posicionamiento, competencia, diferenciación" data-featured="false">
|
||||
<div class="card-image">
|
||||
<img src="../assets/blog/posicionamiento.jpg" alt="Posicionamiento">
|
||||
<span class="card-category estrategia">Estrategia</span>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-meta">
|
||||
<time datetime="2023-12-28">28 Dic 2023</time>
|
||||
<span class="reading-time-mini">11 min</span>
|
||||
</div>
|
||||
<h3 class="card-title">Posicionamiento: cómo destacar en un mercado saturado</h3>
|
||||
<p class="card-excerpt">
|
||||
Estrategias prácticas para encontrar tu espacio único y volverte inolvidable.
|
||||
</p>
|
||||
<div class="card-tags">
|
||||
<span class="tag">Posicionamiento</span>
|
||||
<span class="tag">Diferenciación</span>
|
||||
</div>
|
||||
<a href="#" class="card-link">Leer artículo</a>
|
||||
</div>
|
||||
</article>
|
||||
<!-- JS inyecta las tarjetas aquí -->
|
||||
</div>
|
||||
|
||||
<!-- ESTADO VACÍO (cuando no hay resultados) -->
|
||||
<div class="empty-state" id="empty-state" style="display: none;">
|
||||
<div class="empty-icon">🔍</div>
|
||||
<h3>No encontramos artículos con esos filtros</h3>
|
||||
@@ -310,34 +107,16 @@
|
||||
<button class="btn btn-primary" id="empty-reset">Ver todos los artículos</button>
|
||||
</div>
|
||||
|
||||
<!-- PAGINACIÓN / CARGAR MÁS -->
|
||||
<div class="load-more-container">
|
||||
<button class="btn btn-secondary" id="load-more">Cargar más artículos</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SECCIÓN 5: NEWSLETTER -->
|
||||
<section class="newsletter-section">
|
||||
<div class="newsletter-card">
|
||||
<div class="newsletter-content">
|
||||
<h2 class="newsletter-title">Ideas frescas en tu inbox</h2>
|
||||
<p class="newsletter-subtitle">
|
||||
Suscribite y recibí nuestras mejores estrategias de branding, web y marketing digital.
|
||||
Sin spam, solo contenido de valor.
|
||||
</p>
|
||||
</div>
|
||||
<form class="newsletter-form" id="newsletter-form">
|
||||
<button type="submit" class="btn btn-primary">Tu email profesional</button>
|
||||
<button type="submit" class="btn btn-primary">Suscribirme</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div id="footer-container"></div>
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/blog.js"></script>
|
||||
<link rel="stylesheet" href="style/blog.css">
|
||||
<script src="scripts/fluid.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Configuración general del formulario de contacto.
|
||||
* NO subir este archivo a repos públicos.
|
||||
*/
|
||||
|
||||
// ─── SMTP (DonWeb / Ferozo) ────────────────────────────────────────────
|
||||
// Reemplazá los valores por los reales de tu casilla contacto@amoryroma.com.ar
|
||||
define('SMTP_HOST', 'dtc036.ferozo.com'); // o el que te dio DonWeb
|
||||
define('SMTP_PORT', 465); // 587 (TLS) o 465 (SSL)
|
||||
define('SMTP_SECURE', 'ssl'); // 'tls' o 'ssl'
|
||||
define('SMTP_USER', 'contacto@amoryroma.com.ar');
|
||||
define('SMTP_PASS', '1J@oUz7f');
|
||||
define('SMTP_FROM', 'contacto@amoryroma.com.ar');
|
||||
define('SMTP_FROM_NAME', 'Amor & Roma');
|
||||
|
||||
// ─── Destinatarios ─────────────────────────────────────────────────────
|
||||
define('MAIL_TO', 'contacto@amoryroma.com.ar');
|
||||
define('MAIL_TO_NAME', 'Amor & Roma');
|
||||
|
||||
// ─── Redirección post-éxito ────────────────────────────────────────────
|
||||
define('REDIRECT_URL', 'index.html');
|
||||
define('REDIRECT_MS', 4000); // milisegundos antes de redirigir
|
||||
|
||||
// ─── Modo debug ────────────────────────────────────────────────────────
|
||||
// true → muestra errores SMTP en la respuesta JSON (solo para probar)
|
||||
// false → producción (recomendado)
|
||||
define('DEBUG_MODE', false);
|
||||
@@ -4,10 +4,17 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Contactá a Amor y Roma. Contanos sobre tu proyecto y coordinemos un diagnóstico estratégico sin compromiso.">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css">
|
||||
<title>Contacto | Amor y Roma — Agencia Boutique</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/contacto.css">
|
||||
<link rel="stylesheet" href="style/modal.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="fluid-bg" aria-hidden="true">
|
||||
<canvas id="fluidCanvas"></canvas>
|
||||
</div>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
@@ -45,14 +52,14 @@
|
||||
<span class="canal-icono canal-email"></span>
|
||||
<div class="canal-contenido">
|
||||
<strong>Email</strong>
|
||||
<a href="mailto:contacto@amoryroma.com">hola@amoryroma.com</a>
|
||||
<a href="mailto:contacto@amoryroma.com">contacto@amoryroma.com</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="canal-item">
|
||||
<span class="canal-icono canal-whatsapp"></span>
|
||||
<div class="canal-contenido">
|
||||
<strong>WhatsApp</strong>
|
||||
<a href="https://wa.me/543886118304" target="_blank" rel="noopener">+54 9 11 0000-0000</a>
|
||||
<a href="https://wa.me/543886118304" target="_blank" rel="noopener">+54 9 388 6118304</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="canal-item">
|
||||
@@ -69,6 +76,13 @@
|
||||
<a href="https://www.linkedin.com/company/amoryroma-estudiocreativo/" target="_blank" rel="noopener">Amor & Roma - Estudio creativo</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="canal-item">
|
||||
<span class="canal-icono canal-facebook"></span>
|
||||
<div class="canal-contenido">
|
||||
<strong>Facebook</strong>
|
||||
<a href="https://web.facebook.com/amoryroma.creativo/" target="_blank" rel="noopener">Amor & Roma - Estudio creativo</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="contacto-horario">
|
||||
@@ -174,6 +188,11 @@
|
||||
Acepto que mis datos sean utilizados para contactarme respecto a mi consulta. <span class="form-required">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<!-- Honeypot anti-spam: invisible para humanos -->
|
||||
<div class="form-honeypot" aria-hidden="true">
|
||||
<label for="website">No completar este campo</label>
|
||||
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-form-enviar">
|
||||
Enviar consulta
|
||||
@@ -238,19 +257,26 @@
|
||||
<h2 class="cta-title">¿Preferís una conversación directa?</h2>
|
||||
<p class="cta-subtitle">Agendá una llamada de 15 minutos sin compromiso. Ideal si tenés dudas o querés validar si somos el equipo adecuado para tu proyecto.</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="https://calendly.com/amoryroma" target="_blank" rel="noopener" class="btn btn-cta-primary">Agendar llamada</a>
|
||||
<a href="https://wa.me/543886118304" target="_blank" rel="noopener" class="btn btn-cta-primary">Agendar llamada</a>
|
||||
<a href="https://wa.me/543886118304" target="_blank" rel="noopener" class="btn btn-cta-secondary">Escribir por WhatsApp</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- MODAL DE ÉXITO -->
|
||||
<div id="modal-contacto" role="dialog" aria-modal="true" aria-hidden="true" aria-labelledby="modal-titulo">
|
||||
<div class="modal-card">
|
||||
<div class="modal-icono" aria-hidden="true">✓</div>
|
||||
<h2 id="modal-titulo" class="modal-titulo">¡Mensaje enviado!</h2>
|
||||
<p class="modal-mensaje">Gracias por escribirnos. Te contactaremos en menos de 48 horas hábiles.</p>
|
||||
<button type="button" class="modal-cerrar">Volver al inicio</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="footer-container"></div>
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/efecto.js"></script>
|
||||
<script src="scripts/contacto.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="style/contacto.css">
|
||||
<script src="scripts/fluid.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* Endpoint AJAX del formulario de contacto.
|
||||
* Recibe POST y responde JSON.
|
||||
*/
|
||||
|
||||
// ── Silenciar salida directa, solo JSON ────────────────────────────────
|
||||
if (ob_get_length() > 0) { ob_clean(); }
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
// ── Errores a log, no a pantalla ───────────────────────────────────────
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('display_startup_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
require_once __DIR__ . '/config.php';
|
||||
require_once __DIR__ . '/validar.php';
|
||||
|
||||
// ── Respuesta helper ───────────────────────────────────────────────────
|
||||
function responder($status, $message, $code = 200, $extra = []) {
|
||||
http_response_code($code);
|
||||
echo json_encode(array_merge([
|
||||
'status' => $status,
|
||||
'message' => $message,
|
||||
], $extra));
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── Método ─────────────────────────────────────────────────────────────
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
responder('error', 'Método no permitido.', 405);
|
||||
}
|
||||
|
||||
// ── Honeypot ───────────────────────────────────────────────────────────
|
||||
if (!empty($_POST['website'])) {
|
||||
// Fingimos éxito para no darle pistas al bot
|
||||
responder('success', '¡Gracias! Te contactaremos a la brevedad.');
|
||||
}
|
||||
|
||||
// ── Validación ─────────────────────────────────────────────────────────
|
||||
$resultado = validar_contacto($_POST);
|
||||
if (!$resultado['ok']) {
|
||||
responder('error', implode(' ', $resultado['errores']), 400);
|
||||
}
|
||||
$d = $resultado['datos'];
|
||||
|
||||
// ── PHPMailer ──────────────────────────────────────────────────────────
|
||||
require_once __DIR__ . '/lib/PHPMailer.php';
|
||||
require_once __DIR__ . '/lib/SMTP.php';
|
||||
require_once __DIR__ . '/lib/Exception.php';
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
// ── Mapas para mostrar etiquetas legibles ─────────────────────────────
|
||||
$etiquetas = [
|
||||
'servicio' => [
|
||||
'branding' => 'Branding & Identidad',
|
||||
'web' => 'Desarrollo Web a Medida',
|
||||
'rrss' => 'Gestión de Redes Sociales',
|
||||
'automatizaciones'=> 'Automatizaciones & Flujos',
|
||||
'paid' => 'Paid Media & Campañas',
|
||||
'ecosistema' => 'Ecosistema Digital Completo',
|
||||
'otro' => 'Otro / Aún no definido',
|
||||
],
|
||||
'etapa' => [
|
||||
'idea' => 'Solo tengo la idea',
|
||||
'inicio' => 'Estoy empezando',
|
||||
'marcha' => 'En marcha, necesito orden',
|
||||
'redisenio' => 'Rediseñar / reposicionar',
|
||||
'escalar' => 'Escalar lo existente',
|
||||
],
|
||||
'presupuesto' => [
|
||||
'esencial' => 'Hasta $250.000 (Esencial)',
|
||||
'impulso' => '$250.000 – $500.000 (Impulso)',
|
||||
'premium' => '$500.000 – $800.000 (Premium)',
|
||||
'elite' => 'Más de $800.000 (Élite)',
|
||||
'proyecto' => 'Proyecto cerrado (one-off)',
|
||||
'no-se' => 'A evaluar por el equipo',
|
||||
],
|
||||
'origen' => [
|
||||
'instagram' => 'Instagram',
|
||||
'linkedin' => 'LinkedIn',
|
||||
'referido' => 'Referido',
|
||||
'google' => 'Google',
|
||||
'otro' => 'Otro',
|
||||
],
|
||||
];
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
// SMTP
|
||||
$mail->isSMTP();
|
||||
$mail->Host = SMTP_HOST;
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = SMTP_USER;
|
||||
$mail->Password = SMTP_PASS;
|
||||
$mail->SMTPSecure = SMTP_SECURE;
|
||||
$mail->Port = SMTP_PORT;
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->SMTPDebug = 0;
|
||||
|
||||
// De / Para
|
||||
$mail->setFrom(SMTP_FROM, SMTP_FROM_NAME);
|
||||
$mail->addAddress(MAIL_TO, MAIL_TO_NAME);
|
||||
$mail->addReplyTo($d['email'], $d['nombre']);
|
||||
|
||||
// Contenido
|
||||
$mail->Subject = 'Nuevo contacto: ' . $d['nombre'] . ($d['empresa'] ? ' (' . $d['empresa'] . ')' : '');
|
||||
$mail->isHTML(true);
|
||||
|
||||
$servicio_txt = $etiquetas['servicio'][$d['servicio']] ?? '—';
|
||||
$etapa_txt = $etiquetas['etapa'][$d['etapa']] ?? '—';
|
||||
$presupuesto_txt = $etiquetas['presupuesto'][$d['presupuesto']] ?? '—';
|
||||
$origen_txt = $etiquetas['origen'][$d['origen']] ?? '—';
|
||||
|
||||
$rows = [
|
||||
'Nombre' => $d['nombre'],
|
||||
'Empresa / Marca' => $d['empresa'] ?: '—',
|
||||
'Email' => $d['email'],
|
||||
'Teléfono' => $d['telefono'] ?: '—',
|
||||
'Servicio' => $servicio_txt,
|
||||
'Etapa' => $etapa_txt,
|
||||
'Presupuesto' => $presupuesto_txt,
|
||||
'Cómo nos conoció'=> $origen_txt,
|
||||
];
|
||||
|
||||
$html = '<div style="font-family:Arial,sans-serif;font-size:14px;color:#222;max-width:640px">';
|
||||
$html .= '<h2 style="margin:0 0 16px;color:#111">Nueva consulta desde el sitio</h2>';
|
||||
$html .= '<table cellpadding="8" cellspacing="0" style="border-collapse:collapse;width:100%">';
|
||||
foreach ($rows as $label => $valor) {
|
||||
$html .= '<tr>';
|
||||
$html .= '<td style="background:#f5f2ec;border:1px solid #e5e0d5;font-weight:bold;width:180px">' . htmlspecialchars($label) . '</td>';
|
||||
$html .= '<td style="border:1px solid #e5e0d5">' . htmlspecialchars($valor) . '</td>';
|
||||
$html .= '</tr>';
|
||||
}
|
||||
$html .= '</table>';
|
||||
$html .= '<h3 style="margin:24px 0 8px;color:#111">Mensaje</h3>';
|
||||
$html .= '<div style="white-space:pre-wrap;background:#fafafa;border:1px solid #eee;padding:12px;border-radius:6px">'
|
||||
. htmlspecialchars($d['mensaje']) . '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
$mail->Body = $html;
|
||||
$mail->AltBody = "Nueva consulta\n\n"
|
||||
. "Nombre: {$d['nombre']}\n"
|
||||
. "Empresa: {$d['empresa']}\n"
|
||||
. "Email: {$d['email']}\n"
|
||||
. "Teléfono: {$d['telefono']}\n"
|
||||
. "Servicio: $servicio_txt\n"
|
||||
. "Etapa: $etapa_txt\n"
|
||||
. "Presupuesto: $presupuesto_txt\n"
|
||||
. "Origen: $origen_txt\n\n"
|
||||
. "Mensaje:\n{$d['mensaje']}\n";
|
||||
|
||||
$mail->send();
|
||||
|
||||
responder('success', '¡Gracias! Te contactaremos en menos de 48 horas hábiles.', 200, [
|
||||
'redirect' => REDIRECT_URL,
|
||||
'delay' => REDIRECT_MS,
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('[contacto] Falló el envío: ' . $mail->ErrorInfo);
|
||||
$msg = DEBUG_MODE
|
||||
? 'Error SMTP: ' . $mail->ErrorInfo
|
||||
: 'No pudimos enviar tu mensaje. Probá por WhatsApp o intentá más tarde.';
|
||||
responder('error', $msg, 500);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- SECCIÓN 1: Contenido Principal (Columnas, enlaces y CTAs) -->
|
||||
<div class="footer-content">
|
||||
<div class="footer-col" id="footer-brand">
|
||||
<a href="inicio.html" class="logo">
|
||||
<a href="index.html" class="logo">
|
||||
<img src="assets/logos/logo_ciruela.png" alt="Logo" class="logo-light">
|
||||
<img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark">
|
||||
</a>
|
||||
@@ -13,10 +13,10 @@
|
||||
<div class="footer-col" id="footer-links">
|
||||
<h4>Explorar</h4>
|
||||
<ul>
|
||||
<li><a href="inicio.html">Inicio</a></li>
|
||||
<li><a href="index.html">Inicio</a></li>
|
||||
<li><a href="servicios.html">Servicios</a></li>
|
||||
<li><a href="planes.html">Planes</a></li>
|
||||
<li><a href="inicio.html#portfolio">Portfolio</a></li>
|
||||
<li><a href="index.html#portfolio">Portfolio</a></li>
|
||||
<li><a href="blog.html">Blog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -36,7 +36,7 @@
|
||||
<h4></h4>
|
||||
<div class="menu-buttons">
|
||||
<a href="contacto.html" class="btn-menu btn-menu-primary">¿Tenés un proyecto en mente?</a>
|
||||
<a href="inicio.html#diagnostico" class="btn-menu btn-menu-secondary">Empezar diagnóstico</a>
|
||||
<a href="index.html#diagnostico" class="btn-menu btn-menu-secondary">Empezar diagnóstico</a>
|
||||
<div class="menu-social">
|
||||
<a href="https://www.instagram.com/amoryroma.creativo" target="_blank" rel="noopener"><i class="fa-brands fa-instagram"></i> Instagram</a>
|
||||
<a href="https://web.facebook.com/amoryroma.creativo/" target="_blank" rel="noopener"><i class="fa-brands fa-facebook"></i> Facebook</a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<header class="site-header">
|
||||
<nav class="main-nav">
|
||||
<a href="inicio.html" class="logo">
|
||||
<a href="index.html" class="logo">
|
||||
<img src="assets/logos/logo_ciruela.png" alt="Logo" class="logo-light">
|
||||
<img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark">
|
||||
</a>
|
||||
@@ -35,12 +35,12 @@
|
||||
<div class="menu-column">
|
||||
<h3>Amor&Roma</h3>
|
||||
<ul>
|
||||
<li><a href="inicio.html">Comencemos</a></li>
|
||||
<li><a href="inicio.html#servicios">Qué hacemos?</a></li>
|
||||
<li><a href="inicio.html#diagnostico">Diagnóstico</a></li>
|
||||
<li><a href="inicio.html#metodologia">Método A&R</a></li>
|
||||
<li><a href="inicio.html#planes-destacados">Destacados</a></li>
|
||||
<li><a href="inicio.html#portfolio">Desafios</a></li>
|
||||
<li><a href="index.html">Comencemos</a></li>
|
||||
<li><a href="index.html#servicios">Qué hacemos?</a></li>
|
||||
<li><a href="index.html#diagnostico">Diagnóstico</a></li>
|
||||
<li><a href="index.html#metodologia">Método A&R</a></li>
|
||||
<li><a href="index.html#planes-destacados">Destacados</a></li>
|
||||
<li><a href="index.html#portfolio">Desafios</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<div class="menu-column">
|
||||
<h3>Navegación</h3>
|
||||
<ul>
|
||||
<li><a href="inicio.html">Inicio</a></li>
|
||||
<li><a href="index.html">Inicio</a></li>
|
||||
<li><a href="servicios.html">Servicios</a></li>
|
||||
<li><a href="planes.html">Planes</a></li>
|
||||
<!--<li><a href="portfolio.html">Portfolio</a></li>-->
|
||||
@@ -69,7 +69,13 @@
|
||||
|
||||
<p class="contact-item">
|
||||
<span class="contact-icon icon-phone" aria-hidden="true"></span>
|
||||
<span><a href="https://wa.me/543886118304">Whatsapp</a></span>
|
||||
<span>
|
||||
<a href="https://wa.me/543886118304?text=Hola!%20Quiero%20m%C3%A1s%20informaci%C3%B3n."
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
Whatsapp
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="menu-social">
|
||||
@@ -81,12 +87,12 @@
|
||||
|
||||
<div class="menu-buttons">
|
||||
<a href="contacto.html" class="btn-menu btn-menu-primary">Hablemos</a>
|
||||
<a href="trabaja.html" class="btn-menu btn-menu-secondary">Trabaja con nosotros</a>
|
||||
<!--<a href="trabaja.html" class="btn-menu btn-menu-secondary">Trabaja con nosotros</a>-->
|
||||
</div>
|
||||
|
||||
<!-- Logo de marca integrado en el menú -->
|
||||
<div class="menu-brand">
|
||||
<a href="inicio.html" class="logo">
|
||||
<a href="index.html" class="logo">
|
||||
<img src="assets/logos/logo_ciruela.png" alt="Logo" class="logo-light">
|
||||
<img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark">
|
||||
</a>
|
||||
|
||||
@@ -4,22 +4,27 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<title>Inicio - A&R</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="fluid-bg" aria-hidden="true">
|
||||
<canvas id="fluidCanvas"></canvas>
|
||||
</div>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
<!-- Sección Hero -->
|
||||
<section id="hero" class="hero-section">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Marcas con esencia, construidas con estrategia</h1>
|
||||
<p class="hero-subtitle">Diseñamos servicios que se adaptan a tu realidad, para ayudarte a crecer sin perder lo que te hace único</p>
|
||||
<span class="badge-filosofia">Agencia Boutique de Marketing Digital</span>
|
||||
<h1 class="hero-title">En un mundo de ruido, solo lo auténtico resuena</h1>
|
||||
<p class="hero-subtitle">Combinamos el instinto creativo con la ingeniería de procesos para desarrollar tu identidad, sitio web y automatizaciones. <br>Porque lo auténtico, cuando está bien construido, siempre deja eco.</p>
|
||||
<div class="hero-cta-group">
|
||||
<a href="#" class="btn btn-primary hero-cta-primary">Hablemos</a>
|
||||
<a href="inicio.html#servicios" class="btn btn-secondary hero-cta-secondary">Conocé más</a>
|
||||
<a href="contacto.html" class="btn btn-primary hero-cta-primary">Hablemos</a>
|
||||
<a href="index.html#servicios" class="btn btn-secondary hero-cta-secondary">Conocé más</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -531,6 +536,7 @@
|
||||
<div id="footer-container"></div>
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/fluid.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer Exception class.
|
||||
* PHP Version 5.5.
|
||||
*
|
||||
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||
*
|
||||
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
* @author Brent R. Matzelle (original founder)
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2010 - 2012 Jim Jagielski
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
namespace PHPMailer\PHPMailer;
|
||||
|
||||
/**
|
||||
* PHPMailer exception handler.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
/**
|
||||
* Prettify error message output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function errorMessage()
|
||||
{
|
||||
return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n";
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,15 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Conoce la filosofía, metodología y principios de Amor y Roma, agencia boutique de marketing digital. Marcas con esencia, construidas con estrategia.">
|
||||
<title>Nosotros | Amor y Roma — Agencia Boutique</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/nosotros.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="fluid-bg" aria-hidden="true">
|
||||
<canvas id="fluidCanvas"></canvas>
|
||||
</div>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
@@ -38,13 +42,13 @@
|
||||
<div class="card-icon icon-amor"></div>
|
||||
<h3>Amor</h3>
|
||||
<span class="card-tag">La Pasión y el Arte</span>
|
||||
<p>Representa la chispa creativa, la intuición visual, la dirección de arte meticulosa, la empatía con la visión del cliente y la estética no negociable. Es el alma y la identidad de cada marca.</p>
|
||||
<p>Representa el instinto creativo, la intuición visual, la dirección de arte meticulosa, la empatía con la visión del cliente y la estética no negociable. <br>Es el alma y la identidad de cada marca.</p>
|
||||
</article>
|
||||
<article class="dualidad-card card-roma">
|
||||
<div class="card-icon icon-roma"></div>
|
||||
<h3>Roma</h3>
|
||||
<span class="card-tag">La Construcción y la Estructura</span>
|
||||
<p>Representa la arquitectura, la solidez, la ingeniería de procesos, la estrategia a largo plazo y la infraestructura digital orientada a resultados. Es el imperio que sostiene esa visión.</p>
|
||||
<p>Representa la arquitectura, el método, la ingeniería de procesos, la estrategia a largo plazo y la infraestructura digital orientada a resultados. <br>Es el imperio que sostiene esa visión.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
@@ -77,8 +81,7 @@
|
||||
</div>
|
||||
|
||||
<p class="equipo-colaboradores">
|
||||
Como todo equipo en crecimiento, sumamos colaboradores según el proyecto — diseñadores, redactores y especialistas que se suman cuando hace falta.
|
||||
</p>
|
||||
Trabajamos en equipo ayudando a las PyMEs a competir y crecer. </p>
|
||||
</section>
|
||||
|
||||
<!-- SECCIÓN 3: PRINCIPIOS BOUTIQUE -->
|
||||
@@ -125,7 +128,7 @@
|
||||
<p class="transparencia-titulo">INVERSIÓN</p>
|
||||
<p class="transparencia-dato">Desde $250.000/mes</p>
|
||||
<p class="transparencia-texto">
|
||||
Planes desde <strong>$250.000</strong> (Esencial) hasta <strong>$1.000.000</strong> (Élite). El armado inicial —branding, sitio web— se presupuesta por proyecto.
|
||||
Planes desde <strong>$250.000</strong> (Esencia) hasta <strong>$1.000.000</strong> (Élite). El armado inicial —branding, sitio web— se presupuesta por proyecto.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
@@ -172,7 +175,7 @@
|
||||
<!-- ARQUETIPO 1 -->
|
||||
<article class="caso-card">
|
||||
<div class="caso-header">
|
||||
<span class="caso-badge">Arquetipo 1</span>
|
||||
<span class="caso-badge">Mordi - El mundo en un bocado</span>
|
||||
<h3 class="caso-titulo">Identidad Integral</h3>
|
||||
</div>
|
||||
<p class="caso-descripcion">Desarrollo de marca completo, mascota propia y administración continua de redes.</p>
|
||||
@@ -184,7 +187,7 @@
|
||||
<!-- ARQUETIPO 2 -->
|
||||
<article class="caso-card">
|
||||
<div class="caso-header">
|
||||
<span class="caso-badge">Arquetipo 2</span>
|
||||
<span class="caso-badge">ArWorks - higiene y seguridad</span>
|
||||
<h3 class="caso-titulo">Infraestructura B2B</h3>
|
||||
</div>
|
||||
<p class="caso-descripcion">Consultora de Seguridad: Sitio web corporativo a medida y arquitectura sobria.</p>
|
||||
@@ -196,7 +199,7 @@
|
||||
<!-- ARQUETIPO 3 (INSÍGNIA) -->
|
||||
<article class="caso-card caso-insignia">
|
||||
<div class="caso-header">
|
||||
<span class="caso-badge caso-badge-insignia">Arquetipo 3 (Insígnia)</span>
|
||||
<span class="caso-badge caso-badge-insignia">vetta io</span>
|
||||
<h3 class="caso-titulo">Ecosistema Digital Completo</h3>
|
||||
</div>
|
||||
<p class="caso-descripcion">Empresa de Tecnología: Branding + Web a medida + RRSS activas.</p>
|
||||
@@ -208,7 +211,7 @@
|
||||
<!-- ARQUETIPO 4 -->
|
||||
<article class="caso-card">
|
||||
<div class="caso-header">
|
||||
<span class="caso-badge">Arquetipo 4</span>
|
||||
<span class="caso-badge">ide - consultores</span>
|
||||
<h3 class="caso-titulo">Profesionalización de Servicios</h3>
|
||||
</div>
|
||||
<p class="caso-descripcion">Consultores Independientes: Web a medida + Gestión estratégica de RRSS.</p>
|
||||
@@ -226,7 +229,7 @@
|
||||
<p class="cta-subtitle">Agendemos una reunión. Sin plantillas, sin compromisos, solo estrategia a medida.</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="contacto.html" class="btn btn-cta-primary">Hablemos de tu proyecto</a>
|
||||
<a href="inicio.html#portfolio" class="btn btn-cta-secondary">Ver Casos de Éxito</a>
|
||||
<a href="index.html#portfolio" class="btn btn-cta-secondary">Ver Casos de Éxito</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -235,5 +238,6 @@
|
||||
<div id="footer-container"></div>
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/fluid.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -6,12 +6,16 @@
|
||||
<meta name="description" content="Planes de gestión de redes sociales de Amor y Roma. Soluciones escalables desde $250.000/mes.">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css">
|
||||
<title>Planes - Amor y Roma</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/planes.css">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="fluid-bg" aria-hidden="true">
|
||||
<canvas id="fluidCanvas"></canvas>
|
||||
</div>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
@@ -489,10 +493,10 @@
|
||||
<section class="planes-cta">
|
||||
<div class="planes-cta-card">
|
||||
<h2 class="planes-cta-titulo">¿No sabés cuál plan elegir?</h2>
|
||||
<p class="planes-cta-subtitle">Hablamos contigo y te recomendamos el plan ideal según tus objetivos y presupuesto.</p>
|
||||
<p class="planes-cta-subtitle">Contanos sobre tu negocio y te recomendamos el plan ideal según tus objetivos y presupuesto.</p>
|
||||
<div class="planes-cta-buttons">
|
||||
<a href="contacto.html" class="btn btn-cta-primary">Asesoramiento gratuito</a>
|
||||
<a href="inicio.html#diagnostico" class="btn btn-cta-secondary">Hacé el diagnóstico</a>
|
||||
<a href="index.html#diagnostico" class="btn btn-cta-secondary">Hacé el diagnóstico</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -505,5 +509,6 @@
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/planes.js"></script>
|
||||
<script src="scripts/fluid.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,185 +1,252 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('Blog JS cargado');
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const GHOST_API_URL = 'https://blog.amoryroma.com.ar';
|
||||
const GHOST_API_KEY = '82450ba91ca6b5b9628006eec4';
|
||||
|
||||
const searchInput = document.getElementById('blog-search');
|
||||
const searchClear = document.getElementById('search-clear');
|
||||
// Elementos del DOM
|
||||
const featuredSection = document.getElementById('featured-posts');
|
||||
const featuredGrid = document.getElementById('featured-grid');
|
||||
const blogGrid = document.getElementById('blog-grid');
|
||||
const emptyState = document.getElementById('empty-state');
|
||||
const loadMoreBtn = document.getElementById('load-more');
|
||||
const resultsCount = document.getElementById('results-count');
|
||||
const filtersHeader = document.getElementById('blog-filters-header');
|
||||
const emptyState = document.getElementById('empty-state');
|
||||
const gridSectionTitle = document.getElementById('grid-section-title');
|
||||
const gridSectionSubtitle = document.getElementById('grid-section-subtitle');
|
||||
|
||||
if (!searchInput || !blogGrid) {
|
||||
console.error('Faltan elementos del DOM');
|
||||
return;
|
||||
}
|
||||
|
||||
let currentFilters = {
|
||||
search: '',
|
||||
// Estado de los filtros
|
||||
let posts = [];
|
||||
let state = {
|
||||
category: 'all',
|
||||
featured: 'all',
|
||||
filter: 'all', // 'all' o 'destacados'
|
||||
search: '',
|
||||
sort: 'recent'
|
||||
};
|
||||
|
||||
// ===== EFECTO SCROLL EN FILTROS =====
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 100) {
|
||||
filtersHeader.classList.add('is-scrolled');
|
||||
// Cargar artículos desde Ghost API
|
||||
async function loadPosts() {
|
||||
try {
|
||||
const response = await fetch(`${GHOST_API_URL}/ghost/api/content/posts/?key=${GHOST_API_KEY}&limit=all&include=tags,authors`);
|
||||
const data = await response.json();
|
||||
|
||||
posts = data.posts.map(post => ({
|
||||
id: post.id,
|
||||
slug: post.slug,
|
||||
titulo: post.title,
|
||||
extracto: post.excerpt,
|
||||
categoria: post.primary_tag ? post.primary_tag.name.toLowerCase() : 'general',
|
||||
tags: post.tags ? post.tags.map(t => t.name.toLowerCase()) : [],
|
||||
imagen: post.feature_image || 'assets/blog/default.jpg',
|
||||
fecha: post.published_at,
|
||||
tiempo_lectura: Math.ceil(post.reading_time) || 5,
|
||||
destacado: post.featured
|
||||
}));
|
||||
|
||||
renderPosts();
|
||||
setupEventListeners();
|
||||
} catch (error) {
|
||||
console.error('Error cargando posts de Ghost:', error);
|
||||
if(emptyState) {
|
||||
emptyState.style.display = 'block';
|
||||
emptyState.querySelector('h3').textContent = 'Error al cargar el blog';
|
||||
emptyState.querySelector('p').textContent = 'Por favor, recarga la página.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
const options = { day: '2-digit', month: 'short', year: 'numeric' };
|
||||
return new Date(dateString).toLocaleDateString('es-AR', options);
|
||||
}
|
||||
|
||||
function createCard(post, isFeatured = false) {
|
||||
const catFormatted = post.categoria.charAt(0).toUpperCase() + post.categoria.slice(1);
|
||||
const cardClass = isFeatured ? 'featured-card' : 'blog-card';
|
||||
const badge = isFeatured && post.destacado ? '<span class="featured-badge">Destacado</span>' : '';
|
||||
const metaClass = isFeatured ? 'featured-meta' : 'card-meta';
|
||||
const titleClass = isFeatured ? 'featured-title' : 'card-title';
|
||||
const excerptClass = isFeatured ? 'featured-excerpt' : 'card-excerpt';
|
||||
const linkClass = isFeatured ? 'btn-read' : 'card-link';
|
||||
const linkText = isFeatured ? 'Leer artículo →' : 'Leer artículo';
|
||||
|
||||
return `
|
||||
<article class="${cardClass}" data-categories="${post.categoria}" data-featured="${post.destacado}">
|
||||
<div class="${isFeatured ? 'featured-image' : 'card-image'}">
|
||||
<img src="${post.imagen}" alt="${post.titulo}" loading="lazy">
|
||||
${!isFeatured ? `<span class="card-category ${post.categoria}">${catFormatted}</span>` : ''}
|
||||
${badge}
|
||||
</div>
|
||||
<div class="${isFeatured ? 'featured-content' : 'card-content'}">
|
||||
<div class="${metaClass}">
|
||||
<span class="category-tag ${post.categoria}">${catFormatted}</span>
|
||||
<time datetime="${post.fecha}">${formatDate(post.fecha)}</time>
|
||||
</div>
|
||||
<h3 class="${titleClass}">${post.titulo}</h3>
|
||||
<p class="${excerptClass}">${post.extracto}</p>
|
||||
<div class="${isFeatured ? 'featured-footer' : ''}">
|
||||
${isFeatured ? `<span class="reading-time">⏱ ${post.tiempo_lectura} min</span>` : `<span class="reading-time-mini">${post.tiempo_lectura} min</span>`}
|
||||
<a href="${GHOST_API_URL}/${post.slug}/" class="${linkClass}" target="_blank">${linkText}</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderPosts() {
|
||||
// 1. FILTRAR
|
||||
let filtered = posts.filter(post => {
|
||||
const matchCategory = state.category === 'all' || post.categoria === state.category;
|
||||
const matchFilter = state.filter === 'all' || (state.filter === 'destacados' && post.destacado);
|
||||
const q = state.search.toLowerCase();
|
||||
const matchSearch = !q ||
|
||||
post.titulo.toLowerCase().includes(q) ||
|
||||
post.extracto.toLowerCase().includes(q) ||
|
||||
post.tags.some(tag => tag.includes(q));
|
||||
|
||||
return matchCategory && matchFilter && matchSearch;
|
||||
});
|
||||
|
||||
// 2. ORDENAR
|
||||
if (state.sort === 'recent') {
|
||||
filtered.sort((a, b) => new Date(b.fecha) - new Date(a.fecha));
|
||||
} else if (state.sort === 'popular') {
|
||||
// Como la API pública de Ghost no expone "vistas", simulamos popularidad poniendo los destacados primero
|
||||
filtered.sort((a, b) => (b.destacado === a.destacado) ? 0 : b.destacado ? 1 : -1);
|
||||
}
|
||||
|
||||
// 3. DECIDIR VISTA: ¿Es la vista por defecto (sin filtros)?
|
||||
const isDefaultView = state.category === 'all' && state.filter === 'all' && state.search === '';
|
||||
|
||||
if (isDefaultView) {
|
||||
// VISTA POR DEFECTO: Mostrar Destacados + Últimos 3
|
||||
if (featuredSection) featuredSection.style.display = 'block';
|
||||
if (gridSectionTitle) gridSectionTitle.textContent = 'Últimos artículos';
|
||||
if (gridSectionSubtitle) gridSectionSubtitle.textContent = 'Lo más nuevo y a la vanguardia.';
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.style.display = 'inline-block';
|
||||
loadMoreBtn.textContent = 'Ver todos los artículos en el Blog';
|
||||
loadMoreBtn.onclick = () => window.location.href = `${GHOST_API_URL}/`;
|
||||
}
|
||||
|
||||
const featuredPosts = filtered.filter(p => p.destacado).slice(0, 3);
|
||||
const latestPosts = filtered.slice(0, 3);
|
||||
|
||||
if (featuredGrid) featuredGrid.innerHTML = featuredPosts.map(p => createCard(p, true)).join('');
|
||||
if (blogGrid) blogGrid.innerHTML = latestPosts.map(p => createCard(p, false)).join('');
|
||||
|
||||
if (resultsCount) resultsCount.innerHTML = `Mostrando los <strong>últimos 3</strong> artículos`;
|
||||
if (emptyState) emptyState.style.display = 'none';
|
||||
|
||||
} else {
|
||||
filtersHeader.classList.remove('is-scrolled');
|
||||
// VISTA FILTRADA: Ocultar Destacados, mostrar TODOS los resultados en la grilla principal
|
||||
if (featuredSection) featuredSection.style.display = 'none';
|
||||
if (loadMoreBtn) loadMoreBtn.style.display = 'none'; // Ocultamos "cargar más" porque ya mostramos todos los filtrados
|
||||
|
||||
// Actualizar títulos según el filtro
|
||||
if (gridSectionTitle) {
|
||||
if (state.search) gridSectionTitle.textContent = `Resultados de búsqueda`;
|
||||
else if (state.category !== 'all') gridSectionTitle.textContent = `Artículos de ${state.category.charAt(0).toUpperCase() + state.category.slice(1)}`;
|
||||
else if (state.filter === 'destacados') gridSectionTitle.textContent = `Artículos Destacados`;
|
||||
}
|
||||
if (gridSectionSubtitle) gridSectionSubtitle.textContent = `Se encontraron ${filtered.length} artículo${filtered.length !== 1 ? 's' : ''}`;
|
||||
|
||||
if (blogGrid) {
|
||||
if (filtered.length === 0) {
|
||||
blogGrid.innerHTML = '';
|
||||
if (emptyState) {
|
||||
emptyState.style.display = 'block';
|
||||
emptyState.querySelector('h3').textContent = 'No encontramos artículos con esos filtros';
|
||||
}
|
||||
} else {
|
||||
if (emptyState) emptyState.style.display = 'none';
|
||||
// Mostramos TODOS los artículos que coinciden con el filtro, no solo 3
|
||||
blogGrid.innerHTML = filtered.map(p => createCard(p, false)).join('');
|
||||
}
|
||||
}
|
||||
|
||||
if (resultsCount) {
|
||||
resultsCount.innerHTML = `Mostrando <strong>${filtered.length}</strong> artículo${filtered.length !== 1 ? 's' : ''}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
// 1. Botones de Categoría
|
||||
document.querySelectorAll('.category-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
||||
e.target.classList.add('active');
|
||||
state.category = e.target.dataset.category;
|
||||
renderPosts();
|
||||
});
|
||||
});
|
||||
|
||||
// ===== BUSCADOR =====
|
||||
// 2. Botones de Filtro (Todos / Destacados)
|
||||
document.querySelectorAll('.filter-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||||
e.target.classList.add('active');
|
||||
state.filter = e.target.dataset.filter;
|
||||
renderPosts();
|
||||
});
|
||||
});
|
||||
|
||||
// 3. Buscador
|
||||
const searchInput = document.getElementById('blog-search');
|
||||
const searchClear = document.getElementById('search-clear');
|
||||
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const value = e.target.value.trim();
|
||||
currentFilters.search = value;
|
||||
|
||||
if (searchClear) {
|
||||
searchClear.classList.toggle('visible', value.length > 0);
|
||||
}
|
||||
|
||||
filterArticles();
|
||||
state.search = e.target.value;
|
||||
if (searchClear) searchClear.classList.toggle('visible', state.search.length > 0);
|
||||
renderPosts();
|
||||
});
|
||||
}
|
||||
|
||||
if (searchClear) {
|
||||
searchClear.addEventListener('click', () => {
|
||||
if (searchInput) {
|
||||
searchInput.value = '';
|
||||
state.search = '';
|
||||
searchClear.classList.remove('visible');
|
||||
currentFilters.search = '';
|
||||
filterArticles();
|
||||
searchInput.focus();
|
||||
renderPosts();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ===== FILTROS PRINCIPALES =====
|
||||
document.querySelectorAll('.filter-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
currentFilters.featured = btn.dataset.filter;
|
||||
filterArticles();
|
||||
});
|
||||
});
|
||||
|
||||
// ===== CATEGORÍAS =====
|
||||
document.querySelectorAll('.category-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
currentFilters.category = btn.dataset.category;
|
||||
filterArticles();
|
||||
});
|
||||
});
|
||||
|
||||
// ===== ORDENAMIENTO =====
|
||||
// 4. Ordenamiento
|
||||
const sortSelect = document.getElementById('sort-select');
|
||||
if (sortSelect) {
|
||||
sortSelect.addEventListener('change', (e) => {
|
||||
currentFilters.sort = e.target.value;
|
||||
sortArticles();
|
||||
state.sort = e.target.value;
|
||||
renderPosts();
|
||||
});
|
||||
}
|
||||
|
||||
// ===== RESET =====
|
||||
const resetFilters = document.getElementById('reset-filters');
|
||||
if (resetFilters) {
|
||||
resetFilters.addEventListener('click', () => {
|
||||
currentFilters = { search: '', category: 'all', featured: 'all', sort: 'recent' };
|
||||
searchInput.value = '';
|
||||
searchClear?.classList.remove('visible');
|
||||
// 5. Botón Limpiar Filtros
|
||||
const resetBtn = document.getElementById('reset-filters');
|
||||
const emptyReset = document.getElementById('empty-reset');
|
||||
|
||||
function resetAll() {
|
||||
state = { category: 'all', filter: 'all', search: '', sort: 'recent' };
|
||||
|
||||
// Resetear UI
|
||||
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.category-btn[data-category="all"]').classList.add('active');
|
||||
|
||||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.filter-btn[data-filter="all"]')?.classList.add('active');
|
||||
|
||||
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.category-btn[data-category="all"]')?.classList.add('active');
|
||||
document.querySelector('.filter-btn[data-filter="all"]').classList.add('active');
|
||||
|
||||
if (searchInput) searchInput.value = '';
|
||||
if (searchClear) searchClear.classList.remove('visible');
|
||||
if (sortSelect) sortSelect.value = 'recent';
|
||||
|
||||
filterArticles();
|
||||
});
|
||||
}
|
||||
|
||||
// ===== FUNCIÓN DE FILTRADO =====
|
||||
const filterArticles = () => {
|
||||
const articles = document.querySelectorAll('.blog-card, .featured-card');
|
||||
let visibleCount = 0;
|
||||
|
||||
articles.forEach(article => {
|
||||
const categories = article.dataset.categories || '';
|
||||
const tags = article.dataset.tags || '';
|
||||
const isFeatured = article.dataset.featured === 'true';
|
||||
|
||||
const title = article.querySelector('.card-title, .featured-title')?.textContent.toLowerCase() || '';
|
||||
const excerpt = article.querySelector('.card-excerpt, .featured-excerpt')?.textContent.toLowerCase() || '';
|
||||
|
||||
const searchTerm = currentFilters.search.toLowerCase();
|
||||
const matchSearch = searchTerm === '' ||
|
||||
title.includes(searchTerm) ||
|
||||
excerpt.includes(searchTerm) ||
|
||||
categories.toLowerCase().includes(searchTerm) ||
|
||||
tags.toLowerCase().includes(searchTerm);
|
||||
|
||||
const matchCategory = currentFilters.category === 'all' ||
|
||||
categories.toLowerCase().includes(currentFilters.category.toLowerCase());
|
||||
|
||||
let matchFeatured = true;
|
||||
if (currentFilters.featured === 'destacados') {
|
||||
matchFeatured = isFeatured;
|
||||
}
|
||||
|
||||
if (matchSearch && matchCategory && matchFeatured) {
|
||||
article.style.display = '';
|
||||
visibleCount++;
|
||||
} else {
|
||||
article.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
sortArticles();
|
||||
updateResultsCount(visibleCount);
|
||||
|
||||
if (emptyState) {
|
||||
emptyState.style.display = visibleCount === 0 ? 'block' : 'none';
|
||||
}
|
||||
};
|
||||
|
||||
const sortArticles = () => {
|
||||
const articles = Array.from(document.querySelectorAll('.blog-card'));
|
||||
const container = blogGrid;
|
||||
|
||||
switch(currentFilters.sort) {
|
||||
case 'recent':
|
||||
articles.sort((a, b) => {
|
||||
const dateA = new Date(a.querySelector('time')?.datetime || 0);
|
||||
const dateB = new Date(b.querySelector('time')?.datetime || 0);
|
||||
return dateB - dateA;
|
||||
});
|
||||
break;
|
||||
case 'alphabetical':
|
||||
articles.sort((a, b) => {
|
||||
const titleA = a.querySelector('.card-title')?.textContent || '';
|
||||
const titleB = b.querySelector('.card-title')?.textContent || '';
|
||||
return titleA.localeCompare(titleB);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
articles.forEach(article => container.appendChild(article));
|
||||
};
|
||||
|
||||
const updateResultsCount = (count) => {
|
||||
if (!resultsCount) return;
|
||||
|
||||
if (count === 0) {
|
||||
resultsCount.innerHTML = 'No se encontraron artículos';
|
||||
} else if (currentFilters.category === 'all' && currentFilters.search === '') {
|
||||
resultsCount.innerHTML = `Mostrando <strong>${count}</strong> artículos`;
|
||||
} else {
|
||||
resultsCount.innerHTML = `Mostrando <strong>${count}</strong> artículo${count !== 1 ? 's' : ''}`;
|
||||
}
|
||||
};
|
||||
|
||||
// Inicializar
|
||||
filterArticles();
|
||||
renderPosts();
|
||||
}
|
||||
|
||||
if (resetBtn) resetBtn.addEventListener('click', resetAll);
|
||||
if (emptyReset) emptyReset.addEventListener('click', resetAll);
|
||||
}
|
||||
|
||||
// Iniciar
|
||||
await loadPosts();
|
||||
});
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Envío de formulario de contacto con Formspree + modal de éxito.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const form = document.getElementById('form-contacto');
|
||||
const modal = document.getElementById('modal-contacto');
|
||||
const btnCerrar = modal ? modal.querySelector('.modal-cerrar') : null;
|
||||
const btnEnviar = form ? form.querySelector('button[type="submit"]') : null;
|
||||
|
||||
if (!form || !modal) return;
|
||||
|
||||
const FORMSPREE_URL = 'https://formspree.io/f/xkjgjzpn';
|
||||
|
||||
let redirectTimer = null;
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────
|
||||
function abrirModal(mensaje) {
|
||||
const texto = modal.querySelector('.modal-mensaje');
|
||||
if (texto && mensaje) texto.textContent = mensaje;
|
||||
modal.classList.add('is-visible');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function cerrarModal(redirigir = false) {
|
||||
modal.classList.remove('is-visible');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.style.overflow = '';
|
||||
if (redirectTimer) clearTimeout(redirectTimer);
|
||||
if (redirigir) window.location.href = 'index.html';
|
||||
}
|
||||
|
||||
function mostrarError(mensaje) {
|
||||
modal.classList.add('is-error');
|
||||
abrirModal(mensaje);
|
||||
}
|
||||
|
||||
// ── Cerrar modal ───────────────────────────────────────────────────
|
||||
if (btnCerrar) {
|
||||
btnCerrar.addEventListener('click', () => cerrarModal(true));
|
||||
}
|
||||
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) cerrarModal(true);
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-visible')) {
|
||||
cerrarModal(true);
|
||||
}
|
||||
});
|
||||
|
||||
// ── Submit ─────────────────────────────────────────────────────────
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Validación nativa HTML5
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
// Estado de carga
|
||||
const textoOriginal = btnEnviar ? btnEnviar.innerHTML : '';
|
||||
if (btnEnviar) {
|
||||
btnEnviar.disabled = true;
|
||||
btnEnviar.innerHTML = 'Enviando…';
|
||||
}
|
||||
|
||||
try {
|
||||
const data = new FormData(form);
|
||||
|
||||
const res = await fetch(FORMSPREE_URL, {
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
modal.classList.remove('is-error');
|
||||
abrirModal('¡Mensaje enviado! Te contactaremos en menos de 48 horas hábiles.');
|
||||
form.reset();
|
||||
|
||||
// Redirección automática después de 4 segundos
|
||||
redirectTimer = setTimeout(() => {
|
||||
window.location.href = 'index.html';
|
||||
}, 4000);
|
||||
} else {
|
||||
const json = await res.json().catch(() => ({}));
|
||||
mostrarError(json.error || 'No pudimos enviar tu mensaje. Intentá nuevamente.');
|
||||
}
|
||||
} catch (err) {
|
||||
mostrarError('Hubo un problema de conexión. Probá nuevamente.');
|
||||
} finally {
|
||||
if (btnEnviar) {
|
||||
btnEnviar.disabled = false;
|
||||
btnEnviar.innerHTML = textoOriginal;
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
// ===== CONFIGURACIÓN DEL EFECTO =====
|
||||
// ===== CONFIGURACIÓN DEL EFECTO (Parámetros calibrados de fluid - copia.js) =====
|
||||
const config = {
|
||||
TEXTURE_DOWNSAMPLE: 1,
|
||||
DENSITY_DISSIPATION: 0.975,
|
||||
@@ -11,22 +11,62 @@ const config = {
|
||||
SPLAT_RADIUS: 0.003
|
||||
};
|
||||
|
||||
// ===== COLORES DE MARCA SEGÚN EL TEMA =====
|
||||
function getBrandColors() {
|
||||
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||
if (isDark) {
|
||||
return [
|
||||
[0.850, 0.080, 0.380], // Carmesí / Fucsia vivo de marca
|
||||
[0.050, 0.450, 0.550], // Teal profundo
|
||||
[0.650, 0.200, 0.450] // Plum medio
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
[0.729, 0.071, 0.302], // Bordo de marca (#BA124D)
|
||||
[0.000, 0.247, 0.322], // Teal de marca (#003F52)
|
||||
[0.550, 0.150, 0.280] // Plum suave
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
let brandColors = getBrandColors();
|
||||
let currentColor = brandColors[0];
|
||||
let targetColor = brandColors[1];
|
||||
let transitionProgress = 0;
|
||||
const transitionSpeed = 0.008;
|
||||
|
||||
// Observador para detectar cambios en data-theme
|
||||
const themeObserver = new MutationObserver(() => {
|
||||
brandColors = getBrandColors();
|
||||
currentColor = brandColors[0];
|
||||
targetColor = brandColors[1];
|
||||
transitionProgress = 0;
|
||||
});
|
||||
themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
|
||||
|
||||
function lerpColor(colorA, colorB, t) {
|
||||
return [
|
||||
colorA[0] + (colorB[0] - colorA[0]) * t,
|
||||
colorA[1] + (colorB[1] - colorA[1]) * t,
|
||||
colorA[2] + (colorB[2] - colorA[2]) * t
|
||||
];
|
||||
}
|
||||
|
||||
// ===== INICIALIZAR CANVAS =====
|
||||
let canvas = document.getElementById("fluidCanvas");
|
||||
console.log("Canvas encontrado:", canvas);
|
||||
if (!canvas) {
|
||||
console.error("ERROR: No se encontró el canvas con id 'fluidCanvas'");
|
||||
}
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
// ===== CONTEXTO WEBGL =====
|
||||
// ===== CONTEXTO WEBGL TRANSPARENTE =====
|
||||
let pointers = [];
|
||||
let splatStack = [];
|
||||
|
||||
function getWebGLContext(canvas) {
|
||||
let params = {
|
||||
alpha: false,
|
||||
alpha: true, // Transparente para respetar el fondo CSS
|
||||
premultipliedAlpha: false, // Clave para evitar bordes oscuros o quemados
|
||||
depth: false,
|
||||
stencil: false,
|
||||
antialias: false
|
||||
@@ -34,20 +74,22 @@ function getWebGLContext(canvas) {
|
||||
let gl = canvas.getContext("webgl2", params);
|
||||
let isWebGL2 = !!gl;
|
||||
if (!isWebGL2)
|
||||
gl =
|
||||
canvas.getContext("webgl", params) ||
|
||||
canvas.getContext("experimental-webgl", params);
|
||||
gl = canvas.getContext("webgl", params) || canvas.getContext("experimental-webgl", params);
|
||||
|
||||
let halfFloat = gl.getExtension("OES_texture_half_float");
|
||||
let support_linear_float = gl.getExtension("OES_texture_half_float_linear");
|
||||
if (isWebGL2) {
|
||||
gl.getExtension("EXT_color_buffer_float");
|
||||
support_linear_float = gl.getExtension("OES_texture_float_linear");
|
||||
}
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
let internalFormat = isWebGL2 ? gl.RGBA16F : gl.RGBA;
|
||||
let internalFormatRG = isWebGL2 ? gl.RG16F : gl.RGBA;
|
||||
let formatRG = isWebGL2 ? gl.RG : gl.RGBA;
|
||||
let texType = isWebGL2 ? gl.HALF_FLOAT : halfFloat.HALF_FLOAT_OES;
|
||||
|
||||
return {
|
||||
gl: gl,
|
||||
ext: {
|
||||
@@ -74,29 +116,24 @@ function pointerPrototype() {
|
||||
this.dy = 0;
|
||||
this.down = false;
|
||||
this.moved = false;
|
||||
this.color = [30, 0, 300];
|
||||
this.color = [0.729, 0.071, 0.302];
|
||||
}
|
||||
pointers.push(new pointerPrototype());
|
||||
|
||||
// ===== SHADERS =====
|
||||
let GLProgram = (function () {
|
||||
function GLProgram(vertexShader, fragmentShader) {
|
||||
if (!(this instanceof GLProgram))
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
if (!(this instanceof GLProgram)) throw new TypeError("Cannot call a class as a function");
|
||||
this.uniforms = {};
|
||||
this.program = gl.createProgram();
|
||||
gl.attachShader(this.program, vertexShader);
|
||||
gl.attachShader(this.program, fragmentShader);
|
||||
gl.linkProgram(this.program);
|
||||
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
|
||||
throw gl.getProgramInfoLog(this.program);
|
||||
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) throw gl.getProgramInfoLog(this.program);
|
||||
let uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
|
||||
for (let i = 0; i < uniformCount; i++) {
|
||||
let uniformName = gl.getActiveUniform(this.program, i).name;
|
||||
this.uniforms[uniformName] = gl.getUniformLocation(
|
||||
this.program,
|
||||
uniformName
|
||||
);
|
||||
this.uniforms[uniformName] = gl.getUniformLocation(this.program, uniformName);
|
||||
}
|
||||
}
|
||||
GLProgram.prototype.bind = function bind() {
|
||||
@@ -109,26 +146,52 @@ function compileShader(type, source) {
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
|
||||
throw gl.getShaderInfoLog(shader);
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw gl.getShaderInfoLog(shader);
|
||||
return shader;
|
||||
}
|
||||
|
||||
// ===== VERTEX SHADER =====
|
||||
let baseVertexShader = compileShader(
|
||||
gl.VERTEX_SHADER,
|
||||
"precision highp float; precision mediump sampler2D; attribute vec2 aPosition; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform vec2 texelSize; void main () { vUv = aPosition * 0.5 + 0.5; vL = vUv - vec2(texelSize.x, 0.0); vR = vUv + vec2(texelSize.x, 0.0); vT = vUv + vec2(0.0, texelSize.y); vB = vUv - vec2(0.0, texelSize.y); gl_Position = vec4(aPosition, 0.0, 1.0); }"
|
||||
);
|
||||
|
||||
// ===== FRAGMENT SHADERS =====
|
||||
let clearShader = compileShader(
|
||||
gl.FRAGMENT_SHADER,
|
||||
"precision highp float; precision mediump sampler2D; varying vec2 vUv; uniform sampler2D uTexture; uniform float value; void main () { gl_FragColor = value * texture2D(uTexture, vUv); }"
|
||||
);
|
||||
|
||||
// SHADER DE VISUALIZACIÓN: compatible con GLSL ES 1.0 y libre de blanqueo
|
||||
let displayShader = compileShader(
|
||||
gl.FRAGMENT_SHADER,
|
||||
"precision highp float; precision mediump sampler2D; varying vec2 vUv; uniform sampler2D uTexture; void main () { gl_FragColor = texture2D(uTexture, vUv); }"
|
||||
`precision highp float;
|
||||
precision mediump sampler2D;
|
||||
varying vec2 vUv;
|
||||
uniform sampler2D uTexture;
|
||||
uniform float uIsDark;
|
||||
|
||||
void main () {
|
||||
vec4 c = texture2D(uTexture, vUv);
|
||||
float len = length(c.rgb);
|
||||
|
||||
// Sintaxis 100% compatible con WebGL 1 y 2 (4 componentes)
|
||||
if (len < 0.001) {
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalización cromática: conserva el matiz puro de la marca y previene el blanco
|
||||
vec3 pureColor = c.rgb / len;
|
||||
|
||||
if (uIsDark > 0.5) {
|
||||
// MODO OSCURO: color rico con presencia viva sin deslumbrar
|
||||
float alpha = clamp(len * 1.8, 0.0, 0.80);
|
||||
gl_FragColor = vec4(pureColor, alpha);
|
||||
} else {
|
||||
// MODO CLARO: tinte traslúcido tipo acuarela
|
||||
float alpha = clamp(len * 1.2, 0.0, 0.38);
|
||||
gl_FragColor = vec4(pureColor, alpha);
|
||||
}
|
||||
}`
|
||||
);
|
||||
|
||||
let splatShader = compileShader(
|
||||
@@ -182,51 +245,11 @@ function initFramebuffers() {
|
||||
let iFormatRG = ext.internalFormatRG;
|
||||
let formatRG = ext.formatRG;
|
||||
let texType = ext.texType;
|
||||
density = createDoubleFBO(
|
||||
0,
|
||||
textureWidth,
|
||||
textureHeight,
|
||||
iFormat,
|
||||
gl.RGBA,
|
||||
texType,
|
||||
support_linear_float ? gl.LINEAR : gl.NEAREST
|
||||
);
|
||||
velocity = createDoubleFBO(
|
||||
2,
|
||||
textureWidth,
|
||||
textureHeight,
|
||||
iFormatRG,
|
||||
formatRG,
|
||||
texType,
|
||||
support_linear_float ? gl.LINEAR : gl.NEAREST
|
||||
);
|
||||
divergence = createFBO(
|
||||
4,
|
||||
textureWidth,
|
||||
textureHeight,
|
||||
iFormatRG,
|
||||
formatRG,
|
||||
texType,
|
||||
gl.NEAREST
|
||||
);
|
||||
curl = createFBO(
|
||||
5,
|
||||
textureWidth,
|
||||
textureHeight,
|
||||
iFormatRG,
|
||||
formatRG,
|
||||
texType,
|
||||
gl.NEAREST
|
||||
);
|
||||
pressure = createDoubleFBO(
|
||||
6,
|
||||
textureWidth,
|
||||
textureHeight,
|
||||
iFormatRG,
|
||||
formatRG,
|
||||
texType,
|
||||
gl.NEAREST
|
||||
);
|
||||
density = createDoubleFBO(0, textureWidth, textureHeight, iFormat, gl.RGBA, texType, support_linear_float ? gl.LINEAR : gl.NEAREST);
|
||||
velocity = createDoubleFBO(2, textureWidth, textureHeight, iFormatRG, formatRG, texType, support_linear_float ? gl.LINEAR : gl.NEAREST);
|
||||
divergence = createFBO(4, textureWidth, textureHeight, iFormatRG, formatRG, texType, gl.NEAREST);
|
||||
curl = createFBO(5, textureWidth, textureHeight, iFormatRG, formatRG, texType, gl.NEAREST);
|
||||
pressure = createDoubleFBO(6, textureWidth, textureHeight, iFormatRG, formatRG, texType, gl.NEAREST);
|
||||
}
|
||||
|
||||
function createFBO(texId, w, h, internalFormat, format, type, param) {
|
||||
@@ -240,13 +263,7 @@ function createFBO(texId, w, h, internalFormat, format, type, param) {
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, null);
|
||||
let fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.framebufferTexture2D(
|
||||
gl.FRAMEBUFFER,
|
||||
gl.COLOR_ATTACHMENT0,
|
||||
gl.TEXTURE_2D,
|
||||
texture,
|
||||
0
|
||||
);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||
gl.viewport(0, 0, w, h);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
return [texture, fbo, texId];
|
||||
@@ -256,17 +273,9 @@ function createDoubleFBO(texId, w, h, internalFormat, format, type, param) {
|
||||
let fbo1 = createFBO(texId, w, h, internalFormat, format, type, param);
|
||||
let fbo2 = createFBO(texId + 1, w, h, internalFormat, format, type, param);
|
||||
return {
|
||||
get first() {
|
||||
return fbo1;
|
||||
},
|
||||
get second() {
|
||||
return fbo2;
|
||||
},
|
||||
swap: function swap() {
|
||||
let temp = fbo1;
|
||||
fbo1 = fbo2;
|
||||
fbo2 = temp;
|
||||
}
|
||||
get first() { return fbo1; },
|
||||
get second() { return fbo2; },
|
||||
swap: function swap() { let temp = fbo1; fbo1 = fbo2; fbo2 = temp; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -276,33 +285,19 @@ initFramebuffers();
|
||||
let clearProgram = new GLProgram(baseVertexShader, clearShader);
|
||||
let displayProgram = new GLProgram(baseVertexShader, displayShader);
|
||||
let splatProgram = new GLProgram(baseVertexShader, splatShader);
|
||||
let advectionProgram = new GLProgram(
|
||||
baseVertexShader,
|
||||
support_linear_float ? advectionShader : advectionManualFilteringShader
|
||||
);
|
||||
let advectionProgram = new GLProgram(baseVertexShader, support_linear_float ? advectionShader : advectionManualFilteringShader);
|
||||
let divergenceProgram = new GLProgram(baseVertexShader, divergenceShader);
|
||||
let curlProgram = new GLProgram(baseVertexShader, curlShader);
|
||||
let vorticityProgram = new GLProgram(baseVertexShader, vorticityShader);
|
||||
let pressureProgram = new GLProgram(baseVertexShader, pressureShader);
|
||||
let gradienSubtractProgram = new GLProgram(
|
||||
baseVertexShader,
|
||||
gradientSubtractShader
|
||||
);
|
||||
let gradienSubtractProgram = new GLProgram(baseVertexShader, gradientSubtractShader);
|
||||
|
||||
// ===== BLIT =====
|
||||
let blit = (function () {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]),
|
||||
gl.STATIC_DRAW
|
||||
);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]), gl.STATIC_DRAW);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
|
||||
gl.bufferData(
|
||||
gl.ELEMENT_ARRAY_BUFFER,
|
||||
new Uint16Array([0, 1, 2, 0, 2, 3]),
|
||||
gl.STATIC_DRAW
|
||||
);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(0);
|
||||
return function (destination) {
|
||||
@@ -316,53 +311,26 @@ function splat(x, y, dx, dy, color) {
|
||||
splatProgram.bind();
|
||||
gl.uniform1i(splatProgram.uniforms.uTarget, velocity.first[2]);
|
||||
gl.uniform1f(splatProgram.uniforms.aspectRatio, canvas.width / canvas.height);
|
||||
gl.uniform2f(
|
||||
splatProgram.uniforms.point,
|
||||
x / canvas.width,
|
||||
1.0 - y / canvas.height
|
||||
);
|
||||
gl.uniform2f(splatProgram.uniforms.point, x / canvas.width, 1.0 - y / canvas.height);
|
||||
gl.uniform3f(splatProgram.uniforms.color, dx, -dy, 1.0);
|
||||
gl.uniform1f(splatProgram.uniforms.radius, config.SPLAT_RADIUS);
|
||||
blit(velocity.second[1]);
|
||||
velocity.swap();
|
||||
|
||||
gl.uniform1i(splatProgram.uniforms.uTarget, density.first[2]);
|
||||
gl.uniform3f(
|
||||
splatProgram.uniforms.color,
|
||||
color[0] * 0.3,
|
||||
color[1] * 0.3,
|
||||
color[2] * 0.3
|
||||
);
|
||||
// Inyección equilibrada
|
||||
gl.uniform3f(splatProgram.uniforms.color, color[0] * 0.28, color[1] * 0.28, color[2] * 0.28);
|
||||
blit(density.second[1]);
|
||||
density.swap();
|
||||
}
|
||||
|
||||
// ===== RESIZE =====
|
||||
function resizeCanvas() {
|
||||
(canvas.width !== canvas.clientWidth ||
|
||||
canvas.height !== canvas.clientHeight) &&
|
||||
((canvas.width = canvas.clientWidth),
|
||||
(canvas.height = canvas.clientHeight),
|
||||
initFramebuffers());
|
||||
if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) {
|
||||
canvas.width = canvas.clientWidth;
|
||||
canvas.height = canvas.clientHeight;
|
||||
initFramebuffers();
|
||||
}
|
||||
|
||||
// ===== COLORES DE LA MARCA CON TRANSICIÓN =====
|
||||
const brandColors = [
|
||||
//[0.874, 0.741, 0.725], // Rosa (#DFBDB9)
|
||||
[0.729, 0.071, 0.302], // Bordo (#BA124D)
|
||||
[0.000, 0.247, 0.322] // Teal (#003F52)
|
||||
];
|
||||
|
||||
let currentColor = brandColors[0];
|
||||
let targetColor = brandColors[1];
|
||||
let transitionProgress = 0;
|
||||
const transitionSpeed = 0.008;
|
||||
|
||||
function lerpColor(colorA, colorB, t) {
|
||||
return [
|
||||
colorA[0] + (colorB[0] - colorA[0]) * t,
|
||||
colorA[1] + (colorB[1] - colorA[1]) * t,
|
||||
colorA[2] + (colorB[2] - colorA[2]) * t
|
||||
];
|
||||
}
|
||||
|
||||
let colorArr = currentColor;
|
||||
@@ -370,25 +338,31 @@ let count = 0;
|
||||
|
||||
// ===== DETECTAR ELEMENTOS DE TEXTO =====
|
||||
function isMouseOverTextElement(target) {
|
||||
// Listado de selectores que necesitan "modo apaciguado"
|
||||
const textSelectors = [
|
||||
'p', '.hero-content p', 'h1', 'h2', 'h3', 'h4', 'h5', '.hero-content h1',
|
||||
'.hero-content h2', '.eyebrow', 'a.sheet-link', '.sheet-link span',
|
||||
'.menu-btn', '.sheet-link-desc', '.sheet-link-main'
|
||||
'.hero-content h2', '.eyebrow', 'a', 'button', '.btn', '.servicio-item', '.plan-card'
|
||||
];
|
||||
|
||||
// Verificar si el target o sus ancestros coinciden con algún selector
|
||||
for (const selector of textSelectors) {
|
||||
if (target.closest(selector)) {
|
||||
return true;
|
||||
}
|
||||
if (target.closest(selector)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===== EVENTOS CON COLORES DE MARCA =====
|
||||
// ===== CAPTURA DE MOUSE SIMÉTRICA Y CENTRADA =====
|
||||
let isFirstMove = true;
|
||||
|
||||
document.addEventListener("mousemove", function (e) {
|
||||
// Detectar si estamos sobre un elemento de texto
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const currentX = e.clientX - rect.left;
|
||||
const currentY = e.clientY - rect.top;
|
||||
|
||||
if (isFirstMove) {
|
||||
pointers[0].x = currentX;
|
||||
pointers[0].y = currentY;
|
||||
isFirstMove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const overText = isMouseOverTextElement(e.target);
|
||||
|
||||
count++;
|
||||
@@ -407,20 +381,22 @@ document.addEventListener("mousemove", function (e) {
|
||||
|
||||
pointers[0].down = true;
|
||||
pointers[0].color = colorArr;
|
||||
pointers[0].moved = pointers[0].down;
|
||||
pointers[0].moved = true;
|
||||
|
||||
// Aplicar multiplicador diferente según si estamos sobre texto o no
|
||||
const multiplier = overText ? 8 : 10.0; // Reducido a 4x sobre texto (vs 10x)
|
||||
const multiplier = overText ? 8.0 : 10.0;
|
||||
|
||||
pointers[0].dx = (e.clientX - canvas.offsetLeft - pointers[0].x) * multiplier;
|
||||
pointers[0].dy = (e.clientY - canvas.offsetTop - pointers[0].y) * multiplier;
|
||||
pointers[0].x = e.clientX - canvas.offsetLeft;
|
||||
pointers[0].y = e.clientY - canvas.offsetTop;
|
||||
pointers[0].dx = (currentX - pointers[0].x) * multiplier;
|
||||
pointers[0].dy = (currentY - pointers[0].y) * multiplier;
|
||||
pointers[0].x = currentX;
|
||||
pointers[0].y = currentY;
|
||||
});
|
||||
|
||||
canvas.addEventListener(
|
||||
"touchmove",
|
||||
function (e) {
|
||||
window.addEventListener("mouseleave", function () {
|
||||
isFirstMove = true;
|
||||
pointers[0].moved = false;
|
||||
});
|
||||
|
||||
canvas.addEventListener("touchmove", function (e) {
|
||||
e.preventDefault();
|
||||
let touches = e.targetTouches;
|
||||
count++;
|
||||
@@ -437,23 +413,23 @@ canvas.addEventListener(
|
||||
count = 0;
|
||||
}
|
||||
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
for (let i = 0, len = touches.length; i < len; i++) {
|
||||
if (i >= pointers.length) pointers.push(new pointerPrototype());
|
||||
pointers[i].id = touches[i].identifier;
|
||||
pointers[i].down = true;
|
||||
pointers[i].x = touches[i].pageX;
|
||||
pointers[i].y = touches[i].pageY;
|
||||
pointers[i].color = colorArr;
|
||||
let pointer = pointers[i];
|
||||
pointer.moved = pointer.down;
|
||||
pointer.dx = (touches[i].pageX - pointer.x) * 10.0;
|
||||
pointer.dy = (touches[i].pageY - pointer.y) * 10.0;
|
||||
pointer.x = touches[i].pageX;
|
||||
pointer.y = touches[i].pageY;
|
||||
let touchX = touches[i].clientX - rect.left;
|
||||
let touchY = touches[i].clientY - rect.top;
|
||||
|
||||
pointer.id = touches[i].identifier;
|
||||
pointer.down = true;
|
||||
pointer.color = colorArr;
|
||||
pointer.moved = true;
|
||||
pointer.dx = (touchX - pointer.x) * 10.0;
|
||||
pointer.dy = (touchY - pointer.y) * 10.0;
|
||||
pointer.x = touchX;
|
||||
pointer.y = touchY;
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
}, false);
|
||||
|
||||
// ===== LOOP PRINCIPAL =====
|
||||
let lastTime = Date.now();
|
||||
@@ -465,27 +441,17 @@ function update() {
|
||||
gl.viewport(0, 0, textureWidth, textureHeight);
|
||||
|
||||
advectionProgram.bind();
|
||||
gl.uniform2f(
|
||||
advectionProgram.uniforms.texelSize,
|
||||
1.0 / textureWidth,
|
||||
1.0 / textureHeight
|
||||
);
|
||||
gl.uniform2f(advectionProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||
gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.first[2]);
|
||||
gl.uniform1i(advectionProgram.uniforms.uSource, velocity.first[2]);
|
||||
gl.uniform1f(advectionProgram.uniforms.dt, dt);
|
||||
gl.uniform1f(
|
||||
advectionProgram.uniforms.dissipation,
|
||||
config.VELOCITY_DISSIPATION
|
||||
);
|
||||
gl.uniform1f(advectionProgram.uniforms.dissipation, config.VELOCITY_DISSIPATION);
|
||||
blit(velocity.second[1]);
|
||||
velocity.swap();
|
||||
|
||||
gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.first[2]);
|
||||
gl.uniform1i(advectionProgram.uniforms.uSource, density.first[2]);
|
||||
gl.uniform1f(
|
||||
advectionProgram.uniforms.dissipation,
|
||||
config.DENSITY_DISSIPATION
|
||||
);
|
||||
gl.uniform1f(advectionProgram.uniforms.dissipation, config.DENSITY_DISSIPATION);
|
||||
blit(density.second[1]);
|
||||
density.swap();
|
||||
|
||||
@@ -498,20 +464,12 @@ function update() {
|
||||
}
|
||||
|
||||
curlProgram.bind();
|
||||
gl.uniform2f(
|
||||
curlProgram.uniforms.texelSize,
|
||||
1.0 / textureWidth,
|
||||
1.0 / textureHeight
|
||||
);
|
||||
gl.uniform2f(curlProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||
gl.uniform1i(curlProgram.uniforms.uVelocity, velocity.first[2]);
|
||||
blit(curl[1]);
|
||||
|
||||
vorticityProgram.bind();
|
||||
gl.uniform2f(
|
||||
vorticityProgram.uniforms.texelSize,
|
||||
1.0 / textureWidth,
|
||||
1.0 / textureHeight
|
||||
);
|
||||
gl.uniform2f(vorticityProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||
gl.uniform1i(vorticityProgram.uniforms.uVelocity, velocity.first[2]);
|
||||
gl.uniform1i(vorticityProgram.uniforms.uCurl, curl[2]);
|
||||
gl.uniform1f(vorticityProgram.uniforms.curl, config.CURL);
|
||||
@@ -520,11 +478,7 @@ function update() {
|
||||
velocity.swap();
|
||||
|
||||
divergenceProgram.bind();
|
||||
gl.uniform2f(
|
||||
divergenceProgram.uniforms.texelSize,
|
||||
1.0 / textureWidth,
|
||||
1.0 / textureHeight
|
||||
);
|
||||
gl.uniform2f(divergenceProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||
gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.first[2]);
|
||||
blit(divergence[1]);
|
||||
|
||||
@@ -538,11 +492,7 @@ function update() {
|
||||
pressure.swap();
|
||||
|
||||
pressureProgram.bind();
|
||||
gl.uniform2f(
|
||||
pressureProgram.uniforms.texelSize,
|
||||
1.0 / textureWidth,
|
||||
1.0 / textureHeight
|
||||
);
|
||||
gl.uniform2f(pressureProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||
gl.uniform1i(pressureProgram.uniforms.uDivergence, divergence[2]);
|
||||
pressureTexId = pressure.first[2];
|
||||
gl.activeTexture(gl.TEXTURE0 + pressureTexId);
|
||||
@@ -554,11 +504,7 @@ function update() {
|
||||
}
|
||||
|
||||
gradienSubtractProgram.bind();
|
||||
gl.uniform2f(
|
||||
gradienSubtractProgram.uniforms.texelSize,
|
||||
1.0 / textureWidth,
|
||||
1.0 / textureHeight
|
||||
);
|
||||
gl.uniform2f(gradienSubtractProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||
gl.uniform1i(gradienSubtractProgram.uniforms.uPressure, pressure.first[2]);
|
||||
gl.uniform1i(gradienSubtractProgram.uniforms.uVelocity, velocity.first[2]);
|
||||
blit(velocity.second[1]);
|
||||
@@ -567,6 +513,12 @@ function update() {
|
||||
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||
displayProgram.bind();
|
||||
gl.uniform1i(displayProgram.uniforms.uTexture, density.first[2]);
|
||||
|
||||
const isDarkTheme = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||
if (displayProgram.uniforms.uIsDark !== undefined) {
|
||||
gl.uniform1f(displayProgram.uniforms.uIsDark, isDarkTheme ? 1.0 : 0.0);
|
||||
}
|
||||
|
||||
blit(null);
|
||||
|
||||
requestAnimationFrame(update);
|
||||
@@ -574,9 +526,9 @@ function update() {
|
||||
|
||||
update();
|
||||
|
||||
// ===== REDIMENSIONAR AL CAMBIAR TAMAÑO DE VENTANA =====
|
||||
// ===== REDIMENSIONAR =====
|
||||
window.addEventListener("resize", function() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
canvas.width = canvas.clientWidth;
|
||||
canvas.height = canvas.clientHeight;
|
||||
initFramebuffers();
|
||||
});
|
||||
@@ -6,10 +6,14 @@
|
||||
<meta name="description" content="Servicios de Amor y Roma: gestión de redes, branding, desarrollo web, automatizaciones y paid media.">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.0/css/all.min.css">
|
||||
<title>Servicios - Amor y Roma</title>
|
||||
<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
<link rel="stylesheet" href="style/servicios.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="fluid-bg" aria-hidden="true">
|
||||
<canvas id="fluidCanvas"></canvas>
|
||||
</div>
|
||||
<div id="menu-container"></div>
|
||||
|
||||
<main>
|
||||
@@ -18,7 +22,7 @@
|
||||
<div class="servicios-hero-content">
|
||||
<span class="servicios-hero-tag">Nuestros servicios</span>
|
||||
<h1 class="servicios-hero-title">Soluciones a medida para cada etapa de tu marca</h1>
|
||||
<p class="servicios-hero-subtitle">Combinamos estrategia, diseño y tecnología para construir marcas con esencia y estructura.</p>
|
||||
<p class="servicios-hero-subtitle">Diseñamos servicios que se adaptan a tu realidad, para ayudarte a crecer sin perder lo que te hace único.</p>
|
||||
<a href="#servicios-selector" class="btn btn-primary servicios-hero-cta">Explorar servicios</a>
|
||||
</div>
|
||||
</section>
|
||||
@@ -254,7 +258,7 @@
|
||||
<div class="panel-footer">
|
||||
<div class="panel-precio">
|
||||
<span class="precio-label">Desde</span>
|
||||
<span class="precio-valor">$220.000<span class="precio-periodo">/mes</span></span>
|
||||
<span class="precio-valor">$220.000<span class="precio-periodo">/campaña</span></span>
|
||||
</div>
|
||||
<a href="contacto.html?servicio=paid" class="btn btn-secondary panel-cta">Cotizar este servicio</a>
|
||||
</div>
|
||||
@@ -263,8 +267,8 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Sección 4: Separador visual -->
|
||||
<section class="servicios-separador"></section>
|
||||
<!-- Sección 4: Separador visual
|
||||
<section class="servicios-separador"></section>-->
|
||||
|
||||
<!-- Sección 5: Casos de éxito -->
|
||||
<section class="servicios-casos">
|
||||
@@ -304,7 +308,7 @@
|
||||
<h2 class="servicios-cta-titulo">¿No sabés cuál servicio necesitás?</h2>
|
||||
<p class="servicios-cta-subtitle">Hacé nuestro diagnóstico gratuito y te recomendamos la solución ideal para tu momento.</p>
|
||||
<div class="servicios-cta-buttons">
|
||||
<a href="inicio.html#diagnostico" class="btn btn-cta-primary">Hacer el diagnóstico</a>
|
||||
<a href="index.html#diagnostico" class="btn btn-cta-primary">Hacer el diagnóstico</a>
|
||||
<a href="contacto.html" class="btn btn-cta-secondary">Hablemos directamente</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -318,5 +322,6 @@
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/servicios.js"></script>
|
||||
<script src="scripts/fluid.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,7 +3,7 @@
|
||||
============================================ */
|
||||
.blog-hero-compact {
|
||||
padding: calc(var(--spacing-lg) + 2rem) var(--spacing-md) var(--spacing-lg);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
@@ -54,13 +54,12 @@
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
SECCIÓN FILTROS Y BUSCADOR (INTEGRADOS, NO STICKY)
|
||||
SECCIÓN FILTROS Y BUSCADOR
|
||||
============================================ */
|
||||
.blog-filters-section {
|
||||
padding: var(--spacing-md) var(--spacing-md);
|
||||
background-color: var(--bg-surface);
|
||||
border-bottom: 1px solid var(--border);
|
||||
position: relative; /* Sin sticky, fluye normal */
|
||||
background-color: var(--bg-surface-t0);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@@ -69,18 +68,18 @@
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
/* Fila superior: Buscador + Filtros principales */
|
||||
.filters-top-row {
|
||||
display: flex;
|
||||
gap: var(--spacing-sm);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* Buscador con forma redondeada (pill) */
|
||||
.search-wrapper-compact {
|
||||
flex: 1;
|
||||
min-width: 280px;
|
||||
@@ -90,7 +89,7 @@
|
||||
align-items: center;
|
||||
background-color: var(--bg-base);
|
||||
border: 1.5px solid var(--border);
|
||||
border-radius: 999px; /* Forma redondeada como los botones */
|
||||
border-radius: 999px;
|
||||
padding: 0.5rem 0.5rem 0.5rem 1.1rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
@@ -148,7 +147,6 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Filtros principales (Todos / Destacados) */
|
||||
.filter-group-compact {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
@@ -180,10 +178,9 @@
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
/* Fila inferior: Categorías + Ordenamiento */
|
||||
.filters-bottom-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
flex-wrap: wrap;
|
||||
@@ -195,7 +192,7 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.category-btn {
|
||||
@@ -247,11 +244,11 @@
|
||||
border-color: var(--brand-teal);
|
||||
}
|
||||
|
||||
/* Info de resultados */
|
||||
.results-info-compact {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
font-family: var(--font-small);
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
@@ -276,7 +273,7 @@
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
TAGS CON MEJOR CONTRASTE (UNIFICADO)
|
||||
TAGS DE CATEGORÍAS
|
||||
============================================ */
|
||||
.category-tag {
|
||||
font-family: var(--font-small);
|
||||
@@ -290,89 +287,16 @@
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* Branding */
|
||||
.category-tag.branding {
|
||||
background-color: var(--brand-crimson);
|
||||
color: #ffffff;
|
||||
border-color: var(--brand-crimson);
|
||||
}
|
||||
[data-theme="dark"] .category-tag.branding {
|
||||
background-color: rgba(186, 18, 77, 0.95);
|
||||
color: #ffffff;
|
||||
border-color: rgba(186, 18, 77, 1);
|
||||
}
|
||||
.category-tag.branding { background-color: var(--brand-crimson); color: #ffffff; border-color: var(--brand-crimson); }
|
||||
.category-tag.web { background-color: var(--brand-teal); color: #ffffff; border-color: var(--brand-teal); }
|
||||
.category-tag.automatizaciones { background-color: var(--brand-plum); color: #ffffff; border-color: var(--brand-plum); }
|
||||
.category-tag.redes { background-color: #00a88c; color: #ffffff; border-color: #00a88c; }
|
||||
.category-tag.paid { background-color: #6b4c9a; color: #ffffff; border-color: #6b4c9a; }
|
||||
.category-tag.estrategia { background-color: #d97706; color: #ffffff; border-color: #d97706; }
|
||||
.category-tag.casos { background-color: #475569; color: #ffffff; border-color: #475569; }
|
||||
|
||||
/* Web */
|
||||
.category-tag.web {
|
||||
background-color: var(--brand-teal);
|
||||
color: #ffffff;
|
||||
border-color: var(--brand-teal);
|
||||
}
|
||||
[data-theme="dark"] .category-tag.web {
|
||||
background-color: rgba(0, 63, 82, 0.95);
|
||||
color: #ffffff;
|
||||
border-color: rgba(0, 63, 82, 1);
|
||||
}
|
||||
|
||||
/* Automatizaciones */
|
||||
.category-tag.automatizaciones {
|
||||
background-color: var(--brand-plum);
|
||||
color: #ffffff;
|
||||
border-color: var(--brand-plum);
|
||||
}
|
||||
[data-theme="dark"] .category-tag.automatizaciones {
|
||||
background-color: rgba(23, 12, 29, 0.95);
|
||||
color: var(--brand-sage-light);
|
||||
border-color: rgba(23, 12, 29, 1);
|
||||
}
|
||||
|
||||
/* Redes */
|
||||
.category-tag.redes {
|
||||
background-color: #00a88c;
|
||||
color: #ffffff;
|
||||
border-color: #00a88c;
|
||||
}
|
||||
[data-theme="dark"] .category-tag.redes {
|
||||
background-color: rgba(5, 104, 87, 0.95);
|
||||
color: #ffffff;
|
||||
border-color: rgba(0, 168, 140, 1);
|
||||
}
|
||||
|
||||
/* Paid Media */
|
||||
.category-tag.paid {
|
||||
background-color: #6b4c9a;
|
||||
color: #ffffff;
|
||||
border-color: #6b4c9a;
|
||||
}
|
||||
[data-theme="dark"] .category-tag.paid {
|
||||
background-color: rgba(107, 76, 154, 0.95);
|
||||
color: #ffffff;
|
||||
border-color: rgba(107, 76, 154, 1);
|
||||
}
|
||||
|
||||
/* Estrategia */
|
||||
.category-tag.estrategia {
|
||||
background-color: #d97706;
|
||||
color: #ffffff;
|
||||
border-color: #d97706;
|
||||
}
|
||||
[data-theme="dark"] .category-tag.estrategia {
|
||||
background-color: rgba(217, 119, 6, 0.95);
|
||||
color: #ffffff;
|
||||
border-color: rgba(217, 119, 6, 1);
|
||||
}
|
||||
|
||||
/* Casos */
|
||||
.category-tag.casos {
|
||||
background-color: #475569;
|
||||
color: #ffffff;
|
||||
border-color: #475569;
|
||||
}
|
||||
[data-theme="dark"] .category-tag.casos {
|
||||
background-color: rgba(71, 85, 105, 0.95);
|
||||
color: #ffffff;
|
||||
border-color: rgba(71, 85, 105, 1);
|
||||
}
|
||||
[data-theme="dark"] .category-tag.automatizaciones { background-color: rgba(23, 12, 29, 0.95); color: var(--brand-sage-light); border-color: rgba(23, 12, 29, 1); }
|
||||
[data-theme="dark"] .category-tag.redes { background-color: rgba(5, 104, 87, 0.95); color: #ffffff; border-color: rgba(0, 168, 140, 1); }
|
||||
|
||||
.category-tag:hover {
|
||||
transform: translateY(-1px);
|
||||
@@ -380,11 +304,11 @@
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
ARTÍCULOS DESTACADOS (VERSIÓN SIMÉTRICA)
|
||||
ARTÍCULOS DESTACADOS
|
||||
============================================ */
|
||||
.featured-posts {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t3);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -411,7 +335,7 @@
|
||||
.featured-posts .section-title {
|
||||
font-family: var(--font-title);
|
||||
font-style: italic;
|
||||
font-size: clamp(2rem, 4vw, 2.8rem);
|
||||
font-size: clamp(1.2rem, 2vw, 1.8rem);
|
||||
color: var(--text-primary);
|
||||
margin-bottom: var(--spacing-xs);
|
||||
line-height: 1.2;
|
||||
@@ -444,24 +368,16 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 480px;
|
||||
min-height: 250px !important;
|
||||
}
|
||||
|
||||
/* Glow sutil para destacar en hover */
|
||||
.featured-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
border-radius: 20px;
|
||||
padding: 2px;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(186, 18, 77, 0.3) 0%,
|
||||
rgba(0, 63, 82, 0.3) 50%,
|
||||
rgba(186, 18, 77, 0.3) 100%
|
||||
);
|
||||
background: linear-gradient(135deg, rgba(186, 18, 77, 0.3) 0%, rgba(0, 63, 82, 0.3) 50%, rgba(186, 18, 77, 0.3) 100%);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
@@ -475,9 +391,7 @@
|
||||
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.featured-card:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
.featured-card:hover::before { opacity: 1; }
|
||||
|
||||
.featured-badge {
|
||||
position: absolute;
|
||||
@@ -499,7 +413,7 @@
|
||||
.featured-image {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
aspect-ratio: 16/10;
|
||||
aspect-ratio: 16/8;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -510,9 +424,7 @@
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.featured-card:hover .featured-image img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.featured-card:hover .featured-image img { transform: scale(1.05); }
|
||||
|
||||
.featured-content {
|
||||
padding: var(--spacing-md);
|
||||
@@ -532,18 +444,27 @@
|
||||
.featured-title {
|
||||
font-family: var(--font-title);
|
||||
font-style: italic;
|
||||
font-size: 1.3rem;
|
||||
font-size: 1.1rem;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.3;
|
||||
line-height: 1.2;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.featured-excerpt {
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.95rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
line-height: 1.5;
|
||||
flex: 1;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
margin-bottom: 0.3rem !important;
|
||||
}
|
||||
|
||||
.featured-footer {
|
||||
@@ -583,9 +504,45 @@
|
||||
============================================ */
|
||||
.blog-grid-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-surface-t3);
|
||||
}
|
||||
.blog-grid-section .section-header {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto var(--spacing-lg);
|
||||
text-align: left;
|
||||
padding-left: var(--spacing-sm);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.blog-grid-section .section-header::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 60px;
|
||||
background: linear-gradient(180deg, var(--brand-teal) 0%, var(--brand-crimson) 100%);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.blog-grid-section .section-title {
|
||||
font-family: var(--font-title);
|
||||
font-style: italic;
|
||||
font-size: clamp(1.2rem, 2vw, 1.8rem);
|
||||
color: var(--text-primary);
|
||||
margin-bottom: var(--spacing-xs);
|
||||
line-height: 1.2;
|
||||
padding-left: var(--spacing-md);
|
||||
}
|
||||
|
||||
.blog-grid-section .section-subtitle {
|
||||
font-family: var(--font-body);
|
||||
font-size: 1.1rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
padding-left: var(--spacing-md);
|
||||
max-width: 600px;
|
||||
}
|
||||
.blog-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
@@ -623,9 +580,7 @@
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.blog-card:hover .card-image img {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
.blog-card:hover .card-image img { transform: scale(1.08); }
|
||||
|
||||
.card-category {
|
||||
position: absolute;
|
||||
@@ -659,9 +614,7 @@
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.reading-time-mini {
|
||||
font-weight: 600;
|
||||
}
|
||||
.reading-time-mini { font-weight: 600; }
|
||||
|
||||
.card-title {
|
||||
font-family: var(--font-title);
|
||||
@@ -680,23 +633,6 @@
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.card-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.tag {
|
||||
font-family: var(--font-small);
|
||||
font-size: 0.75rem;
|
||||
padding: 0.25rem 0.7rem;
|
||||
background-color: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.card-link {
|
||||
font-family: var(--font-small);
|
||||
font-size: 0.9rem;
|
||||
@@ -723,12 +659,6 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: var(--spacing-sm);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-state h3 {
|
||||
font-family: var(--font-title);
|
||||
font-style: italic;
|
||||
@@ -750,213 +680,40 @@
|
||||
margin-top: var(--spacing-lg);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
NEWSLETTER
|
||||
============================================ */
|
||||
.newsletter-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
}
|
||||
|
||||
.newsletter-card {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background-color: var(--brand-teal);
|
||||
border-radius: 24px;
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
display: grid;
|
||||
grid-template-columns: 1.5fr 1fr;
|
||||
gap: var(--spacing-lg);
|
||||
align-items: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.newsletter-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
right: -100px;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, var(--brand-crimson) 0%, transparent 70%);
|
||||
opacity: 0.3;
|
||||
filter: blur(60px);
|
||||
}
|
||||
|
||||
.newsletter-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.newsletter-title {
|
||||
font-family: var(--font-title);
|
||||
font-style: italic;
|
||||
font-size: clamp(1.8rem, 3vw, 2.5rem);
|
||||
color: #ffffff;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.newsletter-subtitle {
|
||||
font-family: var(--font-body);
|
||||
font-size: 1rem;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.newsletter-form {
|
||||
display: flex;
|
||||
gap: var(--spacing-sm);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.newsletter-form input {
|
||||
flex: 1;
|
||||
padding: 0.85rem 1.2rem;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.95rem;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.newsletter-form input::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.newsletter-form .btn {
|
||||
white-space: nowrap;
|
||||
background-color: var(--brand-crimson);
|
||||
color: var(--text-on-accent);
|
||||
border: 1.5px solid var(--brand-crimson);
|
||||
}
|
||||
|
||||
.newsletter-form .btn:hover {
|
||||
background-color: #ffffff;
|
||||
color: var(--brand-teal);
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
RESPONSIVE BLOG
|
||||
============================================ */
|
||||
@media (max-width: 1024px) {
|
||||
.blog-grid,
|
||||
.featured-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.featured-card {
|
||||
min-height: 420px;
|
||||
}
|
||||
.blog-grid, .featured-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.featured-card { min-height: 420px; }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.blog-hero-compact {
|
||||
padding: var(--spacing-lg) var(--spacing-sm) var(--spacing-md);
|
||||
}
|
||||
|
||||
.blog-filters-section {
|
||||
padding: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.filters-top-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.search-wrapper-compact {
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.filter-group-compact {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.filters-bottom-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.blog-hero-compact { padding: var(--spacing-lg) var(--spacing-sm) var(--spacing-md); }
|
||||
.blog-filters-section { padding: var(--spacing-sm); }
|
||||
.filters-top-row { flex-direction: column; align-items: stretch; }
|
||||
.search-wrapper-compact { max-width: 100%; min-width: 100%; }
|
||||
.filter-group-compact { justify-content: center; }
|
||||
.filters-bottom-row { flex-direction: column; align-items: stretch; }
|
||||
.filter-categories-compact {
|
||||
overflow-x: auto;
|
||||
flex-wrap: nowrap;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.filter-categories-compact::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.category-btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.filter-secondary-compact {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.blog-grid,
|
||||
.featured-grid {
|
||||
grid-template-columns: 1fr;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.featured-card {
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.newsletter-card {
|
||||
grid-template-columns: 1fr;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.newsletter-form {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.newsletter-form .btn {
|
||||
width: 100%;
|
||||
overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none; padding-bottom: 4px;
|
||||
}
|
||||
.filter-categories-compact::-webkit-scrollbar { display: none; }
|
||||
.category-btn { flex-shrink: 0; }
|
||||
.filter-secondary-compact { align-self: flex-end; }
|
||||
.blog-grid, .featured-grid { grid-template-columns: 1fr; max-width: 500px; }
|
||||
.featured-card { min-height: auto; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.blog-hero-compact .hero-compact-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.search-wrapper-compact {
|
||||
padding: 0.4rem 0.4rem 0.4rem 1rem;
|
||||
}
|
||||
|
||||
.search-wrapper-compact input {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
font-size: 0.8rem;
|
||||
padding: 0.4rem 0.8rem;
|
||||
}
|
||||
|
||||
.featured-title,
|
||||
.card-title {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.blog-hero-compact .hero-compact-title { font-size: 2rem; }
|
||||
.search-wrapper-compact { padding: 0.4rem 0.4rem 0.4rem 1rem; }
|
||||
.search-wrapper-compact input { font-size: 0.9rem; }
|
||||
.filter-btn { font-size: 0.8rem; padding: 0.4rem 0.8rem; }
|
||||
.featured-title, .card-title { font-size: 1.2rem; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.blog-card,
|
||||
.featured-card,
|
||||
.filter-btn,
|
||||
.category-btn,
|
||||
.search-wrapper-compact,
|
||||
.category-tag {
|
||||
transition: none;
|
||||
}
|
||||
.blog-card, .featured-card, .filter-btn, .category-btn, .search-wrapper-compact, .category-tag { transition: none; }
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
============================================ */
|
||||
.contacto-grid-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-surface-t2);
|
||||
}
|
||||
|
||||
.contacto-grid {
|
||||
@@ -95,8 +95,7 @@
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--brand-crimson);
|
||||
border-radius: 10px;
|
||||
border-radius: 1px;
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
@@ -108,22 +107,27 @@
|
||||
.canal-email {
|
||||
-webkit-mask-image: url("../assets/iconos/buzon.svg");
|
||||
mask-image: url("../assets/iconos/buzon.svg");
|
||||
background-color: var(--brand-teal);
|
||||
background-color: var(--brand-teal-contraste);
|
||||
}
|
||||
.canal-whatsapp {
|
||||
-webkit-mask-image: url("../assets/vectores/whatsapp.svg");
|
||||
mask-image: url("../assets/vectores/whatsapp.svg");
|
||||
background-color: #25D366;
|
||||
-webkit-mask-image: url("../assets/logos/whatsapp.svg");
|
||||
mask-image: url("../assets/logos/whatsapp.svg");
|
||||
background-color: var(--brand-teal-contraste);
|
||||
}
|
||||
.canal-instagram {
|
||||
-webkit-mask-image: url("../assets/vectores/insta.svg");
|
||||
mask-image: url("../assets/vectores/insta.svg");
|
||||
background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888);
|
||||
-webkit-mask-image: url("../assets/logos/instagram.svg");
|
||||
mask-image: url("../assets/logos/instagram.svg");
|
||||
background-color: var(--brand-teal-contraste);
|
||||
}
|
||||
.canal-linkedin {
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.063 2.063 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.063 2.063 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E");
|
||||
background-color: #0A66C2;
|
||||
-webkit-mask-image: url("../assets/logos/linkedin.svg");
|
||||
mask-image: url("../assets/logos/linkedin.svg");
|
||||
background-color: var(--brand-teal-contraste);
|
||||
}
|
||||
.canal-facebook {
|
||||
-webkit-mask-image: url("../assets/logos/facebook.svg");
|
||||
mask-image: url("../assets/logos/facebook.svg");
|
||||
background-color: var(--brand-teal-contraste);
|
||||
}
|
||||
|
||||
.canal-contenido {
|
||||
@@ -311,7 +315,7 @@
|
||||
============================================ */
|
||||
.proceso-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t3);
|
||||
}
|
||||
|
||||
.proceso-grid {
|
||||
@@ -388,7 +392,7 @@
|
||||
============================================ */
|
||||
.notas-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-surface-t1);
|
||||
}
|
||||
|
||||
.notas-container {
|
||||
@@ -420,6 +424,13 @@
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.form-honeypot {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
RESPONSIVE CONTACTO
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
--bg-surface-elevated: #f5f9f8;
|
||||
--bg-icon-contrast: var(--brand-teal);
|
||||
|
||||
--bg-base-t0:rgba(234,240,238, 0.98);
|
||||
--bg-base-t1:rgba(234,240,238, 0.95);
|
||||
--bg-base-t2:rgba(234,240,238, 0.7);
|
||||
--bg-base-t3:rgba(234,240,238, 0.5);
|
||||
--bg-surface-t0:rgb(255, 255, 255, 0.98);
|
||||
--bg-surface-t1:rgb(255, 255, 255, 0.95);
|
||||
--bg-surface-t2: rgb(255, 255, 255, 0.7);
|
||||
|
||||
--text-primary: var(--brand-plum);
|
||||
--text-secondary: var(--brand-teal);
|
||||
--text-muted: rgba(34, 23, 40, 0.65);
|
||||
@@ -77,6 +85,14 @@
|
||||
--brand-teal-contraste: #116c88;
|
||||
--brand-crimson-contraste: #d81a5c;
|
||||
|
||||
--bg-base-t0:rgba(17,9,22, 0.98);
|
||||
--bg-base-t1:rgba(17,9,22, 0.95);
|
||||
--bg-base-t2:rgba(17,9,22, 0.7);
|
||||
--bg-base-t3:rgba(17,9,22, 0.5);
|
||||
--bg-surface-t0:rgb(23,12,29, 0.98);
|
||||
--bg-surface-t1:rgb(23,12,29, 0.95);
|
||||
--bg-surface-t2: rgb(23,12,29, 0.7);
|
||||
|
||||
--text-primary: var(--brand-sage-light);
|
||||
--text-secondary: var(--brand-rose-muted);
|
||||
--text-muted: rgba(234, 240, 238, 0.65);
|
||||
@@ -108,11 +124,13 @@
|
||||
html {
|
||||
font-size: var(--font-size-base);
|
||||
scroll-behavior: smooth;
|
||||
background-color: var(--bg-base);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-family-base);
|
||||
background-color: var(--bg-base);
|
||||
/*background-color: var(--bg-base);*/
|
||||
background-color: transparent;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.5;
|
||||
min-height: 100vh;
|
||||
@@ -156,6 +174,20 @@ ul { list-style: none; }
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.badge-filosofia {
|
||||
display: inline-block;
|
||||
padding: 0.4rem 1rem;
|
||||
border-radius: 999px;
|
||||
color: var(--badge-text);
|
||||
font-family: var(--font-small);
|
||||
font-weight: 400;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
opacity: 0;
|
||||
animation: fadeInUp 0.9s ease-out 0s forwards;
|
||||
}
|
||||
|
||||
.site-header {
|
||||
background-color: var(--bg-surface);
|
||||
border-bottom: 1px solid var(--border);
|
||||
@@ -500,7 +532,8 @@ body.menu-open .site-header {
|
||||
============================================ */
|
||||
main section {
|
||||
padding: var(--spacing-md) var(--spacing-sm);
|
||||
border-bottom: 1px dashed var(--border);
|
||||
background-color: transparent;
|
||||
/*border-bottom: 1px dashed var(--border);*/
|
||||
}
|
||||
main section h2 { margin-bottom: var(--spacing-sm); font-size: 1.5rem; }
|
||||
|
||||
@@ -508,7 +541,7 @@ main section h2 { margin-bottom: var(--spacing-sm); font-size: 1.5rem; }
|
||||
border-top: 1px solid var(--border);
|
||||
padding-top: var(--spacing-lg);
|
||||
margin-top: auto;
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-surface-t0);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -565,7 +598,7 @@ main section h2 { margin-bottom: var(--spacing-sm); font-size: 1.5rem; }
|
||||
============================================ */
|
||||
.hero-section {
|
||||
min-height: calc(100vh - var(--header-height));
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t3);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
text-align: center;
|
||||
@@ -665,7 +698,7 @@ main section h2 { margin-bottom: var(--spacing-sm); font-size: 1.5rem; }
|
||||
============================================ */
|
||||
.servicios-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t3);
|
||||
}
|
||||
|
||||
.servicios-container {
|
||||
@@ -789,7 +822,7 @@ SECCIÓN DIAGNÓSTICO
|
||||
============================================ */
|
||||
.diagnostico-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.diagnostico-header {
|
||||
@@ -1364,7 +1397,7 @@ RESPONSIVE DIAGNÓSTICO
|
||||
SECCIÓN METODOLOGÍA
|
||||
============================================ */
|
||||
.metodologia-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md); background-color: var(--bg-base);
|
||||
padding: var(--spacing-lg) var(--spacing-md); background-color: var(--bg-base-t2);
|
||||
}
|
||||
|
||||
.metodologia-header {
|
||||
@@ -1474,7 +1507,7 @@ RESPONSIVE DIAGNÓSTICO
|
||||
SECCIÓN PLANES DESTACADOS
|
||||
============================================ */
|
||||
.planes-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md); background-color: var(--bg-base);
|
||||
padding: var(--spacing-lg) var(--spacing-md); background-color: transparent;
|
||||
}
|
||||
|
||||
.planes-header { text-align: center; max-width: 700px; margin: 0 auto var(--spacing-lg); }
|
||||
@@ -1550,7 +1583,7 @@ RESPONSIVE DIAGNÓSTICO
|
||||
/* ============================================
|
||||
SECCIÓN PORTFOLIO
|
||||
============================================ */
|
||||
.portfolio-section { padding: var(--spacing-lg) var(--spacing-md); background-color: var(--bg-base); }
|
||||
.portfolio-section { padding: var(--spacing-lg) var(--spacing-md); background-color: var(--bg-base-t2); }
|
||||
.portfolio-container {
|
||||
display: grid; grid-template-columns: 1fr 1.2fr; gap: var(--spacing-lg);
|
||||
max-width: 1400px; margin: 0 auto; align-items: center;
|
||||
@@ -1667,56 +1700,242 @@ RESPONSIVE DIAGNÓSTICO
|
||||
/* ============================================
|
||||
SECCIÓN CTA FINAL
|
||||
============================================ */
|
||||
.cta-section { padding: var(--spacing-lg) var(--spacing-md); background-color: var(--bg-base); }
|
||||
.cta-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.cta-card {
|
||||
max-width: 900px; margin: 0 auto; background-color: var(--brand-teal);
|
||||
border-radius: 24px; padding: var(--spacing-lg) var(--spacing-md);
|
||||
text-align: center; position: relative; overflow: hidden;
|
||||
box-shadow: 0 20px 60px -10px rgba(0, 63, 82, 0.4);
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
/* Fondo teal sólido y oscuro para máximo contraste */
|
||||
background-color: var(--brand-teal);
|
||||
border-radius: 24px;
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* Sombra más pronunciada */
|
||||
box-shadow: 0 20px 60px -10px rgba(0, 63, 82, 0.5);
|
||||
/* Borde sutil para definir mejor */
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.cta-card::before, .cta-card::after {
|
||||
content: ""; position: absolute; width: 300px; height: 300px;
|
||||
border-radius: 50%; filter: blur(80px); opacity: 0.35; pointer-events: none;
|
||||
/* Glows decorativos con degradé crimson-teal */
|
||||
.cta-card::before,
|
||||
.cta-card::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
border-radius: 50%;
|
||||
filter: blur(100px);
|
||||
opacity: 0.4;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Glow superior izquierdo - Crimson/Rosa */
|
||||
.cta-card::before {
|
||||
top: -150px;
|
||||
left: -150px;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(186, 18, 77, 0.6) 0%,
|
||||
rgba(186, 18, 77, 0.3) 40%,
|
||||
transparent 70%
|
||||
);
|
||||
animation: glowPulse 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Glow inferior derecho - Teal/Rose */
|
||||
.cta-card::after {
|
||||
bottom: -150px;
|
||||
right: -150px;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(0, 168, 140, 0.5) 0%,
|
||||
rgba(223, 189, 185, 0.3) 40%,
|
||||
transparent 70%
|
||||
);
|
||||
animation: glowPulse 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
/* Animación sutil de los glows */
|
||||
@keyframes glowPulse {
|
||||
0%, 100% {
|
||||
transform: scale(1) translate(0, 0);
|
||||
opacity: 0.4;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1) translate(20px, -20px);
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.cta-card::before { top: -100px; left: -100px; background: radial-gradient(circle, var(--brand-crimson) 0%, transparent 70%); }
|
||||
.cta-card::after { bottom: -100px; right: -100px; background: radial-gradient(circle, var(--brand-rose-muted) 0%, transparent 70%); }
|
||||
|
||||
.cta-title {
|
||||
font-family: var(--font-title); font-style: italic;
|
||||
font-size: clamp(2rem, 4vw, 3rem); color: #ffffff;
|
||||
margin-bottom: var(--spacing-sm); line-height: 1.15; position: relative; z-index: 1;
|
||||
font-family: var(--font-title);
|
||||
font-style: italic;
|
||||
font-size: clamp(2rem, 4vw, 3rem);
|
||||
color: #ffffff;
|
||||
margin-bottom: var(--spacing-sm);
|
||||
line-height: 1.15;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
/* Sombra de texto para mejorar legibilidad */
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.cta-subtitle {
|
||||
font-family: var(--font-body); font-size: clamp(1rem, 2vw, 1.15rem);
|
||||
color: rgba(255, 255, 255, 0.85); max-width: 600px; margin: 0 auto var(--spacing-md);
|
||||
line-height: 1.6; position: relative; z-index: 1;
|
||||
font-family: var(--font-body);
|
||||
font-size: clamp(1rem, 2vw, 1.15rem);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
max-width: 600px;
|
||||
margin: 0 auto var(--spacing-md);
|
||||
line-height: 1.6;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
display: flex; justify-content: center; gap: var(--spacing-sm);
|
||||
flex-wrap: wrap; position: relative; z-index: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-sm);
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Botón primario - Blanco con hover crimson */
|
||||
.btn-cta-primary {
|
||||
background-color: #ffffff; color: var(--brand-teal); border: 1.5px solid #ffffff;
|
||||
padding: 0.85rem 2rem; border-radius: 999px; font-family: var(--font-small);
|
||||
font-size: 0.95rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 14px -3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.btn-cta-primary:hover {
|
||||
background-color: var(--brand-crimson); color: #ffffff; border-color: var(--brand-crimson);
|
||||
transform: translateY(-2px); box-shadow: 0 6px 20px -3px rgba(186, 18, 77, 0.45);
|
||||
background-color: #ffffff;
|
||||
color: var(--brand-teal);
|
||||
border: 2px solid #ffffff;
|
||||
padding: 0.85rem 2.2rem;
|
||||
border-radius: 999px;
|
||||
font-family: var(--font-small);
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
box-shadow: 0 4px 14px -3px rgba(0, 0, 0, 0.25);
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-cta-secondary {
|
||||
background-color: transparent; color: #ffffff; border: 1.5px solid rgba(255, 255, 255, 0.6);
|
||||
padding: 0.85rem 2rem; border-radius: 999px; font-family: var(--font-small);
|
||||
font-size: 0.95rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease;
|
||||
.btn-cta-primary:hover {
|
||||
background-color: var(--brand-crimson);
|
||||
color: #ffffff;
|
||||
border-color: var(--brand-crimson);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px -4px rgba(186, 18, 77, 0.5);
|
||||
}
|
||||
|
||||
/* Botón secundario - Transparente con borde blanco */
|
||||
.btn-cta-secondary {
|
||||
background-color: transparent;
|
||||
color: #ffffff;
|
||||
border: 2px solid rgba(255, 255, 255, 0.8);
|
||||
padding: 0.85rem 2.2rem;
|
||||
border-radius: 999px;
|
||||
font-family: var(--font-small);
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-cta-secondary:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1); border-color: #ffffff; transform: translateY(-2px);
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
border-color: #ffffff;
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px -4px rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/* ===== CANVAS FLUIDO Y APILAMIENTO ===== */
|
||||
main {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#footer-container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#fluid-bg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#fluidCanvas {
|
||||
display: block;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: transparent;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.cta-section {
|
||||
padding: var(--spacing-md) var(--spacing-sm);
|
||||
}
|
||||
|
||||
.cta-card {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.cta-card::before,
|
||||
.cta-card::after {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
filter: blur(60px);
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-cta-primary,
|
||||
.btn-cta-secondary {
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.cta-card {
|
||||
padding: var(--spacing-md) var(--spacing-sm);
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.cta-subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.cta-card::before,
|
||||
.cta-card::after {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.btn-cta-primary,
|
||||
.btn-cta-secondary {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/* ── Modal de contacto ──────────────────────────────────────────────── */
|
||||
#modal-contacto {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(20, 18, 15, 0.55);
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity .35s ease, visibility .35s ease;
|
||||
z-index: 9999;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
#modal-contacto.is-visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#modal-contacto .modal-card {
|
||||
background: #fff;
|
||||
color: #1c1a17;
|
||||
border-radius: 14px;
|
||||
padding: 2.5rem 2rem;
|
||||
max-width: 460px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-shadow: 0 24px 60px rgba(0, 0, 0, .25);
|
||||
transform: translateY(20px) scale(.97);
|
||||
transition: transform .35s cubic-bezier(.2, .8, .2, 1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#modal-contacto.is-visible .modal-card {
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
|
||||
#modal-contacto .modal-icono {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
background: #f1ece1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 1.25rem;
|
||||
font-size: 1.75rem;
|
||||
color: #8b7355;
|
||||
}
|
||||
|
||||
#modal-contacto .modal-titulo {
|
||||
font-size: 1.4rem;
|
||||
margin: 0 0 .75rem;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
#modal-contacto .modal-mensaje {
|
||||
font-size: .98rem;
|
||||
line-height: 1.55;
|
||||
color: #4a453d;
|
||||
margin: 0 0 1.75rem;
|
||||
}
|
||||
|
||||
#modal-contacto .modal-cerrar {
|
||||
display: inline-block;
|
||||
background: #1c1a17;
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: .85rem 1.75rem;
|
||||
border-radius: 999px;
|
||||
font-size: .95rem;
|
||||
cursor: pointer;
|
||||
transition: background .25s ease, transform .25s ease;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
#modal-contacto .modal-cerrar:hover {
|
||||
background: #8b7355;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Variante error */
|
||||
#modal-contacto.is-error .modal-icono {
|
||||
background: #fdecec;
|
||||
color: #c0392b;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
#modal-contacto .modal-card { padding: 2rem 1.25rem; }
|
||||
#modal-contacto .modal-titulo { font-size: 1.2rem; }
|
||||
}
|
||||
@@ -18,24 +18,7 @@
|
||||
[data-theme="dark"] .logo-light { display: none; }
|
||||
[data-theme="dark"] .logo-dark { display: block; }
|
||||
|
||||
/* (Se omiten estilos intermedios del menú por brevedad, asumo que ya los tienes en tu archivo original.
|
||||
Si necesitas el bloque completo del menú, avísame, pero se mantiene intacto tu CSS original aquí). */
|
||||
|
||||
.site-footer {
|
||||
border-top: 1px solid var(--border);
|
||||
padding-top: var(--spacing-lg);
|
||||
margin-top: auto;
|
||||
background-color: var(--bg-surface);
|
||||
}
|
||||
.footer-bottom {
|
||||
border-top: 1px solid var(--border);
|
||||
padding: var(--spacing-sm);
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-muted);
|
||||
background-color: var(--bg-surface);
|
||||
font-family: 'Jost', sans-serif;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
COMPONENTES REUTILIZABLES
|
||||
@@ -69,7 +52,7 @@
|
||||
============================================ */
|
||||
.hero-section {
|
||||
min-height: calc(100vh - var(--header-height));
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
text-align: center;
|
||||
@@ -133,7 +116,7 @@
|
||||
/* --- DUALIDAD --- */
|
||||
.dualidad-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-surface-t2);
|
||||
}
|
||||
.dualidad-grid {
|
||||
display: grid; grid-template-columns: 1fr 1fr; gap: var(--spacing-md);
|
||||
@@ -191,7 +174,7 @@
|
||||
/* --- PRINCIPIOS --- */
|
||||
.principios-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t2);
|
||||
}
|
||||
.principios-grid {
|
||||
display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--spacing-md);
|
||||
@@ -228,7 +211,7 @@
|
||||
============================================ */
|
||||
.casos-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t3);
|
||||
}
|
||||
|
||||
.casos-grid-simetrico {
|
||||
@@ -341,7 +324,7 @@
|
||||
.caso-descripcion {
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.95rem;
|
||||
color: var(--brand-sage-light);
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
flex: 1;
|
||||
}
|
||||
@@ -452,7 +435,7 @@
|
||||
============================================ */
|
||||
.transparencia-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t2);
|
||||
}
|
||||
|
||||
.transparencia-grid {
|
||||
@@ -580,7 +563,7 @@
|
||||
============================================ */
|
||||
.equipo-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Título con gradiente en la palabra destacada */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
============================================ */
|
||||
.planes-hero {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t2);
|
||||
min-height: 70vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -71,7 +71,7 @@
|
||||
============================================ */
|
||||
.planes-selector-section {
|
||||
padding: var(--spacing-sm) var(--spacing-xs);
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-surface-t1);
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
@@ -174,7 +174,7 @@
|
||||
============================================ */
|
||||
.planes-panel-section {
|
||||
padding: var(--spacing-md) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
@@ -419,7 +419,7 @@
|
||||
============================================ */
|
||||
.planes-comparativa-section {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.comparativa-container {
|
||||
@@ -517,7 +517,7 @@
|
||||
============================================ */
|
||||
.planes-cta {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.planes-cta-card {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
============================================ */
|
||||
.servicios-hero {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
min-height: 70vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -71,14 +71,12 @@
|
||||
============================================ */
|
||||
.servicios-selector-section {
|
||||
padding: var(--spacing-md) var(--spacing-sm);
|
||||
background-color: var(--bg-surface);
|
||||
background-color: var(--bg-base-t1);
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .servicios-selector-section {
|
||||
background-color: rgba(45, 32, 52, 0.95);
|
||||
}
|
||||
|
||||
|
||||
.servicios-selector-container {
|
||||
max-width: 1200px;
|
||||
@@ -195,7 +193,7 @@
|
||||
============================================ */
|
||||
.servicios-panel-section {
|
||||
padding: var(--spacing-md) var(--spacing-xs);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
@@ -462,7 +460,7 @@
|
||||
============================================ */
|
||||
.servicios-casos {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: var(--bg-base-t2);
|
||||
}
|
||||
|
||||
.servicios-casos-container {
|
||||
@@ -510,11 +508,11 @@
|
||||
|
||||
.caso-tag {
|
||||
font-family: var(--font-small);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
color: var(--brand-teal);
|
||||
color: #006d8f;
|
||||
display: inline-block;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
@@ -537,7 +535,7 @@
|
||||
============================================ */
|
||||
.servicios-cta {
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
background-color: var(--bg-base);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.servicios-cta-card {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Funciones de sanitización y validación reutilizables.
|
||||
*/
|
||||
|
||||
function limpiar_texto($valor, $max = 500) {
|
||||
$valor = trim((string)$valor);
|
||||
$valor = strip_tags($valor);
|
||||
$valor = preg_replace('/[\r\n\t]+/', ' ', $valor);
|
||||
if (mb_strlen($valor) > $max) {
|
||||
$valor = mb_substr($valor, 0, $max);
|
||||
}
|
||||
return $valor;
|
||||
}
|
||||
|
||||
function limpiar_mensaje($valor, $max = 5000) {
|
||||
$valor = trim((string)$valor);
|
||||
$valor = strip_tags($valor);
|
||||
if (mb_strlen($valor) > $max) {
|
||||
$valor = mb_substr($valor, 0, $max);
|
||||
}
|
||||
return $valor;
|
||||
}
|
||||
|
||||
function limpiar_email($valor) {
|
||||
return filter_var(trim((string)$valor), FILTER_SANITIZE_EMAIL);
|
||||
}
|
||||
|
||||
function email_valido($valor) {
|
||||
return (bool) filter_var($valor, FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
|
||||
function en_lista($valor, array $permitidos) {
|
||||
return in_array($valor, $permitidos, true) ? $valor : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Valida los datos del formulario y devuelve
|
||||
* ['ok' => bool, 'errores' => [], 'datos' => []]
|
||||
*/
|
||||
function validar_contacto(array $post) {
|
||||
$errores = [];
|
||||
|
||||
$datos = [
|
||||
'nombre' => limpiar_texto($post['nombre'] ?? '', 120),
|
||||
'empresa' => limpiar_texto($post['empresa'] ?? '', 120),
|
||||
'email' => limpiar_email($post['email'] ?? ''),
|
||||
'telefono' => limpiar_texto($post['telefono'] ?? '', 40),
|
||||
'servicio' => en_lista($post['servicio'] ?? '', [
|
||||
'branding','web','rrss','automatizaciones','paid','ecosistema','otro'
|
||||
]),
|
||||
'etapa' => en_lista($post['etapa'] ?? '', [
|
||||
'idea','inicio','marcha','redisenio','escalar'
|
||||
]),
|
||||
'presupuesto' => en_lista($post['presupuesto'] ?? '', [
|
||||
'esencial','impulso','premium','elite','proyecto','no-se'
|
||||
]),
|
||||
'mensaje' => limpiar_mensaje($post['mensaje'] ?? '', 5000),
|
||||
'origen' => en_lista($post['origen'] ?? '', [
|
||||
'instagram','linkedin','referido','google','otro'
|
||||
]),
|
||||
'consentimiento'=> !empty($post['consentimiento']),
|
||||
];
|
||||
|
||||
if ($datos['nombre'] === '') $errores[] = 'El nombre es obligatorio.';
|
||||
if (!email_valido($datos['email'])) $errores[] = 'El email no es válido.';
|
||||
if ($datos['servicio'] === '') $errores[] = 'Seleccioná un servicio de interés.';
|
||||
if ($datos['mensaje'] === '') $errores[] = 'El mensaje es obligatorio.';
|
||||
if (!$datos['consentimiento']) $errores[] = 'Debés aceptar el uso de tus datos.';
|
||||
|
||||
return [
|
||||
'ok' => empty($errores),
|
||||
'errores' => $errores,
|
||||
'datos' => $datos,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
|
||||
<!-- Eliminamos el bloque <handlers> manual para que no choque con DonWeb -->
|
||||
|
||||
<!-- 1. DOCUMENTO PREDETERMINADO -->
|
||||
<defaultDocument>
|
||||
<files>
|
||||
<clear />
|
||||
<add value="index.php" />
|
||||
<add value="index.html" />
|
||||
</files>
|
||||
</defaultDocument>
|
||||
|
||||
<!-- 2. MODO DETALLADO PARA DIAGNÓSTICO -->
|
||||
<httpErrors errorMode="Detailed" />
|
||||
|
||||
</system.webServer>
|
||||
</configuration>
|
||||