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
+320
View File
@@ -0,0 +1,320 @@
import type { Metadata } from "next";
import Image from "next/image";
import Link from "next/link";
import { Revelar } from "@/components/site/Revelar";
import { CATEGORIAS, PRODUCTOS } from "@/data/catalogo";
import { EMPRESA, PRENSA, SITIO_URL } from "@/data/empresa";
import { INDUSTRIAS } from "@/data/industrias";
/**
* /nosotros — origen de la tecnología, posicionamiento y postura editorial.
*
* La parte más importante de esta página es la última sección: por qué la
* empresa documenta en lugar de prometer. Es la traducción del hallazgo central
* del estudio de marca y la razón de ser del resto del sitio.
*/
const TITULO = "Quiénes somos";
const DESCRIPCION = `${EMPRESA.nombre}: origen de la tecnología FireAde, posicionamiento en operaciones críticas y por qué documentamos en lugar de prometer.`;
export const metadata: Metadata = {
title: TITULO,
description: DESCRIPCION,
alternates: { canonical: `${SITIO_URL}/nosotros` },
openGraph: {
title: `${TITULO} | ${EMPRESA.nombreCorto}`,
description: DESCRIPCION,
url: `${SITIO_URL}/nosotros`,
},
};
const POSTURA = [
{
n: "01",
titulo: "Una afirmación sin documento es publicidad",
texto:
"El sitio anterior presentaba vida útil ilimitada, veinte años de garantía y ausencia de recarga como características del producto. Eran, en el mejor de los casos, afirmaciones con condiciones que nadie escribió. Ahora viven en un bloque aparte de cada ficha, junto con lo que hay que entregar para poder sostenerlas.",
},
{
n: "02",
titulo: "Los campos vacíos se quedan vacíos",
texto:
"Cuando no hay dato de alcance, de capacidad o de caudal, la ficha lo dice. No ponemos un guion ni una estimación redondeada: un número inventado en una ficha técnica reaparece en una auditoría con el nombre de quien lo firmó.",
},
{
n: "03",
titulo: "No hay botones de descarga que no descarguen nada",
texto:
"El centro de evidencia explica qué documentación corresponde a cada compra y cómo se solicita por número de modelo. Lo que no hace es simular un acervo. Un botón falso destruye la credibilidad de todo lo demás.",
},
{
n: "04",
titulo: "Los casos van rotulados",
texto:
"Los escenarios de aplicación están construidos con fines de demostración y lo dicen arriba, no en una nota al pie. Un caso con nombre de cliente requiere autorización por escrito sobre qué se puede contar y qué cifras se pueden publicar.",
},
{
n: "05",
titulo: "Preferimos la respuesta incómoda",
texto:
"Si un certificado no cubre tu caso de uso, si un plazo trae condiciones o si simplemente no tenemos un documento, va en la propuesta. Sale más barato ahí que en la verificación.",
},
];
export default function PaginaNosotros() {
return (
<>
{/* ---------- encabezado ---------- */}
<section className="grid-bg relative overflow-hidden 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">Nosotros</li>
</ol>
</nav>
<div className="grid gap-12 lg:grid-cols-[1.15fr_1fr] lg:items-center">
<div className="anim-rise">
<p className="eyebrow mb-5">Quiénes somos</p>
<h1 className="font-display text-[2rem] font-black uppercase leading-[1.03] tracking-tight sm:text-[2.75rem] lg:text-5xl">
{EMPRESA.promesa}
</h1>
<p className="mt-6 max-w-xl text-base leading-relaxed text-muted sm:text-lg">
{EMPRESA.descripcion}
</p>
<dl className="spec mt-9 sm:grid-cols-3">
<div className="spec-cell">
<dt className="spec-key">Origen de la tecnología</dt>
<dd className="spec-val">{EMPRESA.fundacionOrigen}</dd>
</div>
<div className="spec-cell">
<dt className="spec-key">Categorías</dt>
<dd className="spec-val">{CATEGORIAS.length}</dd>
</div>
<div className="spec-cell">
<dt className="spec-key">Equipos y agentes</dt>
<dd className="spec-val">{PRODUCTOS.length}</dd>
</div>
</dl>
</div>
<div className="relative aspect-[4/3] w-full overflow-hidden rounded-[6px] border border-rule">
<Image
src="/media/foto/bombero-plataforma.jpg"
alt="Personal de respuesta a incendios trabajando en una plataforma industrial"
fill
priority
sizes="(max-width: 1024px) 92vw, 34rem"
className="object-cover"
/>
<div
aria-hidden="true"
className="absolute inset-0 bg-gradient-to-t from-ink/70 via-transparent to-transparent"
/>
</div>
</div>
</div>
</section>
{/* ---------- origen de la tecnología ---------- */}
<section className="grid-bg-lite bg-paper py-14 sm:py-20" aria-labelledby="origen-titulo">
<div className="shell">
<div className="grid gap-10 lg:grid-cols-[1fr_1.15fr] lg:gap-16">
<div>
<Revelar>
<p className="eyebrow mb-4">Origen</p>
<h2 id="origen-titulo" className="font-display text-2xl font-extrabold text-deep sm:text-3xl">
La tecnología viene de {EMPRESA.empresaOrigen}
</h2>
</Revelar>
<div className="mt-5 space-y-4 text-sm leading-relaxed text-deep-muted sm:text-base">
<p>
{EMPRESA.empresaOrigen} se presenta como fundada en {EMPRESA.fundacionOrigen} por{" "}
{EMPRESA.fundadorOrigen}. {EMPRESA.nombreCorto} opera en México como{" "}
{EMPRESA.razonSocial} y usa esa herencia técnica como respaldo de desarrollo.
</p>
<p>
El activo de diferenciación es el agente FireAde 2000 y la familia de equipos
Enforcer, que permiten competir en un terreno distinto al del extintor
convencional: no por precio unitario, sino por tiempo de control, costo de
limpieza y continuidad de la operación.
</p>
<p>
Ese es también el límite honesto de lo que podemos afirmar aquí. Los datos de
origen provienen de la comunicación pública de la empresa; el desempeño de cada
formulación y de cada modelo se demuestra con su documentación, no con su historia.
</p>
</div>
</div>
<div className="panel-lite p-6 sm:p-8">
<h3 className="font-display text-lg font-extrabold text-deep sm:text-xl">
Dónde decidimos jugar
</h3>
<p className="mt-4 text-sm leading-relaxed text-deep-muted">
El estudio de marca fue explícito: {EMPRESA.nombreCorto} no debería competir por
catálogo más grande ni por precio unitario. El espacio defendible está entre
tecnología especializada, respuesta rápida, evidencia técnica y costo total de
operación.
</p>
<hr className="hair-lite my-6" />
<h4 className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-deep-muted">
Los cinco segmentos donde eso aplica
</h4>
<ul className="mt-4 space-y-3">
{INDUSTRIAS.map((industria) => (
<li key={industria.slug} className="flex gap-3">
<span className="mt-0.5 font-mono text-[0.625rem] font-semibold tracking-[0.08em] text-signal">
{String(industria.prioridad).padStart(2, "0")}
</span>
<p className="text-sm leading-relaxed text-deep-muted">
<Link href={`/soluciones/${industria.slug}`} className="link font-semibold text-deep">
{industria.nombre}
</Link>
{" — "}
{industria.dolor}
</p>
</li>
))}
</ul>
</div>
</div>
</div>
</section>
{/* ---------- postura editorial ---------- */}
<section className="border-t border-rule bg-ink py-14 sm:py-20" aria-labelledby="postura-titulo">
<div className="shell">
<div className="max-w-3xl">
<p className="font-mono text-[0.6875rem] font-medium uppercase tracking-[0.16em] text-ember">
Postura editorial
</p>
<h2 id="postura-titulo" className="mt-4 font-display text-2xl font-extrabold sm:text-3xl">
Por qué documentamos en lugar de prometer
</h2>
<p className="mt-5 text-base leading-relaxed text-muted">
La competencia promete. En protección contra incendios, una promesa sin documento no
es solo una debilidad comercial: es una exposición legal para quien la compra y para
quien la firma. La auditoría de marca lo señaló como el mayor riesgo del sitio
anterior, y estas cinco reglas son la respuesta.
</p>
</div>
<ol className="mt-12 grid gap-px bg-rule sm:grid-cols-2 lg:grid-cols-3">
{POSTURA.map((regla) => (
<li key={regla.n} className="bg-ink-2 p-6 sm:p-7">
<p className="font-mono text-[0.625rem] font-semibold tracking-[0.1em] text-ember">
{regla.n}
</p>
<h3 className="mt-3 font-display text-base font-extrabold leading-tight text-bright">
{regla.titulo}
</h3>
<p className="mt-3 text-sm leading-relaxed text-muted">{regla.texto}</p>
</li>
))}
</ol>
</div>
</section>
{/* ---------- Christmas Hero, sin exagerarlo ---------- */}
<section className="grid-bg-lite border-t border-rule bg-paper py-14 sm:py-20" aria-labelledby="prensa-titulo">
<div className="shell">
<div className="grid gap-10 lg:grid-cols-[1fr_1fr] lg:gap-16">
<div>
<Revelar>
<p className="eyebrow mb-4">Antecedente de comunicación</p>
<h2 id="prensa-titulo" className="font-display text-2xl font-extrabold text-deep sm:text-3xl">
&laquo;Christmas Hero&raquo;
</h2>
</Revelar>
<div className="mt-5 space-y-4 text-sm leading-relaxed text-deep-muted sm:text-base">
<p>
En 2019, {EMPRESA.nombreCorto} desarrolló una pieza de comunicación llamada
Christmas Hero: un adorno navideño que funcionaba como dispositivo de extinción
para árboles de Navidad. Fue publicada por LatinSpots en 2019 y obtuvo una mención
como segundo finalista de El Ojo Local México.
</p>
<p>
Lo decimos con esa medida, sin convertirlo en más de lo que fue. Importa por dos
razones concretas: demuestra que la empresa sabe traducir un problema técnico en
algo que una persona entiende de inmediato, y demuestra que puede sostener
atención de prensa cuando tiene algo que decir.
</p>
<p>
Ese es exactamente el trabajo pendiente en el resto de la comunicación: la
ingeniería está; la traducción es lo que faltaba.
</p>
</div>
</div>
<div>
<h3 className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-deep-muted">
Publicaciones que han cubierto a FSPM
</h3>
<ul className="mt-6 grid grid-cols-2 gap-3 sm:grid-cols-3">
{PRENSA.map((medio) => (
<li key={medio.medio}>
<a
href={medio.url}
target="_blank"
rel="noopener noreferrer"
className="flex h-20 items-center justify-center rounded-[3px] border border-rule-lite bg-white px-4 transition-colors duration-200 hover:border-signal/60 [-webkit-tap-highlight-color:transparent]"
>
<Image
src={medio.logo}
alt={`Nota en ${medio.medio}`}
width={110}
height={36}
sizes="110px"
className="max-h-9 w-auto object-contain opacity-75 transition-opacity duration-200 hover:opacity-100"
/>
</a>
</li>
))}
</ul>
<p className="mt-5 text-xs leading-relaxed text-deep-muted">
Los enlaces llevan a la nota original de cada medio. Varias corresponden a la cobertura
de Christmas Hero; aparecen como cobertura periodística, no como respaldo del
desempeño de un producto.
</p>
</div>
</div>
</div>
</section>
{/* ---------- salidas ---------- */}
<section className="border-t border-rule bg-ink-2 py-14 sm:py-16">
<div className="shell">
<div className="max-w-3xl">
<Revelar>
<p className="eyebrow mb-4">Siguiente paso</p>
<h2 className="font-display text-2xl font-extrabold sm:text-3xl">
Lo que sigue depende de qué tan urgente sea tu caso
</h2>
</Revelar>
<div className="mt-8 flex flex-wrap gap-3">
<Link href="/contacto" className="btn btn-signal">
Hablar con nosotros
</Link>
<Link href="/catalogo" className="btn btn-ghost">
Ver el catálogo
</Link>
<Link href="/evidencia" className="btn btn-ghost">
Centro de evidencia
</Link>
</div>
</div>
</div>
</section>
</>
);
}