// Shared components: Logo, TopStrip, Navbar, Footer, WhatsAppFab, TweaksPanel, ConsultationModal // Exposes to window for use across pages. const { useState, useEffect, useRef, useCallback } = React; // ---------- Tweaks state (shared via localStorage) ---------- const TWEAK_KEY = 'qd_tweaks_v1'; const DEFAULT_TWEAKS = { accent: 'champagne', // champagne | rose | platinum mode: 'ivory', // ivory | noir display: 'cormorant', // cormorant | playfair | italiana }; function loadTweaks() { try { return { ...DEFAULT_TWEAKS, ...(JSON.parse(localStorage.getItem(TWEAK_KEY) || '{}')) }; } catch (e) { return { ...DEFAULT_TWEAKS }; } } function saveTweaks(t) { localStorage.setItem(TWEAK_KEY, JSON.stringify(t)); } function applyTweaks(t) { const root = document.documentElement; // Accent const acc = { champagne: { '--accent': '#C9A86A', '--accent-deep': '#9C7C3C' }, rose: { '--accent': '#C8A29A', '--accent-deep': '#A07467' }, platinum: { '--accent': '#B6B6B2', '--accent-deep': '#7E7E78' }, }[t.accent] || {}; Object.entries(acc).forEach(([k, v]) => root.style.setProperty(k, v)); // Mode root.classList.toggle('dark', t.mode === 'noir'); // Display font const display = { cormorant: '"Cormorant Garamond", serif', playfair: '"Playfair Display", serif', italiana: '"Italiana", serif', }[t.display]; root.style.setProperty('--display-font', display); } function useTweaks() { const [t, setT] = useState(loadTweaks); useEffect(() => { applyTweaks(t); saveTweaks(t); }, [t]); // Cross-tab/page sync useEffect(() => { const onStorage = (e) => { if (e.key === TWEAK_KEY) setT(loadTweaks()); }; window.addEventListener('storage', onStorage); return () => window.removeEventListener('storage', onStorage); }, []); return [t, (patch) => setT(prev => ({ ...prev, ...patch }))]; } // ---------- SVG Logo ---------- function Logo({ size = 'md' }) { const fontSize = size === 'sm' ? 18 : size === 'lg' ? 38 : 24; const subSize = size === 'sm' ? 7 : size === 'lg' ? 11 : 8; // Stylized crown above QUEEN return ( React.createElement('div', { className: 'qd-logo' }, React.createElement('svg', { width: fontSize * 1.3, height: fontSize * 0.55, viewBox: '0 0 60 22', fill: 'none' }, // crown: three peaks connected React.createElement('path', { d: 'M5 18 L12 4 L20 14 L30 2 L40 14 L48 4 L55 18', stroke: 'currentColor', strokeWidth: 1.2, fill: 'none', style: { color: 'var(--navy)' }, }), React.createElement('line', { x1: 4, y1: 19.5, x2: 56, y2: 19.5, stroke: 'currentColor', strokeWidth: 1.2, style: { color: 'var(--navy)' } }), ), React.createElement('div', { className: 'word', style: { fontSize: fontSize + 'px' } }, 'QUEEN'), React.createElement('div', { className: 'sub', style: { fontSize: subSize + 'px' } }, 'DIAMONDS'), ) ); } // ---------- Icons ---------- const Icons = { whatsapp: (props) => React.createElement('svg', { viewBox: '0 0 32 32', fill: 'currentColor', ...props }, React.createElement('path', { d: 'M16 3C8.8 3 3 8.8 3 16c0 2.3.6 4.5 1.7 6.4L3 29l6.8-1.7c1.8 1 3.9 1.5 6.2 1.5 7.2 0 13-5.8 13-13S23.2 3 16 3zm0 23.7c-2 0-3.9-.5-5.5-1.5l-.4-.2-4.1 1 1.1-3.9-.3-.4c-1.1-1.7-1.6-3.7-1.6-5.7 0-5.9 4.9-10.7 10.8-10.7s10.8 4.8 10.8 10.7-4.9 10.7-10.8 10.7zm6-7.9c-.3-.2-1.9-.9-2.2-1-.3-.1-.5-.2-.7.2-.2.3-.8 1-1 1.2-.2.2-.4.2-.7.1-.3-.2-1.3-.5-2.5-1.5-.9-.8-1.5-1.8-1.7-2.1-.2-.3 0-.5.1-.6.1-.1.3-.4.5-.5.2-.2.2-.3.3-.5.1-.2 0-.4 0-.5l-1-2.5c-.3-.6-.5-.5-.7-.5h-.6c-.2 0-.5.1-.8.4-.3.3-1 1-1 2.4 0 1.4 1 2.8 1.2 3 .2.2 2 3.1 4.9 4.4.7.3 1.2.5 1.6.6.7.2 1.3.2 1.8.1.5-.1 1.7-.7 2-1.4.2-.6.2-1.2.2-1.3-.2-.3-.4-.4-.7-.6z' }), ), pin: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('path', { d: 'M12 21s-7-7.5-7-12a7 7 0 0114 0c0 4.5-7 12-7 12z' }), React.createElement('circle', { cx: 12, cy: 9, r: 2.5 }), ), diamond: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('path', { d: 'M5 9l3-5h8l3 5-7 11z' }), React.createElement('path', { d: 'M5 9h14' }), React.createElement('path', { d: 'M8 4l4 16M16 4l-4 16' }), ), cert: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('circle', { cx: 12, cy: 10, r: 6 }), React.createElement('path', { d: 'M9 15l-2 6 5-3 5 3-2-6' }), ), star: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'currentColor', ...props }, React.createElement('path', { d: 'M12 2l3 6.5 7 1-5 5 1.2 7L12 18l-6.2 3.5L7 14.5l-5-5 7-1z' }), ), arrow: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('path', { d: 'M5 12h14M13 6l6 6-6 6' }), ), chev: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('path', { d: 'M9 6l6 6-6 6' }), ), phone: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('path', { d: 'M5 4h4l2 5-3 2a14 14 0 006 6l2-3 5 2v4a2 2 0 01-2 2A17 17 0 013 6a2 2 0 012-2z' }), ), clock: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('circle', { cx: 12, cy: 12, r: 9 }), React.createElement('path', { d: 'M12 7v5l3 2' }), ), ig: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, ...props }, React.createElement('rect', { x: 3, y: 3, width: 18, height: 18, rx: 4 }), React.createElement('circle', { cx: 12, cy: 12, r: 4 }), React.createElement('circle', { cx: 17.5, cy: 6.5, r: 0.8, fill: 'currentColor' }), ), }; // ---------- Top strip ---------- function TopStrip() { return React.createElement('div', { className: 'topstrip' }, React.createElement('div', { className: 'row' }, React.createElement('div', null, React.createElement('span', null, 'Shop 28 · Gold & Diamond Park · Dubai'), React.createElement('span', { className: 'dot' }), React.createElement('span', null, 'Open today 10:00 – 21:00'), ), React.createElement('div', null, React.createElement('a', { href: 'tel:+97143978786' }, '+971 4 397 8786'), React.createElement('span', { className: 'dot' }), React.createElement('a', { href: 'https://wa.me/971568747327', target: '_blank' }, 'WhatsApp'), React.createElement('span', { className: 'dot' }), React.createElement('a', { href: 'https://www.instagram.com/queendiamondsdubai/', target: '_blank' }, '@queendiamondsdubai'), ), ), ); } // ---------- Navbar ---------- function Navbar({ current, onConsult }) { const link = (href, label, id) => React.createElement('a', { href, className: current === id ? 'current' : '' }, label); return React.createElement('nav', { className: 'nav' }, React.createElement('div', { className: 'row' }, React.createElement('div', { className: 'links' }, link('collections.html', 'Collections', 'collections'), link('bespoke.html', 'Bespoke', 'bespoke'), link('index.html#education', 'The 4Cs'), link('index.html#testimonials', 'Reviews'), link('visit.html', 'Visit', 'visit'), ), React.createElement('a', { href: 'index.html', className: 'logo', 'aria-label': 'Queen Diamonds home' }, React.createElement(Logo, { size: 'md' }), ), React.createElement('div', { className: 'actions' }, React.createElement('a', { className: 'btn btn-text', href: 'https://wa.me/971568747327', target: '_blank' }, 'WhatsApp'), React.createElement('button', { className: 'btn btn-primary btn-sm', onClick: onConsult }, 'Book Consultation'), ), ), ); } // ---------- Footer ---------- function Footer() { return React.createElement('footer', { className: 'footer' }, React.createElement('div', { className: 'container' }, React.createElement('div', { className: 'footer-grid' }, React.createElement('div', { className: 'brand' }, React.createElement(Logo, { size: 'md' }), React.createElement('p', null, 'One of the finest jewellers in Dubai — diamond, gold & platinum jewellery, made by hand for the Heart.'), React.createElement('div', { style: { display: 'flex', gap: 14, marginTop: 20 } }, React.createElement('a', { href: 'https://www.instagram.com/queendiamondsdubai/', target: '_blank', 'aria-label': 'Instagram' }, React.createElement(Icons.ig, { width: 20, height: 20 })), ), ), React.createElement('div', null, React.createElement('h4', null, 'Discover'), React.createElement('ul', null, React.createElement('li', null, React.createElement('a', { href: 'collections.html' }, 'Collections')), React.createElement('li', null, React.createElement('a', { href: 'collections.html?cat=engagement' }, 'Engagement & Bridal')), React.createElement('li', null, React.createElement('a', { href: 'bespoke.html' }, 'Bespoke')), React.createElement('li', null, React.createElement('a', { href: 'index.html#education' }, 'The 4Cs')), ), ), React.createElement('div', null, React.createElement('h4', null, 'House'), React.createElement('ul', null, React.createElement('li', null, React.createElement('a', { href: 'index.html#about' }, 'About')), React.createElement('li', null, React.createElement('a', { href: 'index.html#testimonials' }, 'Reviews')), React.createElement('li', null, React.createElement('a', { href: 'visit.html' }, 'Visit the Showroom')), React.createElement('li', null, React.createElement('a', { href: 'https://www.tripadvisor.com/Attraction_Review-g295424-d20348717', target: '_blank' }, 'Tripadvisor')), ), ), React.createElement('div', null, React.createElement('h4', null, 'Contact'), React.createElement('ul', null, React.createElement('li', null, 'Shop 28, Building 1'), React.createElement('li', null, 'Gold & Diamond Park'), React.createElement('li', null, 'Sheikh Zayed Road, Dubai'), React.createElement('li', { style: { marginTop: 10 } }, React.createElement('a', { href: 'tel:+97143978786' }, '+971 4 397 8786')), React.createElement('li', null, React.createElement('a', { href: 'https://wa.me/971568747327', target: '_blank' }, 'WhatsApp +971 56 874 7327')), ), ), ), React.createElement('div', { className: 'footer-bottom' }, React.createElement('div', null, '© Queen Diamonds FZCO · A Dubai Gold & Diamond Park atelier'), React.createElement('div', null, 'GIA / IGI certified · Natural & lab-grown · 18K gold & platinum'), ), ), ); } // ---------- WhatsApp FAB ---------- function WhatsAppFab() { return React.createElement('a', { className: 'wa-fab', href: 'https://wa.me/971568747327?text=Hi%20Queen%20Diamonds%2C%20I%27d%20like%20to%20enquire', target: '_blank', 'aria-label': 'Chat on WhatsApp', }, React.createElement(Icons.whatsapp, null)); } // ---------- Tweaks Panel ---------- function TweaksPanel({ tweaks, setTweak }) { const [open, setOpen] = useState(false); useEffect(() => { const onMsg = (e) => { if (e.data?.type === '__activate_edit_mode') setOpen(true); if (e.data?.type === '__deactivate_edit_mode') setOpen(false); }; window.addEventListener('message', onMsg); window.parent.postMessage({ type: '__edit_mode_available' }, '*'); return () => window.removeEventListener('message', onMsg); }, []); if (!open) return null; const close = () => { setOpen(false); window.parent.postMessage({ type: '__edit_mode_dismissed' }, '*'); }; const Row = ({ label, children }) => React.createElement('div', { className: 'tweaks-row' }, React.createElement('div', { className: 'lbl' }, label), children, ); const Swatch = ({ id, color, current }) => React.createElement('button', { className: 'swatch' + (current === id ? ' active' : ''), style: { background: color }, onClick: () => setTweak({ accent: id }), 'aria-label': id, }); const Opt = ({ k, v, current, label }) => React.createElement('button', { className: 'opt' + (current === v ? ' active' : ''), onClick: () => setTweak({ [k]: v }), }, label); return React.createElement('div', { className: 'tweaks' }, React.createElement('div', { className: 'tweaks-title' }, 'Tweaks', React.createElement('button', { onClick: close, 'aria-label': 'close' }, '×'), ), React.createElement(Row, { label: 'Accent metal' }, React.createElement('div', { className: 'opts' }, React.createElement(Swatch, { id: 'champagne', color: '#C9A86A', current: tweaks.accent }), React.createElement(Swatch, { id: 'rose', color: '#C8A29A', current: tweaks.accent }), React.createElement(Swatch, { id: 'platinum', color: '#B6B6B2', current: tweaks.accent }), ), ), React.createElement(Row, { label: 'Background' }, React.createElement('div', { className: 'opts' }, React.createElement(Opt, { k: 'mode', v: 'ivory', current: tweaks.mode, label: 'Ivory' }), React.createElement(Opt, { k: 'mode', v: 'noir', current: tweaks.mode, label: 'Noir' }), ), ), React.createElement(Row, { label: 'Display type' }, React.createElement('div', { className: 'opts' }, React.createElement(Opt, { k: 'display', v: 'cormorant', current: tweaks.display, label: 'Cormorant' }), React.createElement(Opt, { k: 'display', v: 'playfair', current: tweaks.display, label: 'Playfair' }), React.createElement(Opt, { k: 'display', v: 'italiana', current: tweaks.display, label: 'Italiana' }), ), ), ); } // ---------- Consultation modal ---------- function ConsultationModal({ open, onClose }) { const [submitted, setSubmitted] = useState(false); const [data, setData] = useState({ name: '', contact: '', interest: '', date: '', note: '' }); const interests = ['Engagement', 'Wedding bands', 'Bespoke design', 'Gift', 'Other']; useEffect(() => { if (open) setSubmitted(false); }, [open]); const submit = (e) => { e.preventDefault(); setSubmitted(true); }; return React.createElement('div', { className: 'modal-backdrop' + (open ? ' open' : ''), onClick: onClose }, React.createElement('div', { className: 'modal', onClick: e => e.stopPropagation() }, React.createElement('button', { className: 'x', onClick: onClose, 'aria-label': 'close' }, '×'), submitted ? React.createElement('div', { className: 'thanks' }, React.createElement('div', { className: 'check' }, '✓'), React.createElement('h2', null, 'See you soon.'), React.createElement('p', { className: 'sub' }, 'We\'ll confirm your appointment by WhatsApp within the hour, between 10am and 9pm Dubai time.'), React.createElement('a', { className: 'btn btn-text', href: 'https://wa.me/971568747327', target: '_blank' }, 'Or reach us now on WhatsApp'), ) : React.createElement('form', { onSubmit: submit }, React.createElement('div', { className: 'eyebrow', style: { marginBottom: 6 } }, 'Private consultation'), React.createElement('h2', null, 'Book a visit'), React.createElement('p', { className: 'sub' }, 'A relaxed, one-to-one appointment in the showroom or by video. No obligation.'), React.createElement('div', { className: 'field-row' }, React.createElement('div', { className: 'field' }, React.createElement('label', null, 'Your name'), React.createElement('input', { required: true, value: data.name, onChange: e => setData({ ...data, name: e.target.value }) }), ), React.createElement('div', { className: 'field' }, React.createElement('label', null, 'WhatsApp or phone'), React.createElement('input', { required: true, value: data.contact, onChange: e => setData({ ...data, contact: e.target.value }), placeholder: '+971 ...' }), ), ), React.createElement('div', { className: 'field' }, React.createElement('label', null, 'I\'m interested in'), React.createElement('div', { className: 'chip-group', style: { marginTop: 8 } }, ...interests.map(i => React.createElement('button', { type: 'button', key: i, className: 'chip' + (data.interest === i ? ' active' : ''), onClick: () => setData({ ...data, interest: i }), }, i), ), ), ), React.createElement('div', { className: 'field' }, React.createElement('label', null, 'Preferred date or time (optional)'), React.createElement('input', { value: data.date, onChange: e => setData({ ...data, date: e.target.value }), placeholder: 'e.g. Saturday afternoon' }), ), React.createElement('div', { className: 'field' }, React.createElement('label', null, 'A note for the team (optional)'), React.createElement('textarea', { value: data.note, onChange: e => setData({ ...data, note: e.target.value }), rows: 3 }), ), React.createElement('div', { style: { display: 'flex', gap: 12, marginTop: 24 } }, React.createElement('button', { type: 'submit', className: 'btn btn-primary' }, 'Request appointment'), React.createElement('a', { className: 'btn btn-text', href: 'https://wa.me/971568747327', target: '_blank' }, 'Or chat on WhatsApp →'), ), ), ), ); } // ---------- Shell wrapper: includes nav/footer/fab/tweaks ---------- function Shell({ current, children }) { const [tweaks, setTweak] = useTweaks(); const [consult, setConsult] = useState(false); return React.createElement(React.Fragment, null, React.createElement(TopStrip, null), React.createElement(Navbar, { current, onConsult: () => setConsult(true) }), React.createElement('main', null, typeof children === 'function' ? children({ openConsult: () => setConsult(true) }) : children, ), React.createElement(Footer, null), React.createElement(WhatsAppFab, null), React.createElement(TweaksPanel, { tweaks, setTweak }), React.createElement(ConsultationModal, { open: consult, onClose: () => setConsult(false) }), ); } // Live Google Maps embed used on home + visit. function MapTile() { return React.createElement('div', { className: 'map-tile' }, React.createElement('iframe', { title: 'Google Maps for Queen Diamonds at Gold & Diamond Park', src: 'https://www.google.com/maps?q=Queen%20Diamonds%20Shop%2028%20Building%201%20Gold%20and%20Diamond%20Park%20Dubai&z=16&output=embed', loading: 'lazy', referrerPolicy: 'no-referrer-when-downgrade', }), ); } // Expose globals Object.assign(window, { Logo, Icons, TopStrip, Navbar, Footer, WhatsAppFab, TweaksPanel, ConsultationModal, Shell, MapTile, useTweaks, loadTweaks, applyTweaks, }); // Apply tweaks ASAP on page load (before React mounts) to avoid flash applyTweaks(loadTweaks());