const { useState, useEffect, useRef } = React; const PALETTES = { sand: { bg: "#f6f1e8", surface: "#fbf8f2", ink: "#1a1814", muted: "#6b6253", line: "#e3dccd", accent: "#8a6f3f", accentInk: "#fbf8f2" }, weiss: { bg: "#ffffff", surface: "#f7f7f5", ink: "#111111", muted: "#666666", line: "#e6e6e3", accent: "#1a1a1a", accentInk: "#ffffff" }, marine: { bg: "#eef2f6", surface: "#f7fafc", ink: "#0a1f33", muted: "#4a5d70", line: "#cfd9e3", accent: "#1e3a5f", accentInk: "#f7fafc" }, como: { bg: "#f5f1e8", surface: "#faf6ec", ink: "#1c2a1f", muted: "#5a6a55", line: "#dcd5c2", accent: "#2d4a32", accentInk: "#faf6ec" } }; const TYPO = { sans: { display: "'Inter', sans-serif", body: "'Inter', sans-serif" }, didone: { display: "'Playfair Display', 'Bodoni Moda', Georgia, serif", body: "'Inter', sans-serif" }, editorial: { display: "'Cormorant Garamond', Georgia, serif", body: "'Inter', sans-serif" } }; const IMG = { hero: "photos/villa-pool-bay.jpg", villa1: "photos/villa-pool-loungers.jpg", location: "photos/villa-pool-islands.jpg" }; // Galerie-Sektionen mit echten Bildern. Innenräume + Suiten sind Platzhalter, // bis Innen-Fotos hochgeladen werden. const GALLERY = { exterior: [ { id: "ext-1", url: "photos/villa-aerial-front.jpg", aspect: "wide" }, { id: "ext-2", url: "photos/villa-aerial-bay.jpg", aspect: "tall" }, { id: "ext-3", url: "photos/villa-aerial-overview.jpg", aspect: "wide" }, { id: "ext-4", url: "photos/villa-architecture.jpg", aspect: "square" }, { id: "ext-5", url: "photos/villa-entrance.jpg", aspect: "square" } ], pool: [ { id: "pool-1", url: "photos/villa-pool-bay.jpg", aspect: "wide" }, { id: "pool-2", url: "photos/villa-pool-loungers.jpg", aspect: "tall" }, { id: "pool-3", url: "photos/villa-pool-islands.jpg", aspect: "tall" }, { id: "pool-4", url: "photos/villa-pool-side.jpg", aspect: "wide" }, { id: "pool-5", url: "photos/villa-pool-distant.jpg", aspect: "square" } ], interior: [ { id: "int-1", url: "photos/villa-living-pano.jpg", aspect: "wide" }, { id: "int-2", url: "photos/villa-living-room.jpg", aspect: "square" }, { id: "int-3", url: "photos/villa-staircase.jpg", aspect: "tall" }, { id: "int-4", url: "photos/villa-kitchen-island.jpg", aspect: "wide" }, { id: "int-5", url: "photos/villa-living-sea.jpg", aspect: "square" } ], bedrooms: [ { id: "bed-1", url: "photos/villa-bedroom-master.jpg", aspect: "wide" }, { id: "bed-2", url: "photos/villa-bedroom-seaview.jpg", aspect: "tall" }, { id: "bed-3", url: "photos/villa-bedroom-sea.jpg", aspect: "square" }, { id: "bed-4", url: "photos/villa-bedroom-orange.jpg", aspect: "square" }, { id: "bed-5", url: "photos/villa-hallway.jpg", aspect: "wide" } ], details: [ { id: "det-1", url: "photos/villa-bathroom-shower.jpg", aspect: "square" }, { id: "det-2", url: "photos/villa-bath-detail.jpg", aspect: "tall" }, { id: "det-3", url: "photos/villa-sofa-detail.jpg", aspect: "wide" }, { id: "det-4", url: "photos/villa-dining-sea.jpg", aspect: "wide" }, { id: "det-5", url: "photos/villa-swallows.jpg", aspect: "square" } ] }; function App() { const [t, setTweak] = useTweaks(window.TWEAK_DEFAULTS); const [lang, setLang] = useState("en"); const [scrolled, setScrolled] = useState(false); const [submitted, setSubmitted] = useState(false); const [menuOpen, setMenuOpen] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 60); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); const dict = window.I18N[lang]; const palette = PALETTES[t.palette] || PALETTES.sand; const typo = TYPO[t.typo] || TYPO.serif; const cssVars = { "--bg": palette.bg, "--surface": palette.surface, "--ink": palette.ink, "--muted": palette.muted, "--line": palette.line, "--accent": palette.accent, "--accent-ink": palette.accentInk, "--font-display": typo.display, "--font-body": typo.body }; const scrollTo = (id) => { setMenuOpen(false); const el = document.getElementById(id); if (el) window.scrollTo({ top: el.offsetTop - 60, behavior: "smooth" }); }; useEffect(() => { document.documentElement.dir = lang === "ar" ? "rtl" : "ltr"; document.documentElement.lang = lang; }, [lang]); return (
); } const LANGS = [ { code: "en", cc: "gb", label: "English" }, { code: "de", cc: "de", label: "Deutsch" }, { code: "tr", cc: "tr", label: "Türkçe" }, { code: "ru", cc: "ru", label: "Русский" }, { code: "ar", cc: "sa", label: "العربية" }, { code: "zh", cc: "cn", label: "中文" }, ]; const Flag = ({ cc, alt }) => ( {alt ); function LangSwitcher({ lang, setLang }) { const [open, setOpen] = useState(false); const ref = useRef(null); useEffect(() => { const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }; document.addEventListener("mousedown", onDoc); return () => document.removeEventListener("mousedown", onDoc); }, []); const current = LANGS.find(l => l.code === lang) || LANGS[0]; return (
{open && ( )}
); } function Nav({ dict, lang, setLang, scrolled, scrollTo, menuOpen, setMenuOpen }) { const items = [["villa","villa"],["features","features"],["location","location"],["gallery","gallery"],["prices","prices"],["contact","contact"]]; return ( ); } function Hero({ dict, t, scrollTo }) { const split = t.heroLayout === "split"; const [muted, setMuted] = useState(true); return (
); } function QuickFacts({ dict }) { const items = [ { v: "4", l: dict.quickFacts.bedrooms }, { v: "8", l: dict.quickFacts.guests }, { v: "400", l: dict.quickFacts.size, suf: "m²" }, { v: "∞", l: dict.quickFacts.pool } ]; return (
{items.map((i, idx) => (
{i.v}{i.suf}
{i.l}
))}
); } function Villa({ dict }) { return (

{dict.villa.eyebrow}

{dict.villa.title}

{dict.villa.lead}

{dict.villa.p2}

); } function Features({ dict, scrollTo }) { // Map feature index -> gallery section anchor const targets = ["gal-pool","gal-exterior","gal-exterior","gal-details","gal-exterior","gal-interior"]; const thumbs = [ "photos/villa-pool-bay.jpg", "photos/villa-pool-loungers.jpg", "photos/villa-entrance.jpg", "photos/villa-bathroom-shower.jpg", "https://images.unsplash.com/photo-1567899378494-47b22a2ae96a?w=800&q=80", "https://images.unsplash.com/photo-1528207776546-365bb710ee93?w=800&q=80" ]; return (

{dict.features.eyebrow}

{dict.features.title}

{dict.features.items.map((f, i) => ( scrollTo(targets[i])}>
{String(i+1).padStart(2,"0")}

{f.title}

{f.desc}

))}
); } function LocationHero({ dict }) { return (

{dict.location.eyebrow}

{dict.location.title.toUpperCase()}

{dict.location.tagline}

); } function LocationDetail({ dict }) { return (

{dict.location.lead}

{dict.location.address &&

{dict.location.address}

}

{dict.location.story}