/* global React, ReactDOM */ const { useState, useEffect, useRef, useCallback } = React; /* ===================== Custom cursor ===================== */ function CustomCursor() { const dotRef = useRef(null); const ringRef = useRef(null); const target = useRef({ x: -100, y: -100 }); const ring = useRef({ x: -100, y: -100 }); const isDown = useRef(false); useEffect(() => { // Only render on devices with a fine pointer const mq = window.matchMedia('(hover: hover) and (pointer: fine)'); if (!mq.matches) return; let raf; function loop() { const t = target.current; const r = ring.current; r.x += (t.x - r.x) * 0.18; r.y += (t.y - r.y) * 0.18; if (dotRef.current) dotRef.current.style.transform = `translate3d(${t.x}px, ${t.y}px, 0) translate(-50%, -50%)`; if (ringRef.current) ringRef.current.style.transform = `translate3d(${r.x}px, ${r.y}px, 0) translate(-50%, -50%) scale(${isDown.current ? 0.85 : 1})`; raf = requestAnimationFrame(loop); } function onMove(e) { target.current = { x: e.clientX, y: e.clientY }; // dark backgrounds: figure out element under cursor const el = document.elementFromPoint(e.clientX, e.clientY); const onDark = !!(el && el.closest && el.closest('.on-dark, [data-dark]')); ringRef.current && ringRef.current.classList.toggle('is-dark', onDark); dotRef.current && dotRef.current .classList.toggle('is-dark', onDark); } function onOver(e) { const interactive = e.target.closest && e.target.closest('a, button, [role="button"], input, select, textarea, label, summary'); ringRef.current && ringRef.current.classList.toggle('is-hover', !!interactive); } function onOut(e) { if (!e.relatedTarget) { ringRef.current && ringRef.current.classList.remove('is-hover'); } } function onDown(){ isDown.current = true; } function onUp() { isDown.current = false; } window.addEventListener('mousemove', onMove, { passive: true }); document.addEventListener('mouseover', onOver, { passive: true }); document.addEventListener('mouseout', onOut, { passive: true }); window.addEventListener('mousedown', onDown); window.addEventListener('mouseup', onUp); raf = requestAnimationFrame(loop); return () => { cancelAnimationFrame(raf); window.removeEventListener('mousemove', onMove); document.removeEventListener('mouseover', onOver); document.removeEventListener('mouseout', onOut); window.removeEventListener('mousedown', onDown); window.removeEventListener('mouseup', onUp); }; }, []); return ( <> ); } /* ===================== Media slots (image / video) ===================== */ function ImgSlot({ src, alt, label, badge, className = "", aspect = "aspect-[3/4]" }) { return (
{alt} { e.currentTarget.style.display = "none"; }} /> {(label || badge) && (
{label && {label}} {badge && {badge}}
)}
); } function VideoSlot({ label, srcs = [], poster, aspect = "aspect-[3/4]", className = "" }) { return (
{/* Poster image as fallback while there is no real video */} {poster && ( { e.currentTarget.style.display = "none"; }} /> )}
); } /* ===================== Gallery (Resultados Reales) ===================== */ function Gallery({ onNavigate, dark = false }) { const tiles = (window.siteMedia && window.siteMedia.gallery) || []; const bg = dark ? "bg-charcoal text-ivory on-dark" : "bg-ivory"; const muteText = dark ? "text-ivory/60" : "text-mute"; const heading = dark ? "text-ivory" : "text-ink"; return (

Resultados reales

Tu mejor versión,
en imagen y movimiento.

Una selección del trabajo del atelier — fotografía editorial y reels capturados en cabina. Lo que ves es real, sin filtros.

Ver más en Instagram
{tiles.map((t, i) => ( t.kind === "video" ? : ))}

Atelier Vibelami · Castellón / Valencia

); } /* ===================== Brand mark ===================== */ /* Returns a real URL for a page id when running in multipage mode (window.VIBELAMI_LINKS is defined by each page's ); otherwise null. */ function pageHref(id) { return (typeof window !== "undefined" && window.VIBELAMI_LINKS) ? window.VIBELAMI_LINKS[id] : null; } function Logo({ className = "", onClick }) { const inner = ( VIBELAMI. ); const href = pageHref("inicio"); if (href) { return ( {inner} ); } return ( ); } /* ===================== Top utility strip ===================== */ function TopStrip() { return (
Castellón · Valencia Agenda 2026 abierta — Citas y formaciones disponibles Atelier privado · Por cita previa
); } /* ===================== Navigation ===================== */ function Nav({ currentPage, onNavigate }) { const [open, setOpen] = useState(false); const items = [ { id: "inicio", label: "Inicio" }, { id: "servicios", label: "Servicios" }, { id: "academia", label: "Academia" }, { id: "promocion", label: "Promoción" }, { id: "contacto", label: "Contacto" }, ]; function go(id) { setOpen(false); onNavigate(id); } return (
go("inicio")} />
ES / EN {pageHref("contacto") ? ( Reservar ) : ( )}
{open && ( )}
); } /* ===================== Glyphs for "para ti" ===================== */ function Glyph({ kind }) { const common = { width: 56, height: 56, viewBox: "0 0 56 56", fill: "none", "aria-hidden": true, stroke: "currentColor" }; if (kind === "lift") { return ( ); } if (kind === "diamond") { return ( ); } return ( ); } /* ===================== Contact ===================== */ function Contact({ defaultService }) { const [form, setForm] = useState({ nombre: "", telefono: "", servicio: defaultService || "", mensaje: "", rgpd: false }); const [sent, setSent] = useState(false); const [touched, setTouched] = useState(false); const handle = (k) => (e) => setForm({ ...form, [k]: e.target.type === "checkbox" ? e.target.checked : e.target.value }); const required = form.nombre.trim() && form.telefono.trim() && form.servicio && form.rgpd; function submit(e) { e.preventDefault(); setTouched(true); if (!required) return; setSent(true); } const inputBase = "w-full bg-transparent border-0 border-b border-line/80 focus:border-ink py-3 text-[15px] text-ink placeholder:text-mute/70 transition-colors"; const labelBase = "block text-[10px] tracking-widest-2 uppercase text-mute mb-2"; return (

Contacto

Escríbenos.
Te respondemos hoy.

Cuéntanos qué buscas. Nuestro equipo se pondrá en contacto contigo en menos de 24h para agendar tu valoración personalizada.

Castellón
Atelier Castellón
Av. del Mar, 00
12003 · Castellón de la Plana
+34 642 606 395
Valencia
Atelier Valencia
C/ Colón, 00
46004 · Valencia
+34 642 606 395
Horario
Lun – Sáb · 10:00 – 20:00
Por cita previa
{sent ? (

Mensaje enviado

Gracias, {form.nombre.split(" ")[0] || "hablamos pronto"}.

Hemos recibido tu mensaje. Te escribiremos por WhatsApp o email en las próximas horas para coordinar tu cita.

) : (