feat: sitio comercial FSPM con micro CRM interno

Sitio público orientado a venta consultiva e implementación de las
recomendaciones de la auditoría de marca y mercado:

- Inicio con tres rutas (industria, riesgo, cumplimiento) y clasificador
  de riesgo en el héroe, contra el hallazgo de que el visitante tenía que
  inferir qué solución le correspondía.
- Cinco páginas por segmento prioritario y catálogo comparable por clase
  de fuego, capacidad y agente.
- Los claims sin evidencia por modelo quedan aislados y se presentan como
  compromiso de documentación, nunca como característica del producto.
- SEO técnico completo: metadatos por página, sitemap derivado de los
  datos, JSON-LD, iconos y tarjeta social generadas.

Micro CRM:

- Captura por formulario embebido y por widget de WhatsApp que registra
  antes de abrir la conversación.
- Atribución de primer toque que sobrevive a la navegación.
- Deduplicación de contacto; un mismo contacto acumula oportunidades.
- Motor de asignación por reglas con reparto por turno de respaldo.
- Panel con dos roles de alcance distinto, tablero analítico, bitácora,
  pedidos y reglas. No enlazado desde el sitio público y con noindex.

Empaquetado en Docker multietapa con la base de demostración horneada en
la imagen y el volumen de datos separado, para que los leads capturados
sobrevivan a los redespliegues.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Uriel Jareth
2026-08-28 00:07:20 -06:00
co-authored by Claude Opus 5
parent 122e06a4bb
commit 01b817d098
649 changed files with 26690 additions and 0 deletions
@@ -0,0 +1,316 @@
import type { Metadata } from "next";
import Link from "next/link";
import { AVISO_DEMO, EMPRESA, SITIO_URL } from "@/data/empresa";
/**
* /aviso-de-privacidad
*
* Reproduce, reordenado para poder leerse, el aviso publicado por FSPM en su
* sitio público, más una sección que declara qué recaba realmente el formulario
* de esta demo. Lo que no estaba en la fuente no se agregó, y la versión
* definitiva es siempre la que publique la empresa.
*/
const TITULO = "Aviso de privacidad";
const DESCRIPCION = `Aviso de privacidad de ${EMPRESA.razonSocial}: responsable, finalidades del tratamiento, transferencias, medidas de seguridad y ejercicio de derechos ARCO.`;
export const metadata: Metadata = {
title: TITULO,
description: DESCRIPCION,
alternates: { canonical: `${SITIO_URL}/aviso-de-privacidad` },
robots: { index: true, follow: true },
openGraph: {
title: `${TITULO} | ${EMPRESA.nombreCorto}`,
description: DESCRIPCION,
url: `${SITIO_URL}/aviso-de-privacidad`,
},
};
const CORREO_ARCO = "[email protected]";
const CAMPOS_FORMULARIO = [
{ campo: "Nombre", uso: "Identificarte y dirigirnos a ti por tu nombre en el seguimiento." },
{ campo: "Correo electrónico", uso: "Enviarte la respuesta técnica y la propuesta." },
{ campo: "Teléfono", uso: "Contactarte cuando la solicitud requiere una llamada." },
{ campo: "Empresa y puesto", uso: "Entender quién decide y con qué alcance, para no dar una respuesta genérica." },
{ campo: "Ciudad o estado", uso: "Ubicar la instalación y saber qué requisitos locales pueden aplicar." },
{ campo: "Tipo de operación y superficie", uso: "Interpretar el escenario y proponer una configuración." },
{ campo: "Clases de fuego declaradas", uso: "Clasificar el riesgo que tú mismo declaras en el selector." },
{ campo: "Urgencia y mensaje", uso: "Priorizar la atención y conocer el requerimiento en tus palabras." },
{
campo: "Datos de origen de la visita",
uso: "Saber por qué campaña o página llegaste, para medir qué contenido resuelve dudas reales.",
},
];
export default function PaginaAviso() {
return (
<>
{/* ---------- encabezado ---------- */}
<section className="bg-ink pt-12 pb-10 sm:pt-16 sm:pb-12">
<div className="shell">
<nav aria-label="Ruta de navegación" className="mb-8">
<ol className="flex flex-wrap items-center gap-2 font-mono text-[0.625rem] uppercase tracking-[0.14em] text-faint">
<li>
<Link href="/" className="hover:text-bright">
Inicio
</Link>
</li>
<li aria-hidden="true">/</li>
<li className="text-bright">Aviso de privacidad</li>
</ol>
</nav>
<div className="max-w-3xl">
<p className="eyebrow mb-5">Documento legal</p>
<h1 className="font-display text-[1.875rem] font-black uppercase leading-[1.04] tracking-tight sm:text-[2.5rem]">
Aviso de privacidad
</h1>
<p className="mt-5 text-sm leading-relaxed text-muted sm:text-base">
Reproducción del aviso publicado por {EMPRESA.razonSocial}, reordenado para poder
leerse. La versión vigente y definitiva es la que la empresa publique en su propio
sitio.
</p>
</div>
<div
role="note"
aria-label="Naturaleza de este sitio"
className="mt-8 max-w-3xl rounded-[6px] border border-rule border-l-2 border-l-ember bg-ink-2 p-5"
>
<p className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-ember">
Sobre este sitio
</p>
<p className="mt-3 text-sm leading-relaxed text-muted">{AVISO_DEMO}</p>
</div>
</div>
</section>
{/* ---------- el aviso ---------- */}
<article className="border-t border-rule bg-paper py-14 text-deep sm:py-20">
<div className="shell">
<div className="max-w-3xl space-y-12">
<section aria-labelledby="responsable">
<h2 id="responsable" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
1. Responsable del tratamiento
</h2>
<div className="mt-4 space-y-4 text-sm leading-relaxed text-deep-muted">
<p>
{EMPRESA.razonSocial} ({EMPRESA.nombreCorto}), empresa legalmente constituida
conforme a las leyes de la República Mexicana, con domicilio en Avenida Instituto
Técnico Industrial número 11, Colonia {EMPRESA.colonia}, Alcaldía Cuauhtémoc, C.P.
06400, {EMPRESA.ciudad}.
</p>
<p>
{EMPRESA.nombreCorto} será el responsable del tratamiento que, con motivo de la
relación jurídica que haya sido celebrada y para el cumplimiento de la misma, se le
dé a tus datos personales.
</p>
<p>
En cumplimiento de la Ley Federal de Protección de Datos Personales en Posesión de
los Particulares, pone a tu disposición el presente aviso para hacer de tu
conocimiento que los datos personales que nos proporciones, incluso aquellos
sensibles y patrimoniales o financieros, serán tratados dentro de un marco que
garantice su privacidad y el derecho a la autodeterminación informativa de las
personas.
</p>
</div>
</section>
<hr className="hair-lite" />
<section aria-labelledby="datos">
<h2 id="datos" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
2. Qué datos recaba este sitio
</h2>
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
Esta sección no viene del aviso original: describe exactamente lo que pide el
formulario de este sitio, para que sepas qué estás enviando antes de enviarlo.
</p>
<div
className="mt-6 overflow-x-auto rounded-[6px] border border-rule-lite bg-white [-webkit-overflow-scrolling:touch]"
tabIndex={0}
role="region"
aria-label="Datos que recaba el formulario, tabla desplazable en horizontal"
>
<table className="w-full min-w-[36rem] border-collapse text-left">
<caption className="sr-only">
Campos del formulario de contacto y para qué se usa cada uno.
</caption>
<thead>
<tr className="border-b border-rule-lite bg-paper-2">
<th
scope="col"
className="whitespace-nowrap px-4 py-3 font-mono text-[0.625rem] font-medium uppercase tracking-[0.14em] text-deep-muted"
>
Dato
</th>
<th
scope="col"
className="whitespace-nowrap px-4 py-3 font-mono text-[0.625rem] font-medium uppercase tracking-[0.14em] text-deep-muted"
>
Para qué se usa
</th>
</tr>
</thead>
<tbody>
{CAMPOS_FORMULARIO.map((fila) => (
<tr key={fila.campo} className="border-b border-rule-lite last:border-b-0">
<th scope="row" className="px-4 py-3.5 text-left align-top">
<span className="font-sans text-sm font-semibold text-deep">
{fila.campo}
</span>
</th>
<td className="px-4 py-3.5 align-top text-sm leading-relaxed text-deep-muted">
{fila.uso}
</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="mt-5 text-sm leading-relaxed text-deep-muted">
El formulario no pide datos de tarjeta, contraseñas ni información financiera. Si
necesitas compartir documentación sensible de tu operación, acuérdalo por correo
antes de enviarla.
</p>
</section>
<hr className="hair-lite" />
<section aria-labelledby="finalidades">
<h2 id="finalidades" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
3. Finalidades del tratamiento
</h2>
<div className="mt-4 space-y-4 text-sm leading-relaxed text-deep-muted">
<p>
Tus datos personales, incluso aquellos sensibles y patrimoniales o financieros,
serán utilizados para las siguientes finalidades: identificarte, localizarte,
contactarte, así como para cumplir las obligaciones derivadas de la relación
celebrada contigo, y cualquier otro fin compatible o análogo de los aquí
establecidos.
</p>
<p>
Esto incluye enviar, por cualquier medio físico, electrónico o magnético, de manera
enunciativa mas no limitativa: invitación a reuniones de trabajo, minutas, noticias
y anuncios en general relacionados con la institución, campañas publicitarias
afines e invitación a eventos.
</p>
</div>
</section>
<hr className="hair-lite" />
<section aria-labelledby="transferencias">
<h2 id="transferencias" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
4. Transferencias
</h2>
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
Queda convenido que aceptas la transferencia que {EMPRESA.nombreCorto} pudiera
realizar a sus asociados y a terceros, en cumplimiento de las finalidades
anteriormente descritas.
</p>
</section>
<hr className="hair-lite" />
<section aria-labelledby="seguridad">
<h2 id="seguridad" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
5. Medidas de seguridad
</h2>
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
Con el objeto de limitar el uso y divulgación de tus datos personales, se mantienen
medidas de seguridad administrativas, técnicas y físicas para evitar su daño,
pérdida, alteración, destrucción, uso, acceso o divulgación indebida.
</p>
</section>
<hr className="hair-lite" />
<section aria-labelledby="consentimiento">
<h2 id="consentimiento" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
6. Excepciones al consentimiento
</h2>
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
{EMPRESA.nombreCorto} no requerirá el consentimiento del titular para tratar datos
personales cuando lo haga con fundamento en lo dispuesto por la Ley Federal de
Protección de Datos Personales en Posesión de los Particulares.
</p>
</section>
<hr className="hair-lite" />
<section aria-labelledby="arco">
<h2 id="arco" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
7. Derechos de acceso, rectificación, cancelación y oposición
</h2>
<div className="mt-4 space-y-4 text-sm leading-relaxed text-deep-muted">
<p>
El ejercicio de los derechos de Acceso, Rectificación, Cancelación y Oposición
respecto de tus datos personales, así como la revocación del consentimiento para su
tratamiento, podrá realizarse a través de los procedimientos implementados o
solicitándolo al siguiente correo electrónico:
</p>
<p>
<a href={`mailto:${CORREO_ARCO}`} className="link break-all font-mono text-sm">
{CORREO_ARCO}
</a>
</p>
</div>
</section>
<hr className="hair-lite" />
<section aria-labelledby="cambios">
<h2 id="cambios" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
8. Cambios al aviso
</h2>
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
{EMPRESA.nombreCorto} podrá enmendar o modificar el presente aviso de privacidad como
lo estime conveniente, e informará y pondrá a tu disposición el aviso actualizado en
su sitio web.
</p>
</section>
<hr className="hair-lite" />
<section aria-labelledby="contacto-aviso">
<h2 id="contacto-aviso" className="font-display text-xl font-extrabold text-deep sm:text-2xl">
9. Contacto
</h2>
<dl className="spec mt-5 sm:grid-cols-2">
<div className="spec-cell !bg-white">
<dt className="spec-key !text-deep-muted">Teléfono</dt>
<dd className="spec-val !text-deep">
<a href={`tel:${EMPRESA.telefonoTel}`} className="link">
{EMPRESA.telefono}
</a>
</dd>
</div>
<div className="spec-cell !bg-white">
<dt className="spec-key !text-deep-muted">Correo general</dt>
<dd className="spec-val !text-deep">
<a href={`mailto:${EMPRESA.correo}`} className="link break-all">
{EMPRESA.correo}
</a>
</dd>
</div>
</dl>
<p className="mt-6 text-xs leading-relaxed text-deep-muted">
Si detectas una diferencia entre este texto y el aviso publicado por la empresa,
prevalece el de la empresa.{" "}
<Link href="/contacto" className="link">
Avísanos
</Link>{" "}
y lo corregimos.
</p>
</section>
</div>
</div>
</article>
</>
);
}