/* ========== La Chismosa components ========== */ /* ---------- Custom Cursor ---------- */ const CURSOR_LABELS = [ { sel: ".envelope-wrap, .envelope-cta, .envelope", text: "Abrir" }, { sel: ".press-card", text: "Leer" }, { sel: ".carousel-card, .office-item", text: "Ver" }, { sel: ".contact-cta", text: "Escribir" }, { sel: ".holding-card", text: "Descubrir" }, { sel: ".silencio-sticky", text: "Subir" }, ]; function Cursor() { const dot = React.useRef(null); const ring = React.useRef(null); const lbl = React.useRef(null); const pos = React.useRef({ x: -100, y: -100 }); const target = React.useRef({ x: -100, y: -100 }); React.useEffect(() => { const onMove = (e) => { target.current = { x: e.clientX, y: e.clientY }; if (dot.current) dot.current.style.transform = `translate(${e.clientX}px, ${e.clientY}px) translate(-50%, -50%)`; }; const onOver = (e) => { if (!ring.current) return; const el = e.target; if (el.closest("a, button, [data-hover], .envelope-cta, .office-item, .press-card, .services-foot .item, .map-pin")) { ring.current.classList.add("hover"); } else { ring.current.classList.remove("hover"); } if (lbl.current) { const match = CURSOR_LABELS.find(({ sel }) => el.closest(sel)); if (match) { lbl.current.textContent = match.text; lbl.current.classList.add("visible"); } else { lbl.current.classList.remove("visible"); } } }; let raf; const loop = () => { pos.current.x += (target.current.x - pos.current.x) * 0.18; pos.current.y += (target.current.y - pos.current.y) * 0.18; if (ring.current) ring.current.style.transform = `translate(${pos.current.x}px, ${pos.current.y}px) translate(-50%, -50%)`; if (lbl.current) lbl.current.style.transform = `translate(${pos.current.x + 26}px, ${pos.current.y - 14}px)`; raf = requestAnimationFrame(loop); }; loop(); window.addEventListener("mousemove", onMove); window.addEventListener("mouseover", onOver); return () => { cancelAnimationFrame(raf); window.removeEventListener("mousemove", onMove); window.removeEventListener("mouseover", onOver); }; }, []); return ( <>
); } /* ---------- Navigation ---------- */ function Nav({ active, onNav }) { const [scrolled, setScrolled] = React.useState(false); React.useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 40); window.addEventListener("scroll", onScroll); return () => window.removeEventListener("scroll", onScroll); }, []); const links = [ { id: "nosotros", label: "Nosotros" }, { id: "servicios", label: "Servicios" }, { id: "prensa", label: "Prensa" }, { id: "proyectos", label: "Proyectos" }, { id: "contacto", label: "Contacto" }]; return (
{e.preventDefault();onNav("top");}}> La·Chismosa
ES | EN
); } /* ---------- Intro / persiana ---------- */ function Intro({ onDone }) { const N = 10; const ref = React.useRef(null); React.useEffect(() => { const el = ref.current; if (!el) return; const strips = el.querySelectorAll(".intro-strip"); const half = N / 2; strips.forEach((s, i) => { const dist = Math.abs(i - (half - 0.5)); s.style.setProperty("--d", `${(dist / half) * 0.3}s`); s.style.transformOrigin = i < half ? "top center" : "bottom center"; }); const t1 = setTimeout(() => el.classList.add("opening"), 900); const t2 = setTimeout(() => onDone?.(), 900 + 680 + 300 + 120); return () => { clearTimeout(t1); clearTimeout(t2); }; }, []); return (
{Array.from({ length: N }).map((_, i) => (
))}
La Chismosa
); } /* ---------- Invisible ink ---------- */ function InkText({ children }) { const ref = React.useRef(null); const heat = React.useRef(0); const rafRef = React.useRef(null); React.useEffect(() => { const el = ref.current; if (!el) return; const onMove = (e) => { const r = el.getBoundingClientRect(); const dist = Math.hypot(e.clientX - (r.left + r.width / 2), e.clientY - (r.top + r.height / 2)); const radius = Math.max(r.width * 0.5, 80) + 170; const target = Math.max(0, 1 - dist / radius); cancelAnimationFrame(rafRef.current); const tick = () => { heat.current += (target - heat.current) * 0.08; el.style.setProperty("--heat", heat.current.toFixed(3)); if (Math.abs(heat.current - target) > 0.002) rafRef.current = requestAnimationFrame(tick); }; tick(); }; window.addEventListener("mousemove", onMove, { passive: true }); return () => { window.removeEventListener("mousemove", onMove); cancelAnimationFrame(rafRef.current); }; }, []); return {children}; } /* ---------- Redacted text ---------- */ function Redacted({ children, delay = 0 }) { const ref = React.useRef(null); React.useEffect(() => { const el = ref.current; if (!el) return; el.style.setProperty("--rd", `${delay}s`); const io = new IntersectionObserver(([entry]) => { if (!entry.isIntersecting) return; io.disconnect(); el.classList.add("revealed"); }, { threshold: 0.9, rootMargin: "0px 0px -120px 0px" }); io.observe(el); return () => io.disconnect(); }, [delay]); return ( {children} ); } /* ---------- HERO / Envelope ---------- */ function Hero({ onReveal }) { const [state, setState] = React.useState("closed"); const heroRef = React.useRef(null); React.useEffect(() => { const t = setTimeout(() => {setState("opening");}, 600); return () => clearTimeout(t); }, []); React.useEffect(() => { if (state === "opening") { const t = setTimeout(() => {setState("revealed");onReveal?.();}, 1400); return () => clearTimeout(t); } }, [state]); React.useEffect(() => { const onMove = (e) => { if (!heroRef.current) return; const r = heroRef.current.getBoundingClientRect(); const x = (e.clientX - r.left) / r.width - 0.5; const y = (e.clientY - r.top) / r.height - 0.5; const bg = heroRef.current.querySelector(".video-placeholder"); if (bg) bg.style.transform = `scale(${state === "revealed" ? 1.02 : 1.08}) translate(${x * -20}px, ${y * -20}px)`; }; window.addEventListener("mousemove", onMove); return () => window.removeEventListener("mousemove", onMove); }, [state]); return (
{state === "revealed" && }
state === "closed" && setState("opening")}>
LCH
2026
INVITACIÓN N.º 001
Para quien comunica con intención.
Una carta abierta de
La Chismosa — Luxury Communications
L
backed by a global group
Una agencia global de comunicación para marcas que entienden el lujo como lenguaje.
— Who we are —

"Porque el lujo
también se comunica."

Antonio de Juan Founder · Managing Director
Scroll
© MMXXVI
Málaga · Madrid · Brasil · Cancún · Miami · CDMX
); } /* ---------- Manifesto ---------- */ function Manifesto() { return (
— 01 / Nosotros

Construimos narrativas para marcas donde el detalle no decora: define.

Somos un estudio de comunicación dedicado exclusivamente al universo del lujo — hospitality, gastronomía, arquitectura y diseño interior. Un equipo pequeño, respaldado por un grupo global, que trabaja pieza a pieza, palabra a palabra.

No vendemos ruido. Ofrecemos criterio, discreción y una red de relaciones cultivada durante más de dos décadas en las cinco ciudades que marcan la conversación.

Sabemos lo que no se publica.
); } /* ---------- Services Marquee ---------- */ const SERVICES = [ "Food & Beverage", "Hotel Brands", "Interior Design & FF&E", "Architecture", "Assets Guardianship", "Communication"]; function ServicesMarquee() { const row1 = React.useRef(null); const row2 = React.useRef(null); React.useEffect(() => { let raf,x1 = 0,x2 = 0; const tick = () => { x1 -= 0.4; x2 += 0.4; if (row1.current) row1.current.style.transform = `translate3d(${x1}px,0,0)`; if (row2.current) row2.current.style.transform = `translate3d(${x2}px,0,0)`; if (row1.current) { const w = row1.current.scrollWidth / 2; if (Math.abs(x1) >= w) x1 = 0; } if (row2.current) { const w = row2.current.scrollWidth / 2; if (x2 >= w) x2 = 0; } raf = requestAnimationFrame(tick); }; tick(); return () => cancelAnimationFrame(raf); }, []); const row = (dup = false) => <> {SERVICES.map((s, i) => 0{i + 1} {s} )} ; return (
— 02 / Servicios

Seis disciplinas, una misma gramática del lujo.

+ 500 Proyectos
{row()}{row(true)}
{row()}{row(true)}
{SERVICES.map((s, i) =>
0{i + 1} — {s}
)}
); } /* ---------- Presence / Stats ---------- */ function Presence() { const stats = [ { n: "+20", em: "países", label: "Experience in over", desc: "Presencia operativa en más de veinte mercados." }, { n: "+20", em: "países", label: "Trusted by over", desc: "Marcas de lujo que confían su relato a nuestro criterio." }, { n: "+20", em: "países", label: "Success achieved in", desc: "Proyectos de comunicación, estrategia y custodia de activos." }]; return (
— 03 / Global presence

Respaldados por un grupo global, con base estratégica en cinco ciudades clave.

{stats.map((s, i) =>
{s.n} {s.em} {s.label} {s.desc}
)}
); } /* ---------- Interactive Map ---------- */ const OFFICES = [ { id: "malaga", city: "Málaga", country: "España", addr: "Hacienda del Mar — Meliá Collection, meeting center", x: 48.8, y: 36.5, status: "open", img: "assets/maps/malaga.png" }, { id: "madrid", city: "Madrid", country: "España", addr: "C/ de Fernando Santos, Chamberí, 27", x: 47.2, y: 34.0, status: "open", img: "assets/maps/madrid.png" }, { id: "brasil", city: "Brasil", country: "Sudamérica", addr: "São Paulo", x: 35.2, y: 67.0, status: "open", img: "assets/maps/rio-de-janeiro.png" }, { id: "cancun", city: "Cancún", country: "México", addr: "Carretera Aeropuerto-Bonfil km 11.5", x: 24.6, y: 49.0, status: "open", img: "assets/maps/cancun.png" }, { id: "miami", city: "Miami", country: "USA", addr: "Miami, FL", x: 25.8, y: 45.0, status: "open", img: "assets/maps/miami.png" }, { id: "cdmx", city: "CDMX", country: "México", addr: "Campus corporativo de Coyoacán, PB T2", x: 22.0, y: 52.0, status: "open", img: "assets/maps/mexico-city.png" }, { id: "middle", city: "Middle East", country: "", addr: "Dubai / Riyadh", x: 60.0, y: 47.0, status: "open", img: "assets/maps/riyadh.png" }]; function WorldMap() { const [active, setActive] = React.useState("malaga"); const activeOffice = OFFICES.find((o) => o.id === active) || OFFICES[0]; const activeIdx = OFFICES.findIndex((o) => o.id === active); return (
— 04 / Our workspaces

Conversaciones a escala global, decisiones en persona.

Let's talk · +34 900 155 155
{OFFICES.map((o, i) => { const offset = i - activeIdx; const abs = Math.abs(offset); const pos = abs === 0 ? "center" : abs === 1 ? offset < 0 ? "left" : "right" : "hidden"; return (
setActive(o.id)}>
{o.img && {o.city}}
{o.city} · {o.status === "open" ? "open" : "coming soon"}
{o.city} {o.addr}
); })}
{String(activeIdx + 1).padStart(2, '0')} / {String(OFFICES.length).padStart(2, '0')} {activeOffice.status === "open" ? "Open now" : "Coming soon"}
{OFFICES.map((o) => )}
); } /* ---------- Press / Projects ---------- */ const PRESS = [ { meta: "Hospitality · 2025", title: "Relanzamiento de marca para un resort boutique en la Costa del Sol.", cap: "Hacienda · coastal", cls: "wide", img: "https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=900&q=85&fit=crop" }, { meta: "F&B · 2025", title: "Apertura editorial de un restaurante firma en Ciudad de México.", cap: "Interior · dining", cls: "tall", img: "https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=900&q=85&fit=crop" }, { meta: "Architecture · 2024", title: "Narrativa de producto para un estudio de arquitectura residencial.", cap: "Atelier · studio", cls: "third", img: "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=900&q=85&fit=crop" }, { meta: "Prensa · 2024", title: "Campaña internacional · 28 medios internacionales de referencia.", cap: "Press · portfolio", cls: "third", img: "https://images.unsplash.com/photo-1511578314322-379afb476865?w=900&q=85&fit=crop" }, { meta: "Interior · 2024", title: "Guardianship de marca para una colección de mobiliario de autor.", cap: "FF&E · detail", cls: "third", img: "https://images.unsplash.com/photo-1555041469-a586c61ea9bc?w=900&q=85&fit=crop" }]; /* ---------- Billboard ---------- */ function Billboard() { const ref = React.useRef(null); const [progress, setProgress] = React.useState(0); React.useEffect(() => { const onScroll = () => { const el = ref.current; if (!el) return; const r = el.getBoundingClientRect(); const vh = window.innerHeight; // 0 when section enters viewport from below, 1 when it leaves at top const p = 1 - (r.top + r.height / 2) / (vh + r.height / 2); setProgress(Math.max(0, Math.min(1, p))); }; onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); const shift = (progress - 0.5) * 60; // parallax for the photo // Reveal animation choreography (driven by scroll progress 0 → 1) // 0.20 → 0.45: pink panel sweeps in (clip-path) // 0.42 → 0.58: line 1 ("It's time to") // 0.50 → 0.66: line 2 ("Tell YOUR Story") // 0.66 → 0.80: wordmark const stage = (a, b) => Math.max(0, Math.min(1, (progress - a) / (b - a))); const panelP = stage(0.18, 0.46); const line1P = stage(0.40, 0.58); const line2P = stage(0.50, 0.68); const markP = stage(0.66, 0.82); // panel drops from top like a canvas falling with gravity (ease-in²) const easedP = panelP * panelP; const panelClip = `inset(0% 0% ${(1 - easedP) * 100}% 0%)`; return (
{/* Animated mupi overlay — covers and replays the pink billboard */}
{/* (mupi moved inside billboard-media so it tracks the photo crop) */}
— Manifesto
La Chismosa · Out-of-home · Madrid / 2025
); } function Press() { return (
— 05 / Prensa & Proyectos

Un portfolio editado. Seleccionado, nunca acumulado.

Archivo completo →
{PRESS.map((p, i) =>
{p.img && {p.cap}}
{p.cap}
{p.meta} 0{i + 1} / 0{PRESS.length}

{p.title}

)}
); } /* ---------- Holding / Sister brands ---------- */ const HOLDING_BRANDS = [ { cat: "Food & Beverage", name: "TalentChef", italic: false, tone: 1 }, { cat: "Hotel Brands", name: "Tailors", italic: true, tone: 2 }, { cat: "Interior Design & FF&E", name: "Guinda", italic: true, tone: 3 }, { cat: "Architecture", name: "Alia", italic: true, tone: 4 }, { cat: "Assets Guardianship", name: "Libo", italic: true, tone: 5 }, { cat: "Communication", name: "la CHISMOSA", italic: true, tone: 6, current: true }]; function Holding() { return (
— 06 / Backed by
LITTLEBIG Hospitality Group

Una familia de marcas especialistas. Cada disciplina, una firma propia. Una sola conversación.

); } /* ---------- Contact / Footer ---------- */ function Contact() { const megaRef = React.useRef(null); React.useEffect(() => { const el = megaRef.current; if (!el) return; const letters = el.querySelectorAll(".footer-mega-letter"); const io = new IntersectionObserver(([entry]) => { if (!entry.isIntersecting) return; io.disconnect(); letters.forEach((l, i) => l.style.setProperty("--ld", `${i * 0.048}s`)); requestAnimationFrame(() => letters.forEach(l => l.classList.add("in"))); }, { threshold: 0.25 }); io.observe(el); return () => io.disconnect(); }, []); return (
LET'S TALK · 07 / CONTACTO

Si el chisme importa,
hablemos en persona.

Ya sabemos que te interesa.
hola@lachismosa.com
EUROPA

Málaga
Hacienda del Mar · Meliá

Madrid
C/ Fernando Santos 27 · Chamberí

LATAM

Cancún
Carretera Bonfil km 11.5

CDMX
Coyoacán · Campus PB T2

Miami
Coming soon

Expansión

Brasil
Coming soon · São Paulo

Middle East
Coming soon · Dubai

Direct

+34 900 155 155
Mon — Fri · 09:00–19:00 CET

Instagram
@lachismosa.luxury

LinkedIn
/la-chismosa

{Array.from("La Chismosa.").map((ch, i) => )}
© MMXXVI · La Chismosa · Luxury Communications
); } Object.assign(window, { Intro, Cursor, Nav, Hero, Manifesto, ServicesMarquee, Presence, WorldMap, Press, Contact, Redacted, InkText });