/* global React */
const { useState, useEffect, useRef, useCallback } = React;
// =======================================================================
// COPY DATA (single source of truth — also used by the booking flow)
// =======================================================================
const COPY = {
en: {
nav: { treatments: 'Treatments', experts: 'Experts', about: 'About', location: 'The Opus', contact: 'Contact', book: 'Book a Consultation' },
tagline: 'The Home of Mindful Aesthetics',
values: 'Ethical · Sustainable · Personal',
address1: 'The Opus by Omniyat',
address2: 'Unit C201, Al A’amal Street',
address3: 'Business Bay, Dubai, UAE',
phone: '+971 4 456 2024',
whatsapp: '+971 58 685 8562',
email: 'dubai@ouronyx.com',
direction: 'ltr',
},
ar: {
nav: { treatments: 'علاجات', experts: 'خبراؤنا', about: 'عن أورونيكس', location: 'أوبس', contact: 'اتصل', book: 'احجز استشارة' },
tagline: 'دار جماليات الوعي',
values: 'أخلاقي · مستدام · شخصي',
address1: 'أوبس بواسطة أومنيات',
address2: 'الوحدة C201، شارع الأمل',
address3: 'الخليج التجاري، دبي',
phone: '+971 4 456 2024',
whatsapp: '+971 58 685 8562',
email: 'dubai@ouronyx.com',
direction: 'rtl',
},
};
// =======================================================================
// Phi mark — original interpretation, NOT the proprietary logo
// (the Greek letter phi rendered in our serif type system)
// =======================================================================
function PhiMark({ size = 28, color }) {
const px = typeof size === 'number' ? `${size}px` : size;
return (
φ
);
}
function Wordmark({ size = 18, color }) {
return (
);
}
// =======================================================================
// Scroll-reveal wrapper using IntersectionObserver
// =======================================================================
function Reveal({ children, delay = 0, className = '', as: As = 'div', ...rest }) {
const ref = useRef(null);
const [shown, setShown] = useState(false);
useEffect(() => {
if (!ref.current) return;
const io = new IntersectionObserver(
(entries) => entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }),
{ threshold: 0.08 }
);
io.observe(ref.current);
return () => io.disconnect();
}, []);
return (
{children}
);
}
// =======================================================================
// Top Nav with sticky behavior + Treatments mega-menu
// =======================================================================
function Nav({ route, onNav, onBook, locale, onLocale, dark, onDarkToggle }) {
const [scrolled, setScrolled] = useState(false);
const [mega, setMega] = useState(false);
const t = COPY[locale];
useEffect(() => {
const onScroll = () => {
const el = document.querySelector('.app-scroll');
const top = el ? el.scrollTop : window.scrollY;
setScrolled(top > 30);
};
const el = document.querySelector('.app-scroll');
if (el) el.addEventListener('scroll', onScroll);
else window.addEventListener('scroll', onScroll);
return () => {
if (el) el.removeEventListener('scroll', onScroll);
else window.removeEventListener('scroll', onScroll);
};
}, []);
const link = (key, label) => (
);
return (
);
}
// =======================================================================
// Footer
// =======================================================================
function Footer({ locale, onNav }) {
const t = COPY[locale];
const ar = locale === 'ar';
return (
);
}
// =======================================================================
// Floating CTAs: WhatsApp / Call buttons (bottom-right)
// =======================================================================
function FloatingCTAs() {
return (
);
}
// =======================================================================
// Architectural arch SVG — echoes The Opus's curved steel structure
// =======================================================================
function ArchPattern({ color = 'currentColor', opacity = 0.3 }) {
return (
);
}
// Export
Object.assign(window, { COPY, PhiMark, Wordmark, Reveal, Nav, Footer, FloatingCTAs, ArchPattern });