/* Royal Yachts — main app */
const { useState: useS, useEffect: useE, useRef: useR } = React;
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"palette": "editorial",
"density": "comfortable",
"displayItalic": true,
"showFavBar": true,
"displayFont": "cormorant"
}/*EDITMODE-END*/;
const PALETTES = {
editorial: { /* warm paper editorial — DEFAULT */
"--paper": "#F8F6F1",
"--mist": "#ECE7DD",
"--ink": "#10202E",
"--marine":"#123A5A",
"--noir": "#07121C",
"--foam": "#FAFAF7",
"--brass": "#B89263",
"--brass-deep": "#8E6B3F"
},
marine: { /* cool marine — paper white + deep navy */
"--paper": "#F2F4F6",
"--mist": "#E3E9EE",
"--ink": "#0E2032",
"--marine":"#143C5C",
"--noir": "#05111C",
"--foam": "#F8FAFB",
"--brass": "#9CB1C4",
"--brass-deep": "#5A748A"
},
midnight: { /* full dark editorial */
"--paper": "#0A1620",
"--mist": "#0F1F2C",
"--ink": "#E8EEF2",
"--marine":"#7BA3C9",
"--noir": "#040A12",
"--foam": "#0D1A24",
"--brass": "#D3AC74",
"--brass-deep": "#B89263"
}
};
const DISPLAY_FONTS = {
cormorant: '"Cormorant Garamond", "EB Garamond", Georgia, serif',
playfair: '"Playfair Display", "EB Garamond", Georgia, serif',
ebgaramond:'"EB Garamond", Georgia, serif'
};
function applyTweaks(t) {
const r = document.documentElement;
const p = PALETTES[t.palette] || PALETTES.editorial;
Object.entries(p).forEach(([k, v]) => r.style.setProperty(k, v));
// Recompute line/muted from ink so they stay readable
if (t.palette === "midnight") {
r.style.setProperty("--line", "rgba(232,238,242,0.14)");
r.style.setProperty("--line-strong", "rgba(232,238,242,0.34)");
r.style.setProperty("--muted", "rgba(232,238,242,0.62)");
} else {
r.style.setProperty("--line", "rgba(16,32,46,0.14)");
r.style.setProperty("--line-strong", "rgba(16,32,46,0.32)");
r.style.setProperty("--muted", "rgba(16,32,46,0.62)");
}
r.style.setProperty("--font-display", DISPLAY_FONTS[t.displayFont] || DISPLAY_FONTS.cormorant);
r.style.setProperty("--section-pad", t.density === "tight" ? "72px" : t.density === "lavish" ? "128px" : "96px");
}
/* ---------- Toast ---------- */
function Toast({ msg, show }) {
return (
{msg}
);
}
/* ---------- Main App ---------- */
function App() {
const [tweaks, setTweaks] = useTweaks(TWEAK_DEFAULTS);
const [lang, setLang] = useS("en");
const [favs, setFavs] = useS(() => {
try { return JSON.parse(localStorage.getItem("ry_favs") || "[]"); } catch { return []; }
});
const [enquire, setEnquire] = useS({ open: false, payload: null });
const [drawer, setDrawer] = useS({ open: false, yacht: null });
const [toast, setToast] = useS({ show: false, msg: "" });
const t = I18N[lang];
useE(() => { applyTweaks(tweaks); }, [tweaks]);
useE(() => {
document.body.setAttribute("dir", t.dir);
}, [lang]);
useE(() => { localStorage.setItem("ry_favs", JSON.stringify(favs)); }, [favs]);
const toggleFav = (id) => {
setFavs((f) => {
const has = f.includes(id);
if (has) {
setToast({ show: true, msg: "Removed from shortlist" });
} else {
setToast({ show: true, msg: "Added to shortlist · check the bottom-left" });
}
setTimeout(() => setToast((tt) => ({ ...tt, show: false })), 2400);
return has ? f.filter((x) => x !== id) : [...f, id];
});
};
const openEnquire = (payload = {}) => setEnquire({ open: true, payload });
const closeEnquire = () => setEnquire({ open: false, payload: null });
const openYacht = (yacht) => { setDrawer({ open: true, yacht }); document.body.style.overflow = "hidden"; };
const closeYacht = () => { setDrawer({ open: false, yacht: drawer.yacht }); document.body.style.overflow = ""; };
return (
document.getElementById("fleet").scrollIntoView({behavior:"smooth"})}
onSales={() => document.getElementById("sales").scrollIntoView({behavior:"smooth"})}
t={t}
/>
{t.fleetEyebrow}
{t.fleetTitle} {t.fleetTitleItalic}
{t.fleetSub}
{FLEET.map((y, i) => (
))}
FLEET ROTATES SEASONALLY · 43 — 280 FT
{t.expEyebrow}
{t.expTitle} {t.expTitleItalic}
{t.expSub}
{t.destEyebrow}
{t.destTitle} {t.destTitleItalic}
{t.destSub}
{/* Floating UI */}
{ closeYacht(); openEnquire(p); }}
faved={drawer.yacht ? favs.includes(drawer.yacht.id) : false}
onFave={toggleFav}
/>
{}}
/>
{/* Sticky CTAs */}
{tweaks.showFavBar && favs.length > 0 && (
{String(favs.length).padStart(2,"0")}
)}
{/* Tweaks panel */}
);
}
/* ---------- Tweaks panel ---------- */
function RyTweaks({ tweaks, setTweak }) {
return (
setTweak("palette", v)}
/>
setTweak("displayFont", v)}
/>
{
setTweak("displayItalic", v);
document.documentElement.style.setProperty("--italic-display", v ? "italic" : "normal");
document.querySelectorAll(".display .italic").forEach((el) => {
el.style.fontStyle = v ? "italic" : "normal";
});
}}
/>
setTweak("density", v)}
/>
setTweak("showFavBar", v)}
/>
);
}
Object.assign(window, { App, RyTweaks });
/* ---------- Mount ---------- */
ReactDOM.createRoot(document.getElementById("root")).render();