// KSANET — shared web components
// Monograma KSANET — versión brandbook v3 (Tech)
// Marco rectangular abierto + K geométrica con nodo + ticks de medición + nodos en extremos
const KMonogram = ({ size = 32, color = '#8C1E22', accent = '#4a4945', bg = 'transparent' }) => {
const stroke = Math.max(1.4, size / 80);
return (
);
};
/* Wordmark: KSANET en Inter Tight, peso medio, tracking ancho, con punto tras la T (brandbook v3) */
const KWordmark = ({ height = 18, color = 'var(--ink)', accent = '#8C1E22' }) => (
KSANET
);
/* Tagline — brandbook v3 */
const TAGLINE_DEFAULT = 'Una puerta abierta desde 2012';
const KTagline = ({ color = '#6f6660', size = 10, text = TAGLINE_DEFAULT }) => {
const isLong = (text || '').length > 14;
const tracking = isLong ? '.22em' : '.42em';
return (
{text}
);
};
/* Lockup horizontal — monograma + (wordmark sobre tagline) */
const Brand = ({ size = 38, color = 'var(--ink)', linkBase = '', dark = false, tagline = TAGLINE_DEFAULT }) => {
const ring = dark ? '#f3e8da' : '#8C1E22';
const accent = dark ? '#b6b3ad' : '#4a4945';
const ink = dark ? '#f3e8da' : '#0f0d0c';
const tag = dark ? 'rgba(243,232,218,.6)' : '#6f6660';
return (
);
};
const Header = ({ active, base = '' }) => {
const [open, setOpen] = React.useState(false);
React.useEffect(() => {
document.body.style.overflow = open ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [open]);
const links = [
{ k: 'home', label: 'Inicio', href: base + 'index.html' },
{ k: 'promociones', label: 'Promociones', href: base + 'promociones.html' },
{ k: 'cooperativa', label: 'Cooperativa', href: base + 'cooperativa.html' },
{ k: 'guia', label: 'Guía del socio', href: base + 'guia.html' },
{ k: 'plataforma', label: 'Plataforma KSA', href: base + 'plataforma.html' },
{ k: 'calculadora', label: 'Calculadora', href: base + 'calculadora.html' },
{ k: 'contacto', label: 'Contacto', href: base + 'contacto.html' },
];
return (
);
};
const Footer = ({ base = '' }) => (
);
// Reveal hook
function useReveal() {
React.useEffect(() => {
const els = document.querySelectorAll('.reveal');
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add('in');
io.unobserve(e.target);
}
});
}, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
els.forEach((el) => io.observe(el));
return () => io.disconnect();
}, []);
}
// Architectural placeholder when no photo
const ArchPlaceholder = ({ tone = 'var(--paper-2)', accent = 'var(--brand)', label }) => (
{label && (
{label}
)}
);
Object.assign(window, { KMonogram, KWordmark, KTagline, Brand, Header, Footer, useReveal, ArchPlaceholder });