cambios php

This commit is contained in:
2026-09-21 02:57:06 -03:00
parent 82816cb680
commit e36ec1e8ca
31 changed files with 659 additions and 1389 deletions
-19
View File
@@ -1,19 +0,0 @@
<?php
require_once '../config/db.php';
// Verificar si el usuario está logueado
function verificarAuth() {
if (!isset($_SESSION['admin_id'])) {
header('Location: login.php');
exit;
}
}
// Obtener datos del admin logueado
function getAdminActual() {
global $pdo;
$stmt = $pdo->prepare("SELECT id, nombre, email FROM admin_users WHERE id = ?");
$stmt->execute([$_SESSION['admin_id']]);
return $stmt->fetch();
}
?>
-176
View File
@@ -1,176 +0,0 @@
<?php
require_once '../config/db.php';
require_once 'auth.php';
verificarAuth();
// Obtener todos los artículos
$stmt = $pdo->prepare("
SELECT p.*, u.nombre as autor_nombre
FROM blog_posts p
LEFT JOIN admin_users u ON p.autor_id = u.id
ORDER BY p.created_at DESC
");
$stmt->execute();
$posts = $stmt->fetchAll();
$admin = getAdminActual();
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard - Blog Amor y Roma</title>
<link rel="stylesheet" href="../style/main.css">
<style>
.admin-header {
background: white;
padding: 1.5rem 2rem;
border-bottom: 1px solid rgba(0, 63, 82, 0.12);
display: flex;
justify-content: space-between;
align-items: center;
}
.admin-container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.btn-nuevo {
background: #ba124d;
color: white;
padding: 0.75rem 1.5rem;
border-radius: 24px;
text-decoration: none;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-nuevo:hover {
background: #9c0f40;
}
.posts-table {
width: 100%;
border-collapse: collapse;
margin-top: 2rem;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
}
.posts-table th,
.posts-table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid rgba(0, 63, 82, 0.12);
}
.posts-table th {
background: #f5f9f8;
font-weight: 600;
color: #003f52;
font-size: 0.85rem;
text-transform: uppercase;
}
.posts-table tr:hover {
background: #f9f9f9;
}
.estado-badge {
padding: 0.25rem 0.75rem;
border-radius: 999px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
}
.estado-publicado {
background: #d4edda;
color: #155724;
}
.estado-borrador {
background: #fff3cd;
color: #856404;
}
.acciones {
display: flex;
gap: 0.5rem;
}
.btn-accion {
padding: 0.4rem 0.8rem;
border-radius: 6px;
text-decoration: none;
font-size: 0.85rem;
font-weight: 600;
}
.btn-editar {
background: #003f52;
color: white;
}
.btn-eliminar {
background: #dc3545;
color: white;
}
.logout-link {
color: #ba124d;
text-decoration: none;
font-weight: 600;
}
</style>
</head>
<body>
<div class="admin-header">
<div>
<h2 style="margin: 0; font-family: 'Literata', serif;">Hola, <?= htmlspecialchars($admin['nombre']) ?></h2>
<p style="margin: 0.25rem 0 0; color: #666; font-size: 0.9rem;">Gestión de artículos del blog</p>
</div>
<div style="display: flex; gap: 1rem; align-items: center;">
<a href="../blog.php" target="_blank" class="btn-accion" style="background: #eaf0ee; color: #003f52;">Ver Blog</a>
<a href="editor.php" class="btn-nuevo">+ Nuevo Artículo</a>
<a href="logout.php" class="logout-link">Cerrar sesión</a>
</div>
</div>
<div class="admin-container">
<table class="posts-table">
<thead>
<tr>
<th>Título</th>
<th>Categoría</th>
<th>Autor</th>
<th>Estado</th>
<th>Fecha</th>
<th>Vistas</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php if (empty($posts)): ?>
<tr>
<td colspan="7" style="text-align: center; padding: 3rem; color: #666;">
No hay artículos creados aún. <a href="editor.php" style="color: #ba124d;">Crear el primero</a>
</td>
</tr>
<?php else: ?>
<?php foreach ($posts as $post): ?>
<tr>
<td><?= htmlspecialchars($post['titulo']) ?></td>
<td><?= htmlspecialchars($post['categoria']) ?></td>
<td><?= htmlspecialchars($post['autor_nombre']) ?></td>
<td>
<span class="estado-badge estado-<?= $post['estado'] ?>">
<?= $post['estado'] ?>
</span>
</td>
<td><?= date('d/m/Y', strtotime($post['created_at'])) ?></td>
<td><?= $post['vistas'] ?></td>
<td class="acciones">
<a href="editor.php?id=<?= $post['id'] ?>" class="btn-accion btn-editar">Editar</a>
<a href="eliminar.php?id=<?= $post['id'] ?>" class="btn-accion btn-eliminar" onclick="return confirm('¿Eliminar este artículo?')">Eliminar</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</body>
</html>
-294
View File
@@ -1,294 +0,0 @@
<?php
require_once '../config/db.php';
require_once 'auth.php';
verificarAuth();
$admin = getAdminActual();
$post = null;
$modo_edicion = false;
// Si viene ID, es edición
if (isset($_GET['id'])) {
$stmt = $pdo->prepare("SELECT * FROM blog_posts WHERE id = ?");
$stmt->execute([$_GET['id']]);
$post = $stmt->fetch();
if (!$post) {
die('Artículo no encontrado');
}
$modo_edicion = true;
}
// Procesar formulario
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$titulo = trim($_POST['titulo']);
$slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $titulo)));
$extracto = trim($_POST['extracto']);
$contenido = $_POST['contenido'];
$categoria = $_POST['categoria'];
$tags = trim($_POST['tags']);
$destacado = isset($_POST['destacado']) ? 1 : 0;
$estado = $_POST['estado'];
$tiempo_lectura = (int)$_POST['tiempo_lectura'];
$autor_id = $admin['id'];
// Subida de imagen
$imagen = $post['imagen'] ?? '';
if (isset($_FILES['imagen']) && $_FILES['imagen']['error'] === UPLOAD_ERR_OK) {
$allowed = ['image/jpeg', 'image/png', 'image/webp'];
$max_size = 5 * 1024 * 1024; // 5MB
if (!in_array($_FILES['imagen']['type'], $allowed)) {
$error = 'Solo se permiten imágenes JPG, PNG o WebP';
} elseif ($_FILES['imagen']['size'] > $max_size) {
$error = 'La imagen no puede superar los 5MB';
} else {
$extension = pathinfo($_FILES['imagen']['name'], PATHINFO_EXTENSION);
$nombre_imagen = $slug . '-' . time() . '.' . $extension;
$ruta_destino = '../assets/blog/' . $nombre_imagen;
if (!is_dir('../assets/blog')) {
mkdir('../assets/blog', 0755, true);
}
if (move_uploaded_file($_FILES['imagen']['tmp_name'], $ruta_destino)) {
$imagen = 'assets/blog/' . $nombre_imagen;
} else {
$error = 'Error al subir la imagen';
}
}
}
if (!isset($error)) {
if ($modo_edicion) {
$stmt = $pdo->prepare("
UPDATE blog_posts SET
titulo = ?, slug = ?, extracto = ?, contenido = ?,
categoria = ?, tags = ?, imagen = ?, destacado = ?,
estado = ?, tiempo_lectura = ?
WHERE id = ?
");
$stmt->execute([
$titulo, $slug, $extracto, $contenido,
$categoria, $tags, $imagen, $destacado,
$estado, $tiempo_lectura, $post['id']
]);
} else {
$stmt = $pdo->prepare("
INSERT INTO blog_posts
(titulo, slug, extracto, contenido, categoria, tags, imagen, autor_id, destacado, estado, tiempo_lectura)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$titulo, $slug, $extracto, $contenido,
$categoria, $tags, $imagen, $autor_id, $destacado,
$estado, $tiempo_lectura
]);
}
header('Location: dashboard.php');
exit;
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= $modo_edicion ? 'Editar' : 'Nuevo' ?> Artículo - Amor y Roma</title>
<script src="https://cdn.tiny.mce.com/1/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
<link rel="stylesheet" href="../style/main.css">
<style>
.admin-header {
background: white;
padding: 1.5rem 2rem;
border-bottom: 1px solid rgba(0, 63, 82, 0.12);
display: flex;
justify-content: space-between;
align-items: center;
}
.editor-container {
max-width: 1000px;
margin: 0 auto;
padding: 2rem;
}
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
color: #003f52;
font-weight: 600;
}
input[type="text"],
input[type="number"],
select,
textarea {
width: 100%;
padding: 0.75rem;
border: 1.5px solid rgba(0, 63, 82, 0.2);
border-radius: 8px;
font-size: 1rem;
box-sizing: border-box;
font-family: 'Raleway', sans-serif;
}
textarea {
resize: vertical;
min-height: 100px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.checkbox-group {
display: flex;
align-items: center;
gap: 0.5rem;
}
.checkbox-group input[type="checkbox"] {
width: 20px;
height: 20px;
cursor: pointer;
}
.btn-guardar {
background: #ba124d;
color: white;
padding: 0.85rem 2rem;
border: none;
border-radius: 24px;
font-weight: 600;
cursor: pointer;
font-size: 1rem;
}
.btn-guardar:hover {
background: #9c0f40;
}
.btn-cancelar {
background: #eaf0ee;
color: #003f52;
padding: 0.85rem 2rem;
border: none;
border-radius: 24px;
font-weight: 600;
cursor: pointer;
font-size: 1rem;
text-decoration: none;
display: inline-block;
}
.imagen-preview {
margin-top: 1rem;
max-width: 300px;
}
.imagen-preview img {
width: 100%;
border-radius: 8px;
}
.error {
background: #fee;
color: #c00;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
}
</style>
<script>
tinymce.init({
selector: '#contenido',
height: 500,
plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
content_style: 'body { font-family: Raleway, sans-serif; font-size: 16px; }',
language: 'es'
});
</script>
</head>
<body>
<div class="admin-header">
<h2 style="margin: 0; font-family: 'Literata', serif;"><?= $modo_edicion ? 'Editar' : 'Nuevo' ?> Artículo</h2>
<a href="dashboard.php" class="btn-cancelar">← Volver al dashboard</a>
</div>
<div class="editor-container">
<?php if (isset($error)): ?>
<div class="error"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="titulo">Título del artículo *</label>
<input type="text" id="titulo" name="titulo" required value="<?= htmlspecialchars($post['titulo'] ?? '') ?>">
</div>
<div class="form-group">
<label for="extracto">Extracto (resumen corto) *</label>
<textarea id="extracto" name="extracto" required><?= htmlspecialchars($post['extracto'] ?? '') ?></textarea>
</div>
<div class="form-group">
<label for="contenido">Contenido completo *</label>
<textarea id="contenido" name="contenido" required><?= htmlspecialchars($post['contenido'] ?? '') ?></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="categoria">Categoría *</label>
<select id="categoria" name="categoria" required>
<option value="">Seleccionar...</option>
<option value="branding" <?= ($post['categoria'] ?? '') === 'branding' ? 'selected' : '' ?>>Branding</option>
<option value="web" <?= ($post['categoria'] ?? '') === 'web' ? 'selected' : '' ?>>Web</option>
<option value="redes" <?= ($post['categoria'] ?? '') === 'redes' ? 'selected' : '' ?>>Redes</option>
<option value="automatizaciones" <?= ($post['categoria'] ?? '') === 'automatizaciones' ? 'selected' : '' ?>>Automatizaciones</option>
<option value="paid" <?= ($post['categoria'] ?? '') === 'paid' ? 'selected' : '' ?>>Paid Media</option>
<option value="estrategia" <?= ($post['categoria'] ?? '') === 'estrategia' ? 'selected' : '' ?>>Estrategia</option>
<option value="casos" <?= ($post['categoria'] ?? '') === 'casos' ? 'selected' : '' ?>>Casos</option>
</select>
</div>
<div class="form-group">
<label for="estado">Estado *</label>
<select id="estado" name="estado" required>
<option value="borrador" <?= ($post['estado'] ?? 'borrador') === 'borrador' ? 'selected' : '' ?>>Borrador</option>
<option value="publicado" <?= ($post['estado'] ?? '') === 'publicado' ? 'selected' : '' ?>>Publicado</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="tags">Tags (separados por coma)</label>
<input type="text" id="tags" name="tags" value="<?= htmlspecialchars($post['tags'] ?? '') ?>" placeholder="ej: branding, identidad, logo">
</div>
<div class="form-group">
<label for="tiempo_lectura">Tiempo de lectura (minutos)</label>
<input type="number" id="tiempo_lectura" name="tiempo_lectura" min="1" value="<?= $post['tiempo_lectura'] ?? 5 ?>">
</div>
</div>
<div class="form-group">
<label for="imagen">Imagen destacada *</label>
<input type="file" id="imagen" name="imagen" accept="image/*" <?= !$modo_edicion ? 'required' : '' ?>>
<?php if ($post && $post['imagen']): ?>
<div class="imagen-preview">
<img src="../<?= htmlspecialchars($post['imagen']) ?>" alt="Imagen actual">
<p style="font-size: 0.85rem; color: #666; margin-top: 0.5rem;">Imagen actual: <?= basename($post['imagen']) ?></p>
</div>
<?php endif; ?>
</div>
<div class="form-group">
<div class="checkbox-group">
<input type="checkbox" id="destacado" name="destacado" value="1" <?= ($post['destacado'] ?? 0) ? 'checked' : '' ?>>
<label for="destacado" style="margin: 0;">Marcar como destacado (aparece en la sección "Más leídos")</label>
</div>
</div>
<div style="display: flex; gap: 1rem; margin-top: 2rem;">
<button type="submit" class="btn-guardar"> Guardar Artículo</button>
<a href="dashboard.php" class="btn-cancelar">Cancelar</a>
</div>
</form>
</div>
</body>
</html>
-29
View File
@@ -1,29 +0,0 @@
<?php
require_once '../config/db.php';
require_once 'auth.php';
verificarAuth();
if (!isset($_GET['id'])) {
header('Location: dashboard.php');
exit;
}
// Obtener el artículo para borrar la imagen
$stmt = $pdo->prepare("SELECT imagen FROM blog_posts WHERE id = ?");
$stmt->execute([$_GET['id']]);
$post = $stmt->fetch();
if ($post && $post['imagen']) {
$ruta_imagen = '../' . $post['imagen'];
if (file_exists($ruta_imagen)) {
unlink($ruta_imagen);
}
}
// Eliminar el artículo
$stmt = $pdo->prepare("DELETE FROM blog_posts WHERE id = ?");
$stmt->execute([$_GET['id']]);
header('Location: dashboard.php');
exit;
?>
-130
View File
@@ -1,130 +0,0 @@
<?php
require_once '../config/db.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email']);
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT id, nombre, password FROM admin_users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
// Comparación directa sin hash (como pediste)
if ($user && $password === $user['password']) {
$_SESSION['admin_id'] = $user['id'];
$_SESSION['admin_nombre'] = $user['nombre'];
header('Location: dashboard.php');
exit;
} else {
$error = 'Email o contraseña incorrectos';
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Login - Amor y Roma</title>
<style>
body {
font-family: 'Raleway', sans-serif;
background: #eaf0ee;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
}
.login-container {
background: white;
padding: 3rem;
border-radius: 16px;
box-shadow: 0 10px 40px rgba(0,0,0,0.1);
width: 100%;
max-width: 400px;
}
h1 {
color: #221728;
margin-bottom: 0.5rem;
font-family: 'Literata', serif;
font-style: italic;
}
.subtitle {
color: #666;
margin-bottom: 2rem;
font-size: 0.9rem;
}
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
color: #003f52;
font-weight: 600;
font-size: 0.9rem;
}
input[type="email"],
input[type="password"] {
width: 100%;
padding: 0.75rem;
border: 1.5px solid rgba(0, 63, 82, 0.2);
border-radius: 8px;
font-size: 1rem;
box-sizing: border-box;
}
input:focus {
outline: none;
border-color: #ba124d;
}
.btn-login {
width: 100%;
padding: 0.85rem;
background: #ba124d;
color: white;
border: none;
border-radius: 24px;
font-weight: 600;
cursor: pointer;
font-size: 1rem;
transition: background 0.3s;
}
.btn-login:hover {
background: #9c0f40;
}
.error {
background: #fee;
color: #c00;
padding: 0.75rem;
border-radius: 8px;
margin-bottom: 1rem;
font-size: 0.9rem;
}
</style>
</head>
<body>
<div class="login-container">
<h1>Amor y Roma</h1>
<p class="subtitle">Panel de Administración del Blog</p>
<?php if ($error): ?>
<div class="error"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required autofocus>
</div>
<div class="form-group">
<label for="password">Contraseña</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit" class="btn-login">Ingresar</button>
</form>
</div>
</body>
</html>
-6
View File
@@ -1,6 +0,0 @@
<?php
session_start();
session_destroy();
header('Location: login.php');
exit;
?>
-117
View File
@@ -1,117 +0,0 @@
<?php
require_once 'config/db.php';
if (!isset($_GET['id'])) {
header('Location: blog.php');
exit;
}
// Obtener artículo
$stmt = $pdo->prepare("
SELECT p.*, u.nombre as autor_nombre
FROM blog_posts p
LEFT JOIN admin_users u ON p.autor_id = u.id
WHERE p.id = ? AND p.estado = 'publicado'
");
$stmt->execute([$_GET['id']]);
$post = $stmt->fetch();
if (!$post) {
header('Location: blog.php');
exit;
}
// Incrementar vistas
$stmt = $pdo->prepare("UPDATE blog_posts SET vistas = vistas + 1 WHERE id = ?");
$stmt->execute([$post['id']]);
?>
<!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="<?= htmlspecialchars($post['extracto']) ?>">
<title><?= htmlspecialchars($post['titulo']) ?> | Blog Amor y Roma</title>
<link rel="stylesheet" href="style/main.css">
<style>
.articulo-header {
max-width: 900px;
margin: 0 auto;
padding: 4rem 2rem 2rem;
}
.articulo-imagen {
width: 100%;
max-height: 500px;
object-fit: cover;
border-radius: 16px;
margin: 2rem 0;
}
.articulo-contenido {
max-width: 800px;
margin: 0 auto;
padding: 0 2rem 4rem;
font-size: 1.1rem;
line-height: 1.8;
}
.articulo-contenido h2,
.articulo-contenido h3 {
margin-top: 2.5rem;
margin-bottom: 1rem;
}
.articulo-contenido p {
margin-bottom: 1.5rem;
}
.articulo-contenido img {
max-width: 100%;
height: auto;
border-radius: 8px;
margin: 2rem 0;
}
.articulo-meta {
display: flex;
gap: 2rem;
color: #666;
font-size: 0.9rem;
margin: 1rem 0 2rem;
padding: 1rem 0;
border-top: 1px solid rgba(0, 63, 82, 0.12);
border-bottom: 1px solid rgba(0, 63, 82, 0.12);
}
.volver-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: #ba124d;
text-decoration: none;
font-weight: 600;
margin-bottom: 2rem;
}
</style>
</head>
<body>
<div id="menu-container"></div>
<main>
<article>
<div class="articulo-header">
<a href="blog.php" class="volver-link">← Volver al blog</a>
<span class="badge-filosofia"><?= ucfirst(htmlspecialchars($post['categoria'])) ?></span>
<h1 style="font-size: clamp(2rem, 4vw, 3rem); margin: 1rem 0;"><?= htmlspecialchars($post['titulo']) ?></h1>
<div class="articulo-meta">
<span>📅 <?= date('d de F Y', strtotime($post['created_at'])) ?></span>
<span> <?= $post['tiempo_lectura'] ?> min de lectura</span>
<span>✍️ <?= htmlspecialchars($post['autor_nombre']) ?></span>
</div>
<img src="<?= htmlspecialchars($post['imagen']) ?>" alt="<?= htmlspecialchars($post['titulo']) ?>" class="articulo-imagen">
</div>
<div class="articulo-contenido">
<?= $post['contenido'] ?>
</div>
</article>
</main>
<div id="footer-container"></div>
<script src="scripts/main.js"></script>
</body>
</html>
+131
View File
@@ -0,0 +1,131 @@
<!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="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>📅 5 de enero de 2024</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>
+109
View File
@@ -0,0 +1,109 @@
<!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="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> 10 de enero de 2024</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>
+87
View File
@@ -0,0 +1,87 @@
<!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="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>📅 18 de enero de 2024</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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

+59 -151
View File
@@ -4,30 +4,31 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <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."> <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> <title>Blog | Amor y Roma — Recursos y Estrategias</title>
<link rel="stylesheet" href="style/main.css"> <link rel="stylesheet" href="style/main.css">
<link rel="stylesheet" href="style/blog.css">
</head> </head>
<body> <body>
<div id="fluid-bg" aria-hidden="true">
<canvas id="fluidCanvas"></canvas>
</div>
<div id="menu-container"></div> <div id="menu-container"></div>
<main> <main>
<!-- SECCIÓN 1: HERO COMPACTO --> <!-- HERO -->
<section class="blog-hero-compact"> <section class="blog-hero-compact">
<div class="hero-compact-content"> <div class="hero-compact-content">
<span class="badge-filosofia"></span> <span class="badge-filosofia">Ideas que construyen marcas</span>
<h1 class="hero-compact-title">Ideas que construyen marcas</h1> <h1 class="hero-compact-title">Estrategia, diseño y tecnología explicados sin tecnicismos</h1>
<p class="hero-compact-subtitle"> <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> </p>
</div> </div>
</section> </section>
<!-- SECCIÓN 2: HEADER DE FILTROS (STICKY CON BUSCADOR) --> <!-- FILTROS -->
<section class="blog-filters-header" id="blog-filters-header"> <section class="blog-filters-section" id="blog-filters-header">
<div class="filters-header-container"> <div class="filters-container">
<!-- Fila superior: Buscador + Filtros principales -->
<div class="filters-top-row"> <div class="filters-top-row">
<div class="search-wrapper-compact"> <div class="search-wrapper-compact">
<span class="search-icon"> <span class="search-icon">
@@ -36,13 +37,7 @@
<path d="m21 21-4.35-4.35"/> <path d="m21 21-4.35-4.35"/>
</svg> </svg>
</span> </span>
<input <input type="text" id="blog-search" placeholder="Buscá por tema: branding, web, redes..." autocomplete="off" aria-label="Buscar artículos">
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"> <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"> <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"/> <path d="M18 6 6 18M6 6l12 12"/>
@@ -56,7 +51,6 @@
</div> </div>
</div> </div>
<!-- Fila inferior: Categorías + Ordenamiento -->
<div class="filters-bottom-row"> <div class="filters-bottom-row">
<div class="filter-categories-compact"> <div class="filter-categories-compact">
<button class="category-btn active" data-category="all">Todas</button> <button class="category-btn active" data-category="all">Todas</button>
@@ -73,12 +67,10 @@
<select id="sort-select" class="sort-select-compact"> <select id="sort-select" class="sort-select-compact">
<option value="recent">Más recientes</option> <option value="recent">Más recientes</option>
<option value="popular">Más populares</option> <option value="popular">Más populares</option>
<option value="alphabetical">A-Z</option>
</select> </select>
</div> </div>
</div> </div>
<!-- Info de resultados -->
<div class="results-info-compact"> <div class="results-info-compact">
<span id="results-count">Mostrando <strong>todos</strong> los artículos</span> <span id="results-count">Mostrando <strong>todos</strong> los artículos</span>
<button class="reset-filters-compact" id="reset-filters">Limpiar filtros</button> <button class="reset-filters-compact" id="reset-filters">Limpiar filtros</button>
@@ -86,7 +78,7 @@
</div> </div>
</section> </section>
<!-- SECCIÓN 3: ARTÍCULOS DESTACADOS --> <!-- DESTACADOS -->
<section class="featured-posts" id="featured-posts"> <section class="featured-posts" id="featured-posts">
<div class="section-header"> <div class="section-header">
<h2 class="section-title">Más leídos</h2> <h2 class="section-title">Más leídos</h2>
@@ -94,32 +86,33 @@
</div> </div>
<div class="featured-grid"> <div class="featured-grid">
<!-- Artículo destacado 1 --> <!-- Artículo Destacado 1 -->
<article class="featured-card" data-categories="branding estrategia" data-tags="identidad, marca, posicionamiento" data-featured="true"> <article class="featured-card" data-categories="branding" data-featured="true">
<div class="featured-image"> <div class="featured-image">
<img src="../assets/blog/branding-completo.jpg" alt="Guía completa de branding"> <img src="assets/blog/logo-marca.jpg" alt="Tu logo no es tu marca">
<span class="featured-badge">Más leído</span> <span class="featured-badge">Destacado</span>
</div> </div>
<div class="featured-content"> <div class="featured-content">
<div class="featured-meta"> <div class="featured-meta">
<span class="category-tag branding">Branding</span> <span class="category-tag branding">Branding</span>
<time datetime="2024-01-15">15 Ene 2024</time> <time datetime="2024-01-18">18 Ene 2024</time>
</div> </div>
<h3 class="featured-title">Guía completa: Cómo construir una identidad de marca que perdure</h3> <h3 class="featured-title">Tu logo no es tu marca (y por qué importa)</h3>
<p class="featured-excerpt"> <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. Muchos emprendedores confunden el símbolo con la sustancia. Tener un logo bonito no es tener una marca.
</p> </p>
<div class="featured-footer"> <div class="featured-footer">
<span class="reading-time">⏱ 12 min de lectura</span> <span class="reading-time">⏱ 6 min de lectura</span>
<a href="#" class="btn-read">Leer artículo →</a> <a href="articulos/to-logo-no-es-tu-marca.html" class="btn-read">Leer artículo →</a>
</div> </div>
</div> </div>
</article> </article>
<!-- Artículo destacado 2 --> <!-- Artículo Destacado 2 -->
<article class="featured-card" data-categories="web" data-tags="landing page, conversión, diseño" data-featured="true"> <article class="featured-card" data-categories="web" data-featured="true">
<div class="featured-image"> <div class="featured-image">
<img src="../assets/blog/landing-page.jpg" alt="Landing pages"> <img src="assets/blog/landing-page.jpg" alt="Landing pages que convierten">
<span class="featured-badge">Destacado</span>
</div> </div>
<div class="featured-content"> <div class="featured-content">
<div class="featured-meta"> <div class="featured-meta">
@@ -128,19 +121,20 @@
</div> </div>
<h3 class="featured-title">Landing pages que convierten: 7 principios probados</h3> <h3 class="featured-title">Landing pages que convierten: 7 principios probados</h3>
<p class="featured-excerpt"> <p class="featured-excerpt">
Estructura, copy y diseño working together para transformar visitantes en clientes reales. No es magia, es método. Una landing page efectiva no depende de la suerte ni de tendencias pasajeras.
</p> </p>
<div class="featured-footer"> <div class="featured-footer">
<span class="reading-time">⏱ 8 min de lectura</span> <span class="reading-time"> 8 min de lectura</span>
<a href="#" class="btn-read">Leer artículo →</a> <a href="articulos/landing-pages-que-convierten.html" class="btn-read">Leer artículo →</a>
</div> </div>
</div> </div>
</article> </article>
<!-- Artículo destacado 3 --> <!-- Artículo Destacado 3 -->
<article class="featured-card" data-categories="automatizaciones" data-tags="instagram, chatbots, leads" data-featured="true"> <article class="featured-card" data-categories="automatizaciones" data-featured="true">
<div class="featured-image"> <div class="featured-image">
<img src="../assets/blog/automatizacion.jpg" alt="Automatizaciones"> <img src="assets/blog/automatizacion.jpg" alt="Automatizaciones en Instagram">
<span class="featured-badge">Destacado</span>
</div> </div>
<div class="featured-content"> <div class="featured-content">
<div class="featured-meta"> <div class="featured-meta">
@@ -149,48 +143,24 @@
</div> </div>
<h3 class="featured-title">Automatizaciones en Instagram: de 0 a 100 leads/mes</h3> <h3 class="featured-title">Automatizaciones en Instagram: de 0 a 100 leads/mes</h3>
<p class="featured-excerpt"> <p class="featured-excerpt">
Flujos inteligentes que trabajan 24/7 mientras vos te enfocás en lo que mejor sabés hacer. Responder el mismo mensaje 50 veces al día no es escalable. Las automatizaciones bien hechas te permiten captar prospectos.
</p> </p>
<div class="featured-footer"> <div class="featured-footer">
<span class="reading-time"> 9 min de lectura</span> <span class="reading-time">⏱ 9 min de lectura</span>
<a href="#" class="btn-read">Leer artículo →</a> <a href="articulos/automatizaciones-instagram.html" class="btn-read">Leer artículo →</a>
</div> </div>
</div> </div>
</article> </article>
</div> </div>
</section> </section>
<!-- SECCIÓN 4: GRID DE ARTÍCULOS --> <!-- GRID DE ARTÍCULOS
<section class="blog-grid-section"> <section class="blog-grid-section">
<div class="blog-grid" id="blog-grid"> <div class="blog-grid" id="blog-grid">
<!-- ARTÍCULO 1 --> <article class="blog-card" data-categories="branding" data-featured="true">
<article class="blog-card" data-categories="redes estrategia" data-tags="contenido, planificación, calendario" data-featured="false">
<div class="card-image"> <div class="card-image">
<img src="../assets/blog/contenido-redes.jpg" alt="Contenido para redes"> <img src="assets/blog/logo-marca.jpg" alt="Tu logo no es tu marca">
<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> <span class="card-category branding">Branding</span>
</div> </div>
<div class="card-content"> <div class="card-content">
@@ -200,135 +170,73 @@
</div> </div>
<h3 class="card-title">Tu logo no es tu marca (y por qué importa)</h3> <h3 class="card-title">Tu logo no es tu marca (y por qué importa)</h3>
<p class="card-excerpt"> <p class="card-excerpt">
La diferencia entre un símbolo bonito y una identidad estratégica que realmente funciona. Muchos emprendedores confunden el símbolo con la sustancia. Tener un logo bonito no es tener una marca.
</p> </p>
<div class="card-tags"> <a href="articulos/tu-logo-no-es-tu-marca.html" class="card-link">Leer artículo</a>
<span class="tag">Logo</span>
<span class="tag">Identidad</span>
</div>
<a href="#" class="card-link">Leer artículo</a>
</div> </div>
</article> </article>
<!-- ARTÍCULO 3 --> <article class="blog-card" data-categories="web" data-featured="true">
<article class="blog-card" data-categories="web paid" data-tags="seo, google ads, tráfico" data-featured="false">
<div class="card-image"> <div class="card-image">
<img src="../assets/blog/seo-web.jpg" alt="SEO"> <img src="assets/blog/landing-page.jpg" alt="Landing pages que convierten">
<span class="card-category web">Web</span> <span class="card-category web">Web</span>
</div> </div>
<div class="card-content"> <div class="card-content">
<div class="card-meta"> <div class="card-meta">
<time datetime="2024-01-12">12 Ene 2024</time> <time datetime="2024-01-10">10 Ene 2024</time>
<span class="reading-time-mini">10 min</span> <span class="reading-time-mini">8 min</span>
</div> </div>
<h3 class="card-title">SEO vs Paid Media: cuándo usar cada uno</h3> <h3 class="card-title">Landing pages que convierten: 7 principios probados</h3>
<p class="card-excerpt"> <p class="card-excerpt">
No son enemigos, son complementarios. Te explicamos cómo combinarlos estratégicamente. No es magia, es método. Una landing page efectiva no depende de la suerte.
</p> </p>
<div class="card-tags"> <a href="articulos/landing-pages-que-convierten.html" class="card-link">Leer artículo</a>
<span class="tag">SEO</span>
<span class="tag">Google Ads</span>
</div>
<a href="#" class="card-link">Leer artículo</a>
</div> </div>
</article> </article>
<!-- ARTÍCULO 4 --> <article class="blog-card" data-categories="automatizaciones" data-featured="true">
<article class="blog-card" data-categories="casos estrategia" data-tags="caso de éxito, tecnología, ecosistema" data-featured="false">
<div class="card-image"> <div class="card-image">
<img src="../assets/blog/caso-tech.jpg" alt="Caso de éxito"> <img src="assets/blog/automatizacion.jpg" alt="Automatizaciones en Instagram">
<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> <span class="card-category automatizaciones">Automatizaciones</span>
</div> </div>
<div class="card-content"> <div class="card-content">
<div class="card-meta"> <div class="card-meta">
<time datetime="2024-01-03">3 Ene 2024</time> <time datetime="2024-01-05">5 Ene 2024</time>
<span class="reading-time-mini">9 min</span> <span class="reading-time-mini">9 min</span>
</div> </div>
<h3 class="card-title">Chatbots que no parecen robots: la clave está en el copy</h3> <h3 class="card-title">Automatizaciones en Instagram: de 0 a 100 leads/mes</h3>
<p class="card-excerpt"> <p class="card-excerpt">
Cómo escribir flujos de conversación que suenen humanos y realmente vendan. Responder el mismo mensaje 50 veces al día no es escalable.
</p> </p>
<div class="card-tags"> <a href="articulos/automatizaciones-instagram.html" class="card-link">Leer artículo</a>
<span class="tag">ManyChat</span>
<span class="tag">Ventas</span>
</div>
<a href="#" class="card-link">Leer artículo</a>
</div> </div>
</article> </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>
</div> </div>
<!-- ESTADO VACÍO (cuando no hay resultados) -->
<div class="empty-state" id="empty-state" style="display: none;"> <div class="empty-state" id="empty-state" style="display: none;">
<div class="empty-icon">🔍</div> <div class="empty-icon"></div>
<h3>No encontramos artículos con esos filtros</h3> <h3>No encontramos artículos con esos filtros</h3>
<p>Probá con otros términos o limpiá los filtros para ver todo el contenido.</p> <p>Probá con otros términos o limpiá los filtros para ver todo el contenido.</p>
<button class="btn btn-primary" id="empty-reset">Ver todos los artículos</button> <button class="btn btn-primary" id="empty-reset">Ver todos los artículos</button>
</div> </div>
<!-- PAGINACIÓN / CARGAR MÁS -->
<div class="load-more-container"> <div class="load-more-container">
<button class="btn btn-secondary" id="load-more">Cargar más artículos</button> <button class="btn btn-secondary" id="load-more">Cargar más artículos</button>
</div> </div>
</section> </section> -->
<!-- SECCIÓN 5: NEWSLETTER --> <!-- NEWSLETTER -->
<section class="newsletter-section"> <section class="newsletter-section">
<div class="newsletter-card"> <div class="newsletter-card">
<div class="newsletter-content"> <div class="newsletter-content">
<h2 class="newsletter-title">Ideas frescas en tu inbox</h2> <h2 class="newsletter-title">Ideas frescas en tu inbox</h2>
<p class="newsletter-subtitle"> <p class="newsletter-subtitle">
Suscribite y recibí nuestras mejores estrategias de branding, web y marketing digital. Suscribite y recibí nuestras mejores estrategias de branding, web y marketing digital.
Sin spam, solo contenido de valor.
</p> </p>
</div> </div>
<form class="newsletter-form" id="newsletter-form"> <form class="newsletter-form" id="newsletter-form">
<button type="submit" class="btn btn-primary">Tu email profesional</button> <input type="email" placeholder="Tu email profesional" required>
<button type="submit" class="btn btn-primary">Suscribirme</button> <button type="submit" class="btn btn-primary">Suscribirme</button>
</form> </form>
</div> </div>
@@ -339,6 +247,6 @@
<script src="scripts/main.js"></script> <script src="scripts/main.js"></script>
<script src="scripts/blog.js"></script> <script src="scripts/blog.js"></script>
<link rel="stylesheet" href="style/blog.css"> <script src="scripts/fluid.js"></script>
</body> </body>
</html> </html>
-194
View File
@@ -1,194 +0,0 @@
<?php
require_once 'config/db.php';
// Obtener artículos publicados
$stmt = $pdo->prepare("
SELECT p.*, u.nombre as autor_nombre
FROM blog_posts p
LEFT JOIN admin_users u ON p.autor_id = u.id
WHERE p.estado = 'publicado'
ORDER BY p.created_at DESC
");
$stmt->execute();
$posts = $stmt->fetchAll();
// Obtener destacados
$stmt = $pdo->prepare("
SELECT p.*, u.nombre as autor_nombre
FROM blog_posts p
LEFT JOIN admin_users u ON p.autor_id = u.id
WHERE p.estado = 'publicado' AND p.destacado = 1
ORDER BY p.vistas DESC
LIMIT 3
");
$stmt->execute();
$destacados = $stmt->fetchAll();
?>
<!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="Blog de Amor y Roma. Estrategia, branding, desarrollo web y marketing digital con esencia y solidez.">
<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="menu-container"></div>
<main>
<!-- HERO -->
<section class="blog-hero-compact">
<div class="hero-compact-content">
<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">
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 -->
<section class="blog-filters-section" id="blog-filters-header">
<div class="filters-container">
<!-- Fila superior: Buscador + Filtros principales -->
<div class="filters-top-row">
<div class="search-wrapper-compact">
<span class="search-icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/>
<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">
<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"/>
</svg>
</button>
</div>
<div class="filter-group-compact">
<button class="filter-btn active" data-filter="all">Todos</button>
<button class="filter-btn" data-filter="destacados">Destacados</button>
</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>
<button class="category-btn" data-category="branding">Branding</button>
<button class="category-btn" data-category="web">Web</button>
<button class="category-btn" data-category="redes">Redes</button>
<button class="category-btn" data-category="automatizaciones">Automatizaciones</button>
<button class="category-btn" data-category="paid">Paid Media</button>
<button class="category-btn" data-category="estrategia">Estrategia</button>
<button class="category-btn" data-category="casos">Casos</button>
</div>
<div class="filter-secondary-compact">
<select id="sort-select" class="sort-select-compact">
<option value="recent">Más recientes</option>
<option value="popular">Más populares</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>
</div>
</div>
</section>
<!-- DESTACADOS -->
<?php if (!empty($destacados)): ?>
<section class="featured-posts" id="featured-posts">
<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">
<?php foreach ($destacados as $post): ?>
<article class="featured-card" data-categories="<?= htmlspecialchars($post['categoria']) ?>">
<div class="featured-image">
<img src="<?= htmlspecialchars($post['imagen']) ?>" alt="<?= htmlspecialchars($post['titulo']) ?>">
<span class="featured-badge">Destacado</span>
</div>
<div class="featured-content">
<div class="featured-meta">
<span class="category-tag <?= htmlspecialchars($post['categoria']) ?>"><?= ucfirst(htmlspecialchars($post['categoria'])) ?></span>
<time datetime="<?= $post['created_at'] ?>"><?= date('d M Y', strtotime($post['created_at'])) ?></time>
</div>
<h3 class="featured-title"><?= htmlspecialchars($post['titulo']) ?></h3>
<p class="featured-excerpt"><?= htmlspecialchars($post['extracto']) ?></p>
<div class="featured-footer">
<span class="reading-time">⏱ <?= $post['tiempo_lectura'] ?> min de lectura</span>
<a href="articulo.php?id=<?= $post['id'] ?>" class="btn-read">Leer artículo →</a>
</div>
</div>
</article>
<?php endforeach; ?>
</div>
</section>
<?php endif; ?>
<!-- GRID DE ARTÍCULOS -->
<section class="blog-grid-section">
<div class="blog-grid" id="blog-grid">
<?php foreach ($posts as $post): ?>
<article class="blog-card" data-categories="<?= htmlspecialchars($post['categoria']) ?>">
<div class="card-image">
<img src="<?= htmlspecialchars($post['imagen']) ?>" alt="<?= htmlspecialchars($post['titulo']) ?>">
<span class="card-category <?= htmlspecialchars($post['categoria']) ?>"><?= ucfirst(htmlspecialchars($post['categoria'])) ?></span>
</div>
<div class="card-content">
<div class="card-meta">
<time datetime="<?= $post['created_at'] ?>"><?= date('d M Y', strtotime($post['created_at'])) ?></time>
<span class="reading-time-mini"><?= $post['tiempo_lectura'] ?> min</span>
</div>
<h3 class="card-title"><?= htmlspecialchars($post['titulo']) ?></h3>
<p class="card-excerpt"><?= htmlspecialchars($post['extracto']) ?></p>
<a href="articulo.php?id=<?= $post['id'] ?>" class="card-link">Leer artículo</a>
</div>
</article>
<?php endforeach; ?>
</div>
<?php if (empty($posts)): ?>
<div class="empty-state" id="empty-state">
<div class="empty-icon">📝</div>
<h3>Aún no hay artículos publicados</h3>
<p>Volvé pronto para encontrar contenido de valor sobre branding, web y marketing digital.</p>
</div>
<?php endif; ?>
</section>
<!-- 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.
</p>
</div>
<form class="newsletter-form" id="newsletter-form">
<input type="email" placeholder="Tu email profesional" required style="padding: 0.85rem; border: 1.5px solid rgba(0, 63, 82, 0.2); border-radius: 24px; min-width: 300px;">
<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>
</body>
</html>
+1 -1
View File
@@ -19,7 +19,7 @@ define('MAIL_TO', 'contacto@amoryroma.com.ar');
define('MAIL_TO_NAME', 'Amor & Roma'); define('MAIL_TO_NAME', 'Amor & Roma');
// ─── Redirección post-éxito ──────────────────────────────────────────── // ─── Redirección post-éxito ────────────────────────────────────────────
define('REDIRECT_URL', 'inicio.html'); define('REDIRECT_URL', 'index.html');
define('REDIRECT_MS', 4000); // milisegundos antes de redirigir define('REDIRECT_MS', 4000); // milisegundos antes de redirigir
// ─── Modo debug ──────────────────────────────────────────────────────── // ─── Modo debug ────────────────────────────────────────────────────────
-29
View File
@@ -1,29 +0,0 @@
<?php
// Configuración de base de datos
define('DB_HOST', 'localhost');
define('DB_NAME', 'w360284_blog');
define('DB_USER', 'w360284_blog');
define('DB_PASS', 'f@IuVS8sjLLm7aN');
define('DB_CHARSET', 'utf8mb4');
// Crear conexión PDO
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
} catch (PDOException $e) {
die("Error de conexión: " . $e->getMessage());
}
// Iniciar sesión si no está iniciada
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
?>
+4
View File
@@ -11,6 +11,9 @@
<link rel="stylesheet" href="style/modal.css"> <link rel="stylesheet" href="style/modal.css">
</head> </head>
<body> <body>
<div id="fluid-bg" aria-hidden="true">
<canvas id="fluidCanvas"></canvas>
</div>
<div id="menu-container"></div> <div id="menu-container"></div>
<main> <main>
@@ -266,5 +269,6 @@
<script src="scripts/main.js"></script> <script src="scripts/main.js"></script>
<script src="scripts/contacto.js"></script> <script src="scripts/contacto.js"></script>
<script src="scripts/fluid.js"></script>
</body> </body>
</html> </html>
+4 -4
View File
@@ -3,7 +3,7 @@
<!-- SECCIÓN 1: Contenido Principal (Columnas, enlaces y CTAs) --> <!-- SECCIÓN 1: Contenido Principal (Columnas, enlaces y CTAs) -->
<div class="footer-content"> <div class="footer-content">
<div class="footer-col" id="footer-brand"> <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_ciruela.png" alt="Logo" class="logo-light">
<img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark"> <img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark">
</a> </a>
@@ -13,10 +13,10 @@
<div class="footer-col" id="footer-links"> <div class="footer-col" id="footer-links">
<h4>Explorar</h4> <h4>Explorar</h4>
<ul> <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="servicios.html">Servicios</a></li>
<li><a href="planes.html">Planes</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> <li><a href="blog.html">Blog</a></li>
</ul> </ul>
</div> </div>
@@ -36,7 +36,7 @@
<h4></h4> <h4></h4>
<div class="menu-buttons"> <div class="menu-buttons">
<a href="contacto.html" class="btn-menu btn-menu-primary">¿Tenés un proyecto en mente?</a> <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"> <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://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> <a href="https://web.facebook.com/amoryroma.creativo/" target="_blank" rel="noopener"><i class="fa-brands fa-facebook"></i> Facebook</a>
+9 -9
View File
@@ -1,6 +1,6 @@
<header class="site-header"> <header class="site-header">
<nav class="main-nav"> <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_ciruela.png" alt="Logo" class="logo-light">
<img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark"> <img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark">
</a> </a>
@@ -35,12 +35,12 @@
<div class="menu-column"> <div class="menu-column">
<h3>Amor&Roma</h3> <h3>Amor&Roma</h3>
<ul> <ul>
<li><a href="inicio.html">Comencemos</a></li> <li><a href="index.html">Comencemos</a></li>
<li><a href="inicio.html#servicios">Qué hacemos?</a></li> <li><a href="index.html#servicios">Qué hacemos?</a></li>
<li><a href="inicio.html#diagnostico">Diagnóstico</a></li> <li><a href="index.html#diagnostico">Diagnóstico</a></li>
<li><a href="inicio.html#metodologia">Método A&R</a></li> <li><a href="index.html#metodologia">Método A&R</a></li>
<li><a href="inicio.html#planes-destacados">Destacados</a></li> <li><a href="index.html#planes-destacados">Destacados</a></li>
<li><a href="inicio.html#portfolio">Desafios</a></li> <li><a href="index.html#portfolio">Desafios</a></li>
</ul> </ul>
</div> </div>
@@ -48,7 +48,7 @@
<div class="menu-column"> <div class="menu-column">
<h3>Navegación</h3> <h3>Navegación</h3>
<ul> <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="servicios.html">Servicios</a></li>
<li><a href="planes.html">Planes</a></li> <li><a href="planes.html">Planes</a></li>
<!--<li><a href="portfolio.html">Portfolio</a></li>--> <!--<li><a href="portfolio.html">Portfolio</a></li>-->
@@ -86,7 +86,7 @@
<!-- Logo de marca integrado en el menú --> <!-- Logo de marca integrado en el menú -->
<div class="menu-brand"> <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_ciruela.png" alt="Logo" class="logo-light">
<img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark"> <img src="assets/logos/logo_frio.png" alt="Logo" class="logo-dark">
</a> </a>
+2 -2
View File
@@ -20,10 +20,10 @@
<div class="hero-content"> <div class="hero-content">
<span class="badge-filosofia">Agencia Boutique de Marketing Digital</span> <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> <h1 class="hero-title">En un mundo de ruido, solo lo auténtico resuena</h1>
<p class="hero-subtitle">Combinamos la pasión creativa 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> <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"> <div class="hero-cta-group">
<a href="#" class="btn btn-primary hero-cta-primary">Hablemos</a> <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="index.html#servicios" class="btn btn-secondary hero-cta-secondary">Conocé más</a>
</div> </div>
</div> </div>
</section> </section>
+6 -2
View File
@@ -10,6 +10,9 @@
<link rel="stylesheet" href="style/nosotros.css"> <link rel="stylesheet" href="style/nosotros.css">
</head> </head>
<body> <body>
<div id="fluid-bg" aria-hidden="true">
<canvas id="fluidCanvas"></canvas>
</div>
<div id="menu-container"></div> <div id="menu-container"></div>
<main> <main>
@@ -124,7 +127,7 @@
<p class="transparencia-titulo">INVERSIÓN</p> <p class="transparencia-titulo">INVERSIÓN</p>
<p class="transparencia-dato">Desde $250.000/mes</p> <p class="transparencia-dato">Desde $250.000/mes</p>
<p class="transparencia-texto"> <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> </p>
</article> </article>
@@ -225,7 +228,7 @@
<p class="cta-subtitle">Agendemos una reunión. Sin plantillas, sin compromisos, solo estrategia a medida.</p> <p class="cta-subtitle">Agendemos una reunión. Sin plantillas, sin compromisos, solo estrategia a medida.</p>
<div class="cta-buttons"> <div class="cta-buttons">
<a href="contacto.html" class="btn btn-cta-primary">Hablemos de tu proyecto</a> <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>
</div> </div>
</section> </section>
@@ -234,5 +237,6 @@
<div id="footer-container"></div> <div id="footer-container"></div>
<script src="scripts/main.js"></script> <script src="scripts/main.js"></script>
<script src="scripts/fluid.js"></script>
</body> </body>
</html> </html>
+6 -2
View File
@@ -12,6 +12,9 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head> </head>
<body> <body>
<div id="fluid-bg" aria-hidden="true">
<canvas id="fluidCanvas"></canvas>
</div>
<div id="menu-container"></div> <div id="menu-container"></div>
<main> <main>
@@ -489,10 +492,10 @@
<section class="planes-cta"> <section class="planes-cta">
<div class="planes-cta-card"> <div class="planes-cta-card">
<h2 class="planes-cta-titulo">¿No sabés cuál plan elegir?</h2> <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"> <div class="planes-cta-buttons">
<a href="contacto.html" class="btn btn-cta-primary">Asesoramiento gratuito</a> <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>
</div> </div>
</section> </section>
@@ -505,5 +508,6 @@
<script src="scripts/main.js"></script> <script src="scripts/main.js"></script>
<script src="scripts/planes.js"></script> <script src="scripts/planes.js"></script>
<script src="scripts/fluid.js"></script>
</body> </body>
</html> </html>
+2 -2
View File
@@ -27,7 +27,7 @@
modal.setAttribute('aria-hidden', 'true'); modal.setAttribute('aria-hidden', 'true');
document.body.style.overflow = ''; document.body.style.overflow = '';
if (redirectTimer) clearTimeout(redirectTimer); if (redirectTimer) clearTimeout(redirectTimer);
if (redirigir) window.location.href = 'inicio.html'; if (redirigir) window.location.href = 'index.html';
} }
function mostrarError(mensaje) { function mostrarError(mensaje) {
@@ -86,7 +86,7 @@
const delay = Number(json.delay) || 4000; const delay = Number(json.delay) || 4000;
redirectTimer = setTimeout(() => { redirectTimer = setTimeout(() => {
window.location.href = json.redirect || 'inicio.html'; window.location.href = json.redirect || 'index.html';
}, delay); }, delay);
} else { } else {
mostrarError(json.message || 'No pudimos enviar tu mensaje.'); mostrarError(json.message || 'No pudimos enviar tu mensaje.');
+74 -100
View File
@@ -1,6 +1,6 @@
"use strict"; "use strict";
// ===== CONFIGURACIÓN DEL EFECTO ===== // ===== CONFIGURACIÓN DEL EFECTO (Idéntica a fluid - copia.js) =====
const config = { const config = {
TEXTURE_DOWNSAMPLE: 1, TEXTURE_DOWNSAMPLE: 1,
DENSITY_DISSIPATION: 0.975, DENSITY_DISSIPATION: 0.975,
@@ -11,22 +11,20 @@ const config = {
SPLAT_RADIUS: 0.003 SPLAT_RADIUS: 0.003
}; };
// ===== COLORES DE MARCA (Modo Claro / Oscuro) ===== // ===== COLORES DE MARCA SEGÚN EL TEMA =====
function getBrandColors() { function getBrandColors() {
const isDark = document.documentElement.getAttribute('data-theme') === 'dark'; const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
if (isDark) { if (isDark) {
// Tonos luminiscentes y vibrantes para contrastar sobre #110916
return [ return [
[0.920, 0.120, 0.420], // Carmesí brillante (#EA1E6B) [0.920, 0.120, 0.420], // Carmesí / Fucsia luminoso (#EA1E6B)
[0.050, 0.680, 0.780], // Teal cian luminoso (#0DAEC7) [0.080, 0.650, 0.780], // Teal cian luminoso (#14A6C7)
[0.850, 0.550, 0.700] // Rosa suave (#D98CB3) [0.850, 0.500, 0.720] // Rosa suave (#D980B8)
]; ];
} else { } else {
// Tonos puros y elegantes para teñir el fondo claro sin ensuciarlo
return [ return [
[0.729, 0.071, 0.302], // Bordo de marca (#BA124D) [0.729, 0.071, 0.302], // Bordo de marca (#BA124D)
[0.000, 0.320, 0.420], // Teal medio (#00526B) [0.000, 0.247, 0.322], // Teal de marca (#003F52)
[0.780, 0.280, 0.400] // Rosa carmesí (#C74766) [0.780, 0.280, 0.420] // Carmesí (#C7476B)
]; ];
} }
} }
@@ -37,8 +35,7 @@ let targetColor = brandColors[1];
let transitionProgress = 0; let transitionProgress = 0;
const transitionSpeed = 0.008; const transitionSpeed = 0.008;
// Observar cambios de tema: actualiza paleta y reinicia transición de color. // Observador para detectar el switch de tema en tiempo real
// El fondo CSS cambia automáticamente (el canvas es transparente, el fondo del <html> se ve a través).
const themeObserver = new MutationObserver(() => { const themeObserver = new MutationObserver(() => {
brandColors = getBrandColors(); brandColors = getBrandColors();
currentColor = brandColors[0]; currentColor = brandColors[0];
@@ -59,18 +56,17 @@ function lerpColor(colorA, colorB, t) {
let canvas = document.getElementById("fluidCanvas"); let canvas = document.getElementById("fluidCanvas");
if (!canvas) { if (!canvas) {
console.error("ERROR: No se encontró el canvas con id 'fluidCanvas'"); console.error("ERROR: No se encontró el canvas con id 'fluidCanvas'");
} else { }
canvas.width = window.innerWidth; canvas.width = window.innerWidth;
canvas.height = window.innerHeight; canvas.height = window.innerHeight;
}
// ===== CONTEXTO WEBGL ===== // ===== CONTEXTO WEBGL TRANSPARENTE =====
let pointers = []; let pointers = [];
function getWebGLContext(canvas) { function getWebGLContext(canvas) {
let params = { let params = {
alpha: true, // Canvas transparente: el fondo CSS se ve a través alpha: true, // Transparente para respetar el fondo CSS
premultipliedAlpha: false, // CLAVE: colores sin premultiplicar para composición correcta premultipliedAlpha: false, // Clave para composición limpia sobre el fondo
depth: false, depth: false,
stencil: false, stencil: false,
antialias: false antialias: false
@@ -87,7 +83,6 @@ function getWebGLContext(canvas) {
support_linear_float = gl.getExtension("OES_texture_float_linear"); support_linear_float = gl.getExtension("OES_texture_float_linear");
} }
// ✅ CLAVE: Fondo transparente para que se vea el color del body
gl.clearColor(0.0, 0.0, 0.0, 0.0); gl.clearColor(0.0, 0.0, 0.0, 0.0);
let internalFormat = isWebGL2 ? gl.RGBA16F : gl.RGBA; let internalFormat = isWebGL2 ? gl.RGBA16F : gl.RGBA;
@@ -125,7 +120,7 @@ function pointerPrototype() {
} }
pointers.push(new pointerPrototype()); pointers.push(new pointerPrototype());
// ===== SHADERS ===== // ===== SHADERS BASE =====
let GLProgram = (function () { let GLProgram = (function () {
function GLProgram(vertexShader, fragmentShader) { 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");
@@ -165,6 +160,7 @@ let clearShader = compileShader(
"precision highp float; precision mediump sampler2D; varying vec2 vUv; uniform sampler2D uTexture; uniform float value; void main () { gl_FragColor = value * texture2D(uTexture, vUv); }" "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 ADAPTATIVO AL FONDO Y TEMA
let displayShader = compileShader( let displayShader = compileShader(
gl.FRAGMENT_SHADER, gl.FRAGMENT_SHADER,
`precision highp float; `precision highp float;
@@ -175,24 +171,22 @@ let displayShader = compileShader(
void main () { void main () {
vec4 c = texture2D(uTexture, vUv); vec4 c = texture2D(uTexture, vUv);
float maxC = max(c.r, max(c.g, c.b)); float density = max(c.r, max(c.g, c.b));
if (maxC < 0.001) {
if (density < 0.001) {
gl_FragColor = vec4(0.0); gl_FragColor = vec4(0.0);
return; return;
} }
// Normalizamos el tono cromático para conservar la saturación original
vec3 nColor = c.rgb / maxC;
if (uIsDark > 0.5) { if (uIsDark > 0.5) {
// MODO OSCURO: fluido con mayor presencia y brillo // MODO OSCURO: Núcleo luminoso y bordes de humo orgánico
float alpha = clamp(maxC * 2.5, 0.0, 0.70); float alpha = clamp(density * 2.2, 0.0, 0.90);
vec3 glow = clamp(nColor * 1.2, 0.0, 1.0); vec3 rgb = c.rgb * (1.15 + density * 1.3);
gl_FragColor = vec4(glow, alpha); gl_FragColor = vec4(clamp(rgb, 0.0, 1.0), alpha);
} else { } else {
// MODO CLARO: tinte traslúcido suave que no satura el fondo sage-light // MODO CLARO: Tinte de acuarela suave que no ensucia el fondo claro
float alpha = clamp(maxC * 1.5, 0.0, 0.35); float alpha = clamp(density * 1.35, 0.0, 0.45);
gl_FragColor = vec4(nColor, alpha); gl_FragColor = vec4(c.rgb, alpha);
} }
}` }`
); );
@@ -217,6 +211,7 @@ let divergenceShader = compileShader(
"precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; vec2 sampleVelocity (in vec2 uv) { vec2 multiplier = vec2(1.0, 1.0); if (uv.x < 0.0) { uv.x = 0.0; multiplier.x = -1.0; } if (uv.x > 1.0) { uv.x = 1.0; multiplier.x = -1.0; } if (uv.y < 0.0) { uv.y = 0.0; multiplier.y = -1.0; } if (uv.y > 1.0) { uv.y = 1.0; multiplier.y = -1.0; } return multiplier * texture2D(uVelocity, uv).xy; } void main () { float L = sampleVelocity(vL).x; float R = sampleVelocity(vR).x; float T = sampleVelocity(vT).y; float B = sampleVelocity(vB).y; float div = 0.5 * (R - L + T - B); gl_FragColor = vec4(div, 0.0, 0.0, 1.0); }" "precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; vec2 sampleVelocity (in vec2 uv) { vec2 multiplier = vec2(1.0, 1.0); if (uv.x < 0.0) { uv.x = 0.0; multiplier.x = -1.0; } if (uv.x > 1.0) { uv.x = 1.0; multiplier.x = -1.0; } if (uv.y < 0.0) { uv.y = 0.0; multiplier.y = -1.0; } if (uv.y > 1.0) { uv.y = 1.0; multiplier.y = -1.0; } return multiplier * texture2D(uVelocity, uv).xy; } void main () { float L = sampleVelocity(vL).x; float R = sampleVelocity(vR).x; float T = sampleVelocity(vT).y; float B = sampleVelocity(vB).y; float div = 0.5 * (R - L + T - B); gl_FragColor = vec4(div, 0.0, 0.0, 1.0); }"
); );
// RESTAURACIÓN EXACTA DE LA FÍSICA DE COPIA (Sin inversión de ejes)
let curlShader = compileShader( let curlShader = compileShader(
gl.FRAGMENT_SHADER, gl.FRAGMENT_SHADER,
"precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; void main () { float L = texture2D(uVelocity, vL).y; float R = texture2D(uVelocity, vR).y; float T = texture2D(uVelocity, vT).x; float B = texture2D(uVelocity, vB).x; float vorticity = R - L - T + B; gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0); }" "precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; void main () { float L = texture2D(uVelocity, vL).y; float R = texture2D(uVelocity, vR).y; float T = texture2D(uVelocity, vT).x; float B = texture2D(uVelocity, vB).x; float vorticity = R - L - T + B; gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0); }"
@@ -321,18 +316,16 @@ function splat(x, y, dx, dy, color) {
velocity.swap(); velocity.swap();
gl.uniform1i(splatProgram.uniforms.uTarget, density.first[2]); gl.uniform1i(splatProgram.uniforms.uTarget, density.first[2]);
const isDark = document.documentElement.getAttribute('data-theme') === 'dark'; gl.uniform3f(splatProgram.uniforms.color, color[0] * 0.35, color[1] * 0.35, color[2] * 0.35);
const densityIntensity = isDark ? 0.65 : 0.45;
gl.uniform3f(splatProgram.uniforms.color, color[0] * densityIntensity, color[1] * densityIntensity, color[2] * densityIntensity);
blit(density.second[1]); blit(density.second[1]);
density.swap(); density.swap();
} }
// ===== RESIZE ===== // ===== RESIZE SIN DESFASES =====
function resizeCanvas() { function resizeCanvas() {
if (canvas.width !== window.innerWidth || canvas.height !== window.innerHeight) { if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) {
canvas.width = window.innerWidth; canvas.width = canvas.clientWidth;
canvas.height = window.innerHeight; canvas.height = canvas.clientHeight;
initFramebuffers(); initFramebuffers();
} }
} }
@@ -343,7 +336,8 @@ let count = 0;
// ===== DETECTAR ELEMENTOS DE TEXTO ===== // ===== DETECTAR ELEMENTOS DE TEXTO =====
function isMouseOverTextElement(target) { function isMouseOverTextElement(target) {
const textSelectors = [ const textSelectors = [
'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'a', 'span', 'button', '.btn', '.card-content', '.hero-content' 'p', '.hero-content p', 'h1', 'h2', 'h3', 'h4', 'h5', '.hero-content h1',
'.hero-content h2', '.eyebrow', 'a', 'button', '.btn', '.servicio-item', '.plan-card'
]; ];
for (const selector of textSelectors) { for (const selector of textSelectors) {
if (target.closest(selector)) return true; if (target.closest(selector)) return true;
@@ -351,8 +345,22 @@ function isMouseOverTextElement(target) {
return false; return false;
} }
// ===== EVENTOS CON COLORES DE MARCA ===== // ===== CONTROL DE MOUSE CENTRADO Y SIMÉTRICO =====
let isFirstMove = true;
document.addEventListener("mousemove", function (e) { document.addEventListener("mousemove", function (e) {
const rect = canvas.getBoundingClientRect();
const currentX = e.clientX - rect.left;
const currentY = e.clientY - rect.top;
// Evita el salto o raya diagonal al entrar por primera vez
if (isFirstMove) {
pointers[0].x = currentX;
pointers[0].y = currentY;
isFirstMove = false;
return;
}
const overText = isMouseOverTextElement(e.target); const overText = isMouseOverTextElement(e.target);
count++; count++;
@@ -371,15 +379,20 @@ document.addEventListener("mousemove", function (e) {
pointers[0].down = true; pointers[0].down = true;
pointers[0].color = colorArr; pointers[0].color = colorArr;
pointers[0].moved = pointers[0].down; pointers[0].moved = true;
// ✅ CLAVE: Reducir la fuerza del fluido sobre texto para no dificultar la lectura // Multiplicador simétrico de fluid - copia.js (10.0 en fondo, 8.0 en texto)
const multiplier = overText ? 4.0 : 10.0; const multiplier = overText ? 8.0 : 10.0;
pointers[0].dx = (e.clientX - pointers[0].x) * multiplier; pointers[0].dx = (currentX - pointers[0].x) * multiplier;
pointers[0].dy = (e.clientY - pointers[0].y) * multiplier; pointers[0].dy = (currentY - pointers[0].y) * multiplier;
pointers[0].x = e.clientX; pointers[0].x = currentX;
pointers[0].y = e.clientY; pointers[0].y = currentY;
});
window.addEventListener("mouseleave", function () {
isFirstMove = true;
pointers[0].moved = false;
}); });
canvas.addEventListener("touchmove", function (e) { canvas.addEventListener("touchmove", function (e) {
@@ -399,19 +412,23 @@ canvas.addEventListener("touchmove", function (e) {
count = 0; count = 0;
} }
const rect = canvas.getBoundingClientRect();
for (let i = 0, len = touches.length; i < len; i++) { for (let i = 0, len = touches.length; i < len; i++) {
if (i >= pointers.length) pointers.push(new pointerPrototype()); if (i >= pointers.length) pointers.push(new pointerPrototype());
let pointer = pointers[i]; let pointer = pointers[i];
let touchX = touches[i].clientX - rect.left;
let touchY = touches[i].clientY - rect.top;
pointer.id = touches[i].identifier; pointer.id = touches[i].identifier;
pointer.down = true; pointer.down = true;
pointer.color = colorArr; pointer.color = colorArr;
pointer.moved = true; pointer.moved = true;
pointer.dx = (touches[i].pageX - pointer.x) * 10.0; pointer.dx = (touchX - pointer.x) * 10.0;
pointer.dy = (touches[i].pageY - pointer.y) * 10.0; pointer.dy = (touchY - pointer.y) * 10.0;
pointer.x = touches[i].pageX; pointer.x = touchX;
pointer.y = touches[i].pageY; pointer.y = touchY;
} }
}, { passive: false }); }, false);
// ===== LOOP PRINCIPAL ===== // ===== LOOP PRINCIPAL =====
let lastTime = Date.now(); let lastTime = Date.now();
@@ -495,10 +512,13 @@ function update() {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
displayProgram.bind(); displayProgram.bind();
gl.uniform1i(displayProgram.uniforms.uTexture, density.first[2]); gl.uniform1i(displayProgram.uniforms.uTexture, density.first[2]);
// Informar al shader si estamos en modo oscuro
const isDarkTheme = document.documentElement.getAttribute('data-theme') === 'dark'; const isDarkTheme = document.documentElement.getAttribute('data-theme') === 'dark';
if (displayProgram.uniforms.uIsDark !== undefined) { if (displayProgram.uniforms.uIsDark !== undefined) {
gl.uniform1f(displayProgram.uniforms.uIsDark, isDarkTheme ? 1.0 : 0.0); gl.uniform1f(displayProgram.uniforms.uIsDark, isDarkTheme ? 1.0 : 0.0);
} }
blit(null); blit(null);
requestAnimationFrame(update); requestAnimationFrame(update);
@@ -506,55 +526,9 @@ function update() {
update(); update();
// ===== REDIMENSIONAR =====
/* captura del movimiento del mouse*/
let isFirstMove = true;
document.addEventListener("mousemove", function (e) {
if (isFirstMove) {
pointers[0].x = e.clientX;
pointers[0].y = e.clientY;
isFirstMove = false;
return;
}
const overText = isMouseOverTextElement(e.target);
count++;
if (count > 1) {
transitionProgress += transitionSpeed;
if (transitionProgress >= 1) {
transitionProgress = 0;
let currentIndex = brandColors.indexOf(currentColor);
let nextIndex = (currentIndex + 1) % brandColors.length;
currentColor = targetColor;
targetColor = brandColors[nextIndex];
}
colorArr = lerpColor(currentColor, targetColor, transitionProgress);
count = 0;
}
pointers[0].down = true;
pointers[0].color = colorArr;
pointers[0].moved = true;
// Fuerza balanceada sobre el texto y sobre el fondo
const multiplier = overText ? 4.0 : 8.0;
pointers[0].dx = (e.clientX - pointers[0].x) * multiplier;
pointers[0].dy = (e.clientY - pointers[0].y) * multiplier;
pointers[0].x = e.clientX;
pointers[0].y = e.clientY;
});
window.addEventListener("mouseleave", function () {
isFirstMove = true;
pointers[0].moved = false;
});
// ===== REDIMENSIONAR AL CAMBIAR TAMAÑO DE VENTANA =====
window.addEventListener("resize", function() { window.addEventListener("resize", function() {
canvas.width = window.innerWidth; canvas.width = canvas.clientWidth;
canvas.height = window.innerHeight; canvas.height = canvas.clientHeight;
initFramebuffers(); initFramebuffers();
}); });
+7 -3
View File
@@ -10,6 +10,9 @@
<link rel="stylesheet" href="style/servicios.css"> <link rel="stylesheet" href="style/servicios.css">
</head> </head>
<body> <body>
<div id="fluid-bg" aria-hidden="true">
<canvas id="fluidCanvas"></canvas>
</div>
<div id="menu-container"></div> <div id="menu-container"></div>
<main> <main>
@@ -18,7 +21,7 @@
<div class="servicios-hero-content"> <div class="servicios-hero-content">
<span class="servicios-hero-tag">Nuestros servicios</span> <span class="servicios-hero-tag">Nuestros servicios</span>
<h1 class="servicios-hero-title">Soluciones a medida para cada etapa de tu marca</h1> <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> <a href="#servicios-selector" class="btn btn-primary servicios-hero-cta">Explorar servicios</a>
</div> </div>
</section> </section>
@@ -254,7 +257,7 @@
<div class="panel-footer"> <div class="panel-footer">
<div class="panel-precio"> <div class="panel-precio">
<span class="precio-label">Desde</span> <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> </div>
<a href="contacto.html?servicio=paid" class="btn btn-secondary panel-cta">Cotizar este servicio</a> <a href="contacto.html?servicio=paid" class="btn btn-secondary panel-cta">Cotizar este servicio</a>
</div> </div>
@@ -304,7 +307,7 @@
<h2 class="servicios-cta-titulo">¿No sabés cuál servicio necesitás?</h2> <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> <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"> <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> <a href="contacto.html" class="btn btn-cta-secondary">Hablemos directamente</a>
</div> </div>
</div> </div>
@@ -318,5 +321,6 @@
<script src="scripts/main.js"></script> <script src="scripts/main.js"></script>
<script src="scripts/servicios.js"></script> <script src="scripts/servicios.js"></script>
<script src="scripts/fluid.js"></script>
</body> </body>
</html> </html>
+20 -5
View File
@@ -69,6 +69,7 @@
margin: 0 auto; margin: 0 auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center;
gap: var(--spacing-sm); gap: var(--spacing-sm);
} }
@@ -77,6 +78,7 @@
display: flex; display: flex;
gap: var(--spacing-sm); gap: var(--spacing-sm);
align-items: center; align-items: center;
justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -250,8 +252,9 @@
/* Info de resultados */ /* Info de resultados */
.results-info-compact { .results-info-compact {
display: flex; display: flex;
justify-content: space-between; justify-content: center;
align-items: center; align-items: center;
gap: var(--spacing-sm);
font-family: var(--font-small); font-family: var(--font-small);
font-size: 0.85rem; font-size: 0.85rem;
color: var(--text-muted); color: var(--text-muted);
@@ -810,17 +813,22 @@
gap: var(--spacing-sm); gap: var(--spacing-sm);
position: relative; position: relative;
z-index: 1; z-index: 1;
justify-content: center;
} }
.newsletter-form input { .newsletter-form input {
flex: 1; flex: 1;
padding: 0.85rem 1.2rem; max-width: 320px; /* Limitar ancho para que parezca botón */
border: none; padding: 0.85rem 1.5rem;
border: 1.5px solid rgba(255, 255, 255, 0.3);
border-radius: 999px; border-radius: 999px;
font-family: var(--font-body); font-family: var(--font-body);
font-size: 0.95rem; font-size: 0.95rem;
background-color: rgba(255, 255, 255, 0.95); font-weight: 500;
color: var(--text-primary); background-color: rgba(255, 255, 255, 0.15); /* Fondo sutil tipo botón */
color: #ffffff; /* ← CLAVE: Texto blanco siempre visible */
backdrop-filter: blur(4px);
transition: all 0.3s ease;
} }
.newsletter-form input::placeholder { .newsletter-form input::placeholder {
@@ -1052,10 +1060,17 @@
.newsletter-form { .newsletter-form {
flex-direction: column; flex-direction: column;
align-items: center;
}
.newsletter-form input {
max-width: 100%;
width: 100%;
} }
.newsletter-form .btn { .newsletter-form .btn {
width: 100%; width: 100%;
max-width: 320px;
} }
} }
+1
View File
@@ -1862,6 +1862,7 @@ main {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background: transparent; background: transparent;
} }
.hero-section, .hero-section,
+3 -3
View File
@@ -510,11 +510,11 @@
.caso-tag { .caso-tag {
font-family: var(--font-small); font-family: var(--font-small);
font-size: 0.7rem; font-size: 0.85rem;
font-weight: 600; font-weight: 500;
letter-spacing: 0.5px; letter-spacing: 0.5px;
text-transform: uppercase; text-transform: uppercase;
color: var(--brand-teal); color: #006d8f;
display: inline-block; display: inline-block;
margin-bottom: var(--spacing-xs); margin-bottom: var(--spacing-xs);
} }
+3
View File
@@ -0,0 +1,3 @@
<?php
echo "¡PHP funciona!";
?>
+20
View File
@@ -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>