Este proyecto forma parte del Programa de Innovación Edith Alanis .

Se extiende un especial agradecimiento al “amigo especial” que motivó la creación de este proyecto, cuya inspiración dio origen a esta iniciativa de acompañamiento mediante mensajes escritos.

ACOMPAÑAMIENTO POR ESCRITO

Un mensaje electrónico de apoyo gratuito para ti

¿Necesitas que alguien te escriba?

A veces unas palabras pueden atravesar la distancia y llegar justo donde más se necesitan.

Puedes contarnos lo que estás viviendo. Tu solicitud será asignada a una persona que preparará un mensaje especialmente para ti.

Solicitar mi mensaje gratuito
Mensaje de apoyo
🌹 🌹 🌹 🌹 🌹 🌹

Un espacio para escribir y ser escuchado

Este servicio ofrece acompañamiento mediante mensajes escritos. Puedes utilizar tu nombre o un seudónimo y compartir únicamente aquello que desees expresar.

✉️ Escribe

Cuéntanos aquello que quieras compartir.

🌹 Recibe compañía

Tu solicitud será asignada a uno de nuestros asesores.

💌 Recibe una respuesta

Obtendrás un mensaje preparado especialmente para ti.

MENSAJE GRATUITO

¿Por qué te gustaría recibir un mensaje de apoyo?

Puedes elegir una o varias opciones.

Importante: no se admiten mensajes que describan o soliciten actividades sexuales. Para ser enviado, tu mensaje debe finalizar con: “De antemano muchas gracias por responder.”

PROCESO

¿Cómo funciona?

1 Escribes

Comparte aquello que quieras expresar.

2 Recibes un folio

Tu solicitud queda registrada.

3 Se asigna

Uno de nuestros asesores recibe tu mensaje.

4 Recibes respuesta

Se prepara un mensaje para ti.

❤️

¿Deseas apoyar este proyecto?

Este servicio es gratuito. Si deseas contribuir voluntariamente para ayudarnos a continuar enviando mensajes de apoyo, puedes realizar una donación.

La donación es completamente opcional y no condiciona la atención ni la respuesta a tu mensaje.

$ MXN

Selecciona la cantidad que deseas donar.

La conexión con PayPal será habilitada próximamente.
CONOCE MÁS

Otros proyectos de Edith Alanis

Acceso de asesores

Cada asesor podrá consultar únicamente los mensajes que le hayan sido asignados.

2. Sustituye TODO styles.css por esto * { box-sizing: border-box; } html { scroll-behavior: smooth; } body { margin: 0; font-family: Arial, Helvetica, sans-serif; background: linear-gradient(180deg, #fffafa 0%, #fff 35%, #fff7f7 100%); color: #30272a; line-height: 1.6; } a { color: inherit; } .topbar { position: sticky; top: 0; z-index: 100; min-height: 68px; padding: 12px 5%; background: rgba(255,255,255,.97); border-bottom: 1px solid #eadfe2; display: flex; align-items: center; justify-content: space-between; gap: 25px; box-shadow: 0 3px 15px rgba(70,30,40,.06); } .marca { font-family: Georgia, serif; font-weight: bold; color: #761f36; font-size: 17px; } .navlinks { display: flex; flex-wrap: wrap; gap: 20px; } .navlinks a { text-decoration: none; font-size: 14px; font-weight: bold; color: #514248; } .navlinks a:hover { color: #a41e45; } .institucional { text-align: center; padding: 18px 8%; background: #761f36; color: white; } .institucional p { max-width: 1050px; margin: 3px auto; } .institucional a { color: white; font-weight: bold; } .agradecimiento { font-size: 14px; opacity: .95; } .hero { max-width: 1250px; min-height: 590px; margin: auto; padding: 65px 6% 50px; display: grid; grid-template-columns: 1.05fr .95fr; align-items: center; gap: 50px; } .etiqueta, .encabezado-seccion > span { display: inline-block; letter-spacing: 2px; font-size: 12px; font-weight: bold; color: #a21d46; margin-bottom: 10px; } .hero h1 { margin: 0 0 18px; font-family: Georgia, "Times New Roman", serif; font-size: clamp(40px, 5vw, 68px); line-height: 1.05; color: #4d1830; } .hero h2 { font-size: 26px; margin: 5px 0 15px; color: #7e2440; } .hero p { font-size: 18px; max-width: 670px; } .hero .principal { font-family: Georgia, serif; font-size: 22px; color: #514146; } .hero-imagen img { width: 100%; max-height: 500px; object-fit: contain; filter: drop-shadow(0 18px 20px rgba(67,25,36,.16)); } .btn { display: inline-block; border: none; border-radius: 8px; background: #8c2343; color: white; font-size: 16px; font-weight: bold; padding: 15px 26px; text-decoration: none; cursor: pointer; transition: .2s; box-shadow: 0 7px 18px rgba(110,28,53,.16); } .btn:hover { transform: translateY(-2px); background: #701a35; } main { max-width: 1150px; margin: auto; padding: 0 20px 60px; } .rosas { text-align: center; font-size: 25px; letter-spacing: 10px; margin: 10px 0 25px; } .card { margin: 30px auto; padding: 42px; border-radius: 18px; background: white; border: 1px solid #eee3e6; box-shadow: 0 12px 35px rgba(70,35,45,.07); } .card h2 { font-family: Georgia, serif; color: #641c35; font-size: 32px; margin-top: 0; } .presentacion { text-align: center; } .presentacion > p { max-width: 820px; margin: 0 auto 35px; font-size: 17px; } .beneficios { display: grid; grid-template-columns: repeat(3,1fr); gap: 20px; } .beneficios > div { padding: 25px 18px; background: #fff9fa; border-radius: 12px; } .beneficios span { font-size: 35px; display: block; margin-bottom: 10px; } .beneficios strong { display: block; color: #70203a; font-size: 18px; } .encabezado-seccion { text-align: center; margin-bottom: 30px; } .encabezado-seccion h2 { margin-bottom: 5px; } .choices { display: grid; grid-template-columns: repeat(2,1fr); gap: 10px 15px; margin-bottom: 35px; } .choice { display: flex; align-items: flex-start; gap: 10px; min-height: 55px; padding: 13px 15px; border: 1px solid #eadfe2; border-radius: 9px; background: #fffafa; cursor: pointer; transition: .15s; } .choice:hover { border-color: #bd7589; background: #fff4f6; } .choice input { margin-top: 5px; } .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; } form label { display: block; font-weight: bold; margin-bottom: 18px; color: #4d3940; } input, textarea { display: block; width: 100%; margin-top: 7px; padding: 13px 14px; border: 1px solid #d6c7cc; border-radius: 8px; font: inherit; color: #30272a; background: white; } input:focus, textarea:focus { outline: none; border-color: #9e2a4c; box-shadow: 0 0 0 3px rgba(158,42,76,.09); } textarea { resize: vertical; } .aviso { padding: 18px 20px; margin: 15px 0 20px; background: #fff6e8; border-left: 5px solid #d89b37; border-radius: 7px; color: #5b4630; } .acepto { display: flex !important; align-items: flex-start; gap: 10px; font-weight: normal !important; padding: 15px; background: #f8f8f8; border-radius: 8px; } .acepto input { width: auto; margin-top: 5px; } .btn-enviar { width: 100%; margin-top: 5px; font-size: 18px; } #estado { margin: 20px 0 0; padding: 0; font-weight: bold; text-align: center; } #estado.ok { padding: 16px; color: #176533; background: #ecf8ef; border-radius: 8px; } #estado.error { padding: 16px; color: #a32323; background: #fff0f0; border-radius: 8px; } .steps { display: grid; grid-template-columns: repeat(4,1fr); gap: 18px; } .steps > div { text-align: center; padding: 20px 15px; border-radius: 12px; background: #fff8f9; } .steps b { display: flex; align-items: center; justify-content: center; width: 45px; height: 45px; margin: 0 auto 12px; border-radius: 50%; background: #842341; color: white; font-size: 20px; } .steps strong { display: block; color: #641c35; } .steps p { font-size: 14px; margin-bottom: 0; } .donar { text-align: center; background: linear-gradient(135deg,#fff 0%,#fff4f6 100%); border: 2px solid #f0d6dd; } .corazon { font-size: 50px; } .donar > p { max-width: 760px; margin-left: auto; margin-right: auto; } .donacion-aclaracion { font-weight: bold; color: #75213b; } .montos { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin: 30px 0 20px; } .monto { border: 2px solid #8c2343; background: white; color: #8c2343; border-radius: 8px; padding: 12px 20px; font-size: 16px; font-weight: bold; cursor: pointer; } .monto:hover, .monto.activo { background: #8c2343; color: white; } .otra-cantidad { max-width: 400px; margin: 20px auto; } .otra-cantidad label { font-weight: bold; } .cantidad-input { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px; margin-top: 7px; padding: 0 14px; background: white; border: 1px solid #d7c7cc; border-radius: 8px; } .cantidad-input input { border: none; margin: 0; box-shadow: none; } .paypal { margin-top: 10px; min-width: 240px; } .donar small { display: block; margin-top: 15px; color: #796b70; } .enlaces-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; } .enlace-proyecto { padding: 28px; border-radius: 12px; text-decoration: none; background: #faf7f8; border: 1px solid #eadfe2; transition: .2s; } .enlace-proyecto:hover { transform: translateY(-3px); border-color: #a84c68; } .enlace-proyecto strong { display: block; font-family: Georgia, serif; color: #681d36; font-size: 21px; margin-bottom: 12px; } .enlace-proyecto span { color: #8e2948; font-weight: bold; } .asesor-card { text-align: center; } .secondary { background: #55505a; } footer { text-align: center; padding: 40px 20px; background: #411526; color: white; } .footer-titulo { font-family: Georgia, serif; font-size: 20px; font-weight: bold; } .footer-links { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin: 15px 0; } .footer-links a { color: white; } .petalo { position: fixed; top: -50px; z-index: 3; pointer-events: none; animation-name: caer; animation-timing-function: linear; animation-fill-mode: forwards; } @keyframes caer { 0% { transform: translate(0,-30px) rotate(0deg); opacity: .8; } 100% { transform: translate(var(--x),110vh) rotate(420deg); opacity: .1; } } @media(max-width:850px) { .topbar { position: relative; flex-direction: column; } .navlinks { justify-content: center; } .hero { grid-template-columns: 1fr; text-align: center; padding-top: 45px; } .hero p { margin-left: auto; margin-right: auto; } .hero-imagen { order: -1; } .hero-imagen img { max-height: 350px; } .choices, .grid, .beneficios, .steps, .enlaces-grid { grid-template-columns: 1fr; } .card { padding: 28px 20px; } } @media(max-width:500px) { .hero h1 { font-size: 40px; } .hero h2 { font-size: 22px; } .navlinks { gap: 10px 15px; } .rosas { letter-spacing: 3px; } } 3. Sustituye TODO app.js por esta versión Esta conserva Supabase y agrega la selección de donaciones. const SUPABASE_URL = "https://mmjsgrdujjomopefkzeq.supabase.co"; const SUPABASE_KEY = "sb_publishable__UgjBRf9uxweu8yEFQNvbw_wo10XxZY"; const frase = "de antemano muchas gracias por responder"; const prohibidos = [ /\b(sexo|sexual|pornograf|coito|penetraci[oó]n|masturbaci[oó]n|orgasmo)\b/i, /\b(er[oó]tico|er[oó]tica)\b/i ]; document .getElementById("f") .addEventListener("submit", async (e) => { e.preventDefault(); const estado = document.getElementById("estado"); const mensaje = document.getElementById("mensaje").value.trim(); const nombre = document.getElementById("nombre").value.trim(); const correo = document.getElementById("correo").value.trim(); const seleccionados = [ ...document.querySelectorAll( 'input[name="motivo"]:checked' ) ]; if (!seleccionados.length) { estado.className = "error"; estado.textContent = "Selecciona por lo menos un motivo."; return; } if (prohibidos.some((r) => r.test(mensaje))) { estado.className = "error"; estado.textContent = "El mensaje contiene contenido no permitido y no puede enviarse."; document.getElementById("mensaje").value = ""; return; } const mensajeNormalizado = mensaje .toLocaleLowerCase("es-MX") .replace(/[.\s]+$/g, ""); if (!mensajeNormalizado.endsWith(frase)) { estado.className = "error"; estado.textContent = 'Para enviarlo, finaliza con: “De antemano muchas gracias por responder.”'; return; } estado.className = ""; estado.textContent = "Enviando solicitud..."; const ahora = Date.now(); const numero = String(ahora).slice(-8); const folio = "MAP-" + numero; const asesor = (ahora % 10) + 1; const motivos = seleccionados .map((x) => x.value) .join(" | "); const datos = { folio: folio, nombre: nombre, correo: correo, motivos: motivos, mensaje: mensaje, asesor: asesor, estado: "pendiente" }; try { const respuesta = await fetch( `${SUPABASE_URL}/rest/v1/Solicitudes`, { method: "POST", headers: { "Content-Type": "application/json", "apikey": SUPABASE_KEY, "Authorization": `Bearer ${SUPABASE_KEY}`, "Prefer": "return=minimal" }, body: JSON.stringify(datos) } ); if (!respuesta.ok) { const error = await respuesta.text(); console.error( "Error Supabase:", error ); throw new Error( "No se pudo guardar la solicitud." ); } estado.className = "ok"; estado.textContent = `Solicitud recibida correctamente. ` + `Número de mensaje: ${folio}. ` + `Asignado al Asesor ` + `${String(asesor).padStart(2,"0")}.`; e.target.reset(); } catch (error) { console.error(error); estado.className = "error"; estado.textContent = "No fue posible enviar el mensaje en este momento. Inténtalo nuevamente."; } }); let cantidadDonacion = null; document .querySelectorAll(".monto") .forEach((boton) => { boton.addEventListener( "click", () => { document .querySelectorAll(".monto") .forEach((b) => b.classList.remove("activo") ); boton.classList.add("activo"); cantidadDonacion = Number(boton.dataset.monto); document .getElementById("donacionOtro") .value = ""; document .getElementById("montoSeleccionado") .textContent = `Donación seleccionada: $${cantidadDonacion} MXN`; } ); }); document .getElementById("donacionOtro") .addEventListener( "input", (e) => { document .querySelectorAll(".monto") .forEach((b) => b.classList.remove("activo") ); cantidadDonacion = Number(e.target.value); if (cantidadDonacion > 0) { document .getElementById("montoSeleccionado") .textContent = `Donación seleccionada: $${cantidadDonacion} MXN`; } else { document .getElementById("montoSeleccionado") .textContent = "Selecciona la cantidad que deseas donar."; } } ); document .getElementById("btnDonar") .addEventListener( "click", () => { if (!cantidadDonacion || cantidadDonacion <= 0) { alert( "Selecciona una cantidad para donar." ); return; } alert( `Has seleccionado donar $${cantidadDonacion} MXN. ` + `La conexión con PayPal será habilitada próximamente.` ); } ); setInterval(() => { const p = document.createElement("span"); p.className = "petalo"; p.textContent = "🌹"; p.style.left = Math.random() * 100 + "vw"; p.style.setProperty( "--x", Math.random() * 160 - 80 + "px" ); p.style.animationDuration = 7 + Math.random() * 5 + "s"; document.body.appendChild(p); setTimeout( () => p.remove(), 12500 ); }, 1200); Haz los tres Commit changes, uno por cada archivo. Después presiona Ctrl + F5 en la página publicada. Lo importante: no debes cambiar nada en Supabase. Esta nueva versión utiliza exactamente la misma tabla Solicitudes que ya comprobamos que funciona. Cuando termines, mándame una captura de la parte superior de la nueva página. Ahí revisamos el resultado visual y, si hace falta, la hacemos todavía más elegante.