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:
co-authored by
Claude Opus 5
parent
122e06a4bb
commit
01b817d098
@@ -0,0 +1,453 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { FormularioContacto } from "@/components/formulario/FormularioContacto";
|
||||
import { Revelar } from "@/components/site/Revelar";
|
||||
import { EMPRESA, NORMAS, SITIO_URL } from "@/data/empresa";
|
||||
import { INDUSTRIAS } from "@/data/industrias";
|
||||
|
||||
/**
|
||||
* /cumplimiento-nom-002 — página de intención de búsqueda alta.
|
||||
*
|
||||
* Regla del contenido: no se citan artículos, umbrales ni plazos que no estén
|
||||
* en src/data/empresa.ts o en la fuente pública. Lo que no está verificado se
|
||||
* declara como no reproducido, no se estima.
|
||||
*/
|
||||
|
||||
const TITULO = "Cumplimiento NOM-002-STPS-2010";
|
||||
const DESCRIPCION =
|
||||
"Qué exige la NOM-002-STPS-2010 a un centro de trabajo, qué documentación se acumula y cómo se ve un expediente completo. Referencia orientativa, no dictamen técnico ni jurídico.";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: TITULO,
|
||||
description: DESCRIPCION,
|
||||
alternates: { canonical: `${SITIO_URL}/cumplimiento-nom-002` },
|
||||
openGraph: {
|
||||
title: `${TITULO} | ${EMPRESA.nombreCorto}`,
|
||||
description: DESCRIPCION,
|
||||
url: `${SITIO_URL}/cumplimiento-nom-002`,
|
||||
},
|
||||
};
|
||||
|
||||
const AVISO_ALCANCE =
|
||||
"Esta página es una referencia orientativa construida con información pública. La normativa puede actualizarse y complementarse por estado, municipio, tipo de instalación y autoridad competente. No sustituye un dictamen técnico ni una opinión jurídica.";
|
||||
|
||||
/** Elementos que la norma contempla, según la referencia de NORMAS. */
|
||||
const ELEMENTOS = [
|
||||
{
|
||||
n: "01",
|
||||
titulo: "Clasificación del riesgo de incendio",
|
||||
detalle:
|
||||
"Es el primer paso y condiciona todo lo demás. De la clasificación depende qué equipo, qué sistemas y qué plan te corresponden. Se determina con el procedimiento de la propia norma; los umbrales no se reproducen aquí porque dependen del material y de la superficie de cada centro de trabajo.",
|
||||
},
|
||||
{
|
||||
n: "02",
|
||||
titulo: "Equipo contra incendio",
|
||||
detalle:
|
||||
"Extintores disponibles, accesibles y señalizados, seleccionados según la clase de fuego presente en cada área. El equipo correcto en el lugar equivocado no cumple.",
|
||||
},
|
||||
{
|
||||
n: "03",
|
||||
titulo: "Sistemas fijos y de alarma",
|
||||
detalle:
|
||||
"Según el nivel de riesgo, el centro de trabajo puede requerir sistemas fijos de supresión y medios de detección y alarma, no solo equipo portátil.",
|
||||
},
|
||||
{
|
||||
n: "04",
|
||||
titulo: "Plan de atención a emergencias",
|
||||
detalle:
|
||||
"Documento por escrito. Es lo primero que se pide en una verificación y lo que más frecuentemente no existe o está desactualizado.",
|
||||
},
|
||||
{
|
||||
n: "05",
|
||||
titulo: "Brigadas y capacitación",
|
||||
detalle:
|
||||
"Personal designado, entrenado y con constancia. La capacitación sin registro documental no es demostrable ante una autoridad.",
|
||||
},
|
||||
{
|
||||
n: "06",
|
||||
titulo: "Simulacros",
|
||||
detalle:
|
||||
"Ejecutados y documentados. El registro del simulacro es evidencia tanto del plan como de la capacitación.",
|
||||
},
|
||||
];
|
||||
|
||||
const EXPEDIENTE = [
|
||||
{
|
||||
documento: "Clasificación de riesgo de incendio",
|
||||
quePrueba: "Que el nivel de exigencia aplicado al centro de trabajo es el correcto.",
|
||||
quienLoPide: "Verificación STPS, Protección Civil, aseguradora",
|
||||
},
|
||||
{
|
||||
documento: "Plan de atención a emergencias",
|
||||
quePrueba: "Que existe un procedimiento escrito y vigente para el escenario.",
|
||||
quienLoPide: "Verificación STPS, Protección Civil",
|
||||
},
|
||||
{
|
||||
documento: "Inventario y ubicación del equipo",
|
||||
quePrueba: "Qué hay instalado, dónde, de qué clase y con qué capacidad.",
|
||||
quienLoPide: "Verificación STPS, auditoría interna",
|
||||
},
|
||||
{
|
||||
documento: "Ficha técnica y certificado por modelo",
|
||||
quePrueba: "Que el equipo instalado es el que se declara y cubre las clases que se afirman.",
|
||||
quienLoPide: "Auditoría, aseguradora, cliente corporativo",
|
||||
},
|
||||
{
|
||||
documento: "Hoja de datos de seguridad del agente",
|
||||
quePrueba: "Manejo, almacenamiento y respuesta ante exposición del agente extintor.",
|
||||
quienLoPide: "Seguridad industrial, ambiental, auditoría",
|
||||
},
|
||||
{
|
||||
documento: "Bitácora de revisión mensual",
|
||||
quePrueba: "Que la revisión de extintores se realiza con la periodicidad debida.",
|
||||
quienLoPide: "Verificación STPS, Protección Civil",
|
||||
},
|
||||
{
|
||||
documento: "Constancias de capacitación y brigadas",
|
||||
quePrueba: "Que hay personal designado y entrenado, con nombre y fecha.",
|
||||
quienLoPide: "Verificación STPS",
|
||||
},
|
||||
{
|
||||
documento: "Registro de simulacros",
|
||||
quePrueba: "Que el plan se ejecuta y se corrige con lo aprendido.",
|
||||
quienLoPide: "Verificación STPS, Protección Civil",
|
||||
},
|
||||
];
|
||||
|
||||
export default function PaginaCumplimiento() {
|
||||
return (
|
||||
<>
|
||||
{/* ---------- encabezado con la advertencia de alcance ---------- */}
|
||||
<section className="grid-bg bg-ink pt-12 pb-14 sm:pt-16 sm:pb-20">
|
||||
<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">Cumplimiento</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div className="max-w-3xl anim-rise">
|
||||
<p className="eyebrow mb-5">Referencia normativa</p>
|
||||
<h1 className="font-display text-[2rem] font-black uppercase leading-[1.03] tracking-tight sm:text-[2.75rem] lg:text-5xl">
|
||||
Cumplimiento NOM-002: qué te van a pedir y cómo se ve un expediente completo
|
||||
</h1>
|
||||
<p className="mt-6 text-base leading-relaxed text-muted sm:text-lg">
|
||||
La norma no se cumple comprando extintores. Se cumple demostrando, por escrito, que el
|
||||
riesgo está clasificado, el equipo corresponde a ese riesgo y el personal sabe qué
|
||||
hacer. Esta página explica esa lógica y qué documentos la sostienen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
role="note"
|
||||
aria-label="Alcance de esta página"
|
||||
className="mt-10 max-w-3xl rounded-[6px] border border-rule border-l-2 border-l-ember bg-ink-2 p-5 sm:p-6"
|
||||
>
|
||||
<p className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-ember">
|
||||
Alcance de esta página
|
||||
</p>
|
||||
<p className="mt-3 text-sm leading-relaxed text-muted">{AVISO_ALCANCE}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- a quién aplica ---------- */}
|
||||
<section className="grid-bg-lite bg-paper py-14 sm:py-20" aria-labelledby="aplica-titulo">
|
||||
<div className="shell">
|
||||
<div className="grid gap-10 lg:grid-cols-[1fr_1.1fr] lg:gap-16">
|
||||
<div>
|
||||
<Revelar>
|
||||
<p className="eyebrow mb-4">A quién aplica</p>
|
||||
<h2 id="aplica-titulo" className="font-display text-2xl font-extrabold text-deep sm:text-3xl">
|
||||
A todo centro de trabajo, sin mínimo de tamaño
|
||||
</h2>
|
||||
<p className="mt-4 text-sm leading-relaxed text-deep-muted sm:text-base">
|
||||
{NORMAS[0].aplica}
|
||||
</p>
|
||||
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
|
||||
Es la razón por la que una oficina de veinte personas y una planta petroquímica
|
||||
están bajo la misma norma con obligaciones muy distintas: lo que cambia no es la
|
||||
norma, es la clasificación del riesgo.
|
||||
</p>
|
||||
</Revelar>
|
||||
</div>
|
||||
|
||||
<div className="panel-lite p-6 sm:p-8">
|
||||
<h3 className="font-display text-lg font-extrabold text-deep sm:text-xl">
|
||||
Dos niveles, dos conversaciones distintas
|
||||
</h3>
|
||||
|
||||
<div className="mt-6 space-y-6">
|
||||
<div className="border-l-2 border-l-rule-lite pl-4">
|
||||
<p className="font-mono text-[0.625rem] uppercase tracking-[0.14em] text-deep-muted">
|
||||
Riesgo ordinario
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-deep-muted">
|
||||
El foco está en tener el equipo correcto, señalizado y revisado, con un plan por
|
||||
escrito y personal capacitado. La mayoría de las PyMEs y oficinas queda aquí y
|
||||
el error caro es comprar de más por miedo.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-l-2 border-l-signal pl-4">
|
||||
<p className="font-mono text-[0.625rem] uppercase tracking-[0.14em] text-signal">
|
||||
Riesgo alto
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-deep-muted">
|
||||
La norma establece requerimientos mayores para los centros clasificados como de
|
||||
riesgo alto de incendio: la conversación pasa de equipo portátil a sistemas
|
||||
fijos, detección, brigadas formales y evidencia sostenida en el tiempo.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr className="hair-lite my-6" />
|
||||
|
||||
<p className="text-xs leading-relaxed text-deep-muted">
|
||||
No reproducimos aquí los umbrales de clasificación: dependen del material y de la
|
||||
superficie de cada centro de trabajo, y determinarlos mal invalida todo lo que se
|
||||
construya encima. Ese es el primer punto de un diagnóstico.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- qué contempla la norma ---------- */}
|
||||
<section className="border-t border-rule bg-ink py-14 sm:py-20" aria-labelledby="elementos-titulo">
|
||||
<div className="shell">
|
||||
<Revelar>
|
||||
<p className="eyebrow mb-4">Qué contempla</p>
|
||||
<h2 id="elementos-titulo" className="font-display text-2xl font-extrabold sm:text-3xl">
|
||||
Seis frentes, y ninguno se cierra con una compra
|
||||
</h2>
|
||||
<p className="mt-3 max-w-2xl text-sm leading-relaxed text-muted sm:text-base">
|
||||
Cada uno genera un documento distinto. Un expediente incompleto suele fallar en los
|
||||
frentes que no se compran: el plan, la capacitación y el registro.
|
||||
</p>
|
||||
</Revelar>
|
||||
|
||||
<ol className="mt-10 grid gap-px bg-rule sm:grid-cols-2 lg:grid-cols-3">
|
||||
{ELEMENTOS.map((elemento) => (
|
||||
<li key={elemento.n} className="bg-ink-2 p-6">
|
||||
<p className="font-mono text-[0.625rem] font-semibold tracking-[0.1em] text-signal">
|
||||
{elemento.n}
|
||||
</p>
|
||||
<h3 className="mt-3 font-display text-base font-extrabold leading-tight text-bright">
|
||||
{elemento.titulo}
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-relaxed text-muted">{elemento.detalle}</p>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
||||
<div className="mt-10 rounded-[6px] border border-rule bg-ink-2 p-5 sm:p-6">
|
||||
<p className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-faint">
|
||||
Mantenimiento de extintores
|
||||
</p>
|
||||
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-muted">
|
||||
{NORMAS[1].aplica} Es la obligación recurrente que más seguido se pierde: no por
|
||||
desconocerla, sino porque nadie quedó a cargo de la bitácora.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- el expediente ---------- */}
|
||||
<section className="grid-bg-lite bg-paper py-14 sm:py-20" aria-labelledby="expediente-titulo">
|
||||
<div className="shell-wide">
|
||||
<Revelar>
|
||||
<p className="eyebrow mb-4">Expediente</p>
|
||||
<h2 id="expediente-titulo" className="font-display text-2xl font-extrabold text-deep sm:text-3xl">
|
||||
Cómo se ve un expediente que aguanta una verificación
|
||||
</h2>
|
||||
<p className="mt-3 max-w-2xl text-sm leading-relaxed text-deep-muted sm:text-base">
|
||||
Ocho documentos. Ninguno es opcional cuando alguien pregunta, y cada uno prueba algo
|
||||
distinto.
|
||||
</p>
|
||||
</Revelar>
|
||||
|
||||
<p className="mt-6 font-mono text-[0.6875rem] uppercase tracking-[0.14em] text-deep-muted sm:hidden">
|
||||
Desliza la tabla para ver todas las columnas
|
||||
</p>
|
||||
|
||||
<div
|
||||
className="mt-4 overflow-x-auto rounded-[6px] border border-rule-lite bg-white [-webkit-overflow-scrolling:touch]"
|
||||
tabIndex={0}
|
||||
role="region"
|
||||
aria-label="Documentos del expediente, tabla desplazable en horizontal"
|
||||
>
|
||||
<table className="w-full min-w-[46rem] border-collapse text-left">
|
||||
<caption className="sr-only">
|
||||
Documentos que integran un expediente de cumplimiento, qué prueba cada uno y quién
|
||||
lo solicita.
|
||||
</caption>
|
||||
<thead>
|
||||
<tr className="border-b border-rule-lite bg-paper-2">
|
||||
{["Documento", "Qué prueba", "Quién lo pide"].map((c) => (
|
||||
<th
|
||||
key={c}
|
||||
scope="col"
|
||||
className="whitespace-nowrap px-4 py-3 font-mono text-[0.625rem] font-medium uppercase tracking-[0.14em] text-deep-muted"
|
||||
>
|
||||
{c}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{EXPEDIENTE.map((fila) => (
|
||||
<tr key={fila.documento} className="border-b border-rule-lite last:border-b-0">
|
||||
<th scope="row" className="px-4 py-4 text-left align-top">
|
||||
<span className="font-sans text-sm font-semibold text-deep">
|
||||
{fila.documento}
|
||||
</span>
|
||||
</th>
|
||||
<td className="max-w-[24rem] px-4 py-4 align-top text-sm leading-relaxed text-deep-muted">
|
||||
{fila.quePrueba}
|
||||
</td>
|
||||
<td className="px-4 py-4 align-top font-mono text-xs leading-relaxed text-deep-muted">
|
||||
{fila.quienLoPide}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p className="mt-6 max-w-3xl text-xs leading-relaxed text-deep-muted">
|
||||
En una compra con nosotros, los documentos que dependen del equipo se entregan por
|
||||
número de modelo.{" "}
|
||||
<Link href="/evidencia" className="link">
|
||||
Ver el índice de documentación por categoría
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- referencias ---------- */}
|
||||
<section className="border-t border-rule bg-ink py-14 sm:py-16" aria-labelledby="referencias-titulo">
|
||||
<div className="shell">
|
||||
<Revelar>
|
||||
<p className="eyebrow mb-4">Referencias</p>
|
||||
<h2 id="referencias-titulo" className="font-display text-xl font-extrabold sm:text-2xl">
|
||||
Normas citadas en esta página
|
||||
</h2>
|
||||
</Revelar>
|
||||
|
||||
<ul className="mt-8 grid gap-4 lg:grid-cols-2">
|
||||
{NORMAS.map((norma) => (
|
||||
<li key={norma.clave} className="panel p-5 sm:p-6">
|
||||
<p className="font-mono text-xs font-semibold uppercase tracking-[0.12em] text-signal">
|
||||
{norma.clave}
|
||||
</p>
|
||||
<h3 className="mt-3 font-display text-base font-extrabold leading-tight text-bright">
|
||||
{norma.titulo}
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-relaxed text-muted">{norma.aplica}</p>
|
||||
<a
|
||||
href={norma.fuente}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-4 inline-block font-mono text-[0.625rem] uppercase tracking-[0.14em] text-bright underline decoration-rule-2 underline-offset-4 hover:decoration-signal"
|
||||
>
|
||||
Ver la fuente oficial
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<p className="mt-8 max-w-3xl text-xs leading-relaxed text-faint">
|
||||
Los enlaces apuntan al sitio del Diario Oficial de la Federación. Verifica siempre la
|
||||
versión vigente: la publicación oficial manda sobre cualquier resumen, incluido este.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- por industria ---------- */}
|
||||
<section className="border-t border-rule bg-ink-2 py-14 sm:py-16" aria-labelledby="segmentos-titulo">
|
||||
<div className="shell">
|
||||
<Revelar>
|
||||
<p className="eyebrow eyebrow-muted mb-4">Por operación</p>
|
||||
<h2 id="segmentos-titulo" className="font-display text-xl font-extrabold sm:text-2xl">
|
||||
Lo que cambia según dónde trabajas
|
||||
</h2>
|
||||
</Revelar>
|
||||
<ul className="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{INDUSTRIAS.map((industria) => (
|
||||
<li key={industria.slug}>
|
||||
<Link
|
||||
href={`/soluciones/${industria.slug}`}
|
||||
className="group flex h-full flex-col rounded-[6px] border border-rule bg-ink p-5 transition-colors duration-200 hover:border-rule-2 [-webkit-tap-highlight-color:transparent]"
|
||||
>
|
||||
<h3 className="font-display text-base font-extrabold leading-tight text-bright">
|
||||
{industria.nombre}
|
||||
</h3>
|
||||
<ul className="mt-3 space-y-2">
|
||||
{industria.cumplimiento.map((obligacion) => (
|
||||
<li key={obligacion} className="flex gap-2.5 text-xs leading-relaxed text-muted">
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="mt-1.5 h-1 w-1 shrink-0 rounded-full bg-signal"
|
||||
/>
|
||||
{obligacion}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<span className="mt-auto pt-5 font-mono text-[0.625rem] uppercase tracking-[0.14em] text-signal transition-colors group-hover:text-signal-hi">
|
||||
Ver el segmento →
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- formulario y cierre con la advertencia ---------- */}
|
||||
<section id="validar" className="grid-bg-lite border-t border-rule bg-paper py-14 sm:py-20">
|
||||
<div className="shell">
|
||||
<div className="grid gap-10 lg:grid-cols-[1fr_1.05fr] lg:items-start lg:gap-16">
|
||||
<div>
|
||||
<Revelar>
|
||||
<p className="eyebrow mb-4">Siguiente paso</p>
|
||||
<h2 className="font-display text-2xl font-extrabold text-deep sm:text-3xl">
|
||||
Validar cumplimiento NOM-002
|
||||
</h2>
|
||||
<p className="mt-4 text-sm leading-relaxed text-deep-muted sm:text-base">
|
||||
Revisamos qué tienes, qué te falta y en qué orden conviene resolverlo. Si algo de tu
|
||||
situación requiere un dictamen formal, te lo decimos en lugar de venderte equipo.
|
||||
</p>
|
||||
</Revelar>
|
||||
|
||||
<div
|
||||
role="note"
|
||||
aria-label="Alcance de esta página"
|
||||
className="mt-8 rounded-[6px] border border-rule-lite border-l-2 border-l-ember bg-white p-5"
|
||||
>
|
||||
<p className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-deep-muted">
|
||||
Recordatorio de alcance
|
||||
</p>
|
||||
<p className="mt-3 text-sm leading-relaxed text-deep-muted">{AVISO_ALCANCE}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FormularioContacto
|
||||
canal="cumplimiento"
|
||||
variante="claro"
|
||||
titulo="Validar mi cumplimiento"
|
||||
descripcion="Dinos qué tipo de instalación es y qué te pidieron. Respondemos con el hueco documental que vemos y por dónde empezar."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user