// components.jsx — shared site primitives & chrome const { useState, useEffect, useRef } = React; function Icon({ name, size = 18, color, style }) { return ; } function refreshIcons() { if (window.lucide) window.lucide.createIcons({ attrs: { "stroke-width": 1.6 } }); } function useIcons(dep) { useEffect(() => { refreshIcons(); }); } function Container({ children, width = 1200, style, className }) { return
{children}
; } function Eyebrow({ children, light, style }) { return ( {children} ); } function GoldRule({ style }) { return
; } function Button({ children, variant = "primary", size = "md", href, onClick, icon, iconLeft, target, download, style }) { const [hover, setHover] = useState(false); const base = { fontFamily: "var(--font-sans)", fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase", fontSize: size === "sm" ? 11 : 13, padding: size === "sm" ? "10px 18px" : "15px 28px", borderRadius: "var(--radius-md)", border: 0, cursor: "pointer", transition: "all var(--dur-base) var(--ease-out)", display: "inline-flex", alignItems: "center", gap: 9, whiteSpace: "nowrap", textDecoration: "none", }; const variants = { primary: { background: "var(--gold-metallic)", color: "var(--ink-900)", boxShadow: "var(--shadow-gold)" }, dark: { background: "var(--ink-900)", color: "var(--gold-300)" }, outline: { background: "transparent", color: "var(--ink-800)", border: "1.5px solid var(--ink-700)" }, outlineLight: { background: "transparent", color: "var(--gold-200)", border: "1.5px solid var(--gold-500)" }, ghost: { background: "transparent", color: "var(--ink-800)", padding: size === "sm" ? "10px 6px" : "15px 6px" }, }; const hov = hover ? ( variant === "primary" ? { transform: "translateY(-1px)", boxShadow: "0 10px 30px rgba(255,208,48,0.45)", filter: "brightness(1.04)" } : variant === "outline" ? { background: "var(--ink-900)", color: "var(--gold-300)", borderColor: "var(--ink-900)" } : variant === "outlineLight" ? { background: "rgba(255,208,48,0.12)" } : variant === "dark" ? { filter: "brightness(1.15)" } : { color: "var(--gold-700)" } ) : {}; const Tag = href ? "a" : "button"; return ( setHover(true)} onMouseLeave={() => setHover(false)} style={{ ...base, ...variants[variant], ...hov, ...style }}> {iconLeft && } {children} {icon && } ); } function SectionHead({ eyebrow, title, lead, light, align = "left", maxTitle = 720 }) { return (
{eyebrow && {eyebrow}}

{title}

{lead &&

{lead}

}
); } // Image placeholder — styled, with caption. (Real images get dropped in later.) function Placeholder({ label, ratio = "4 / 3", dark, icon = "image", style }) { return (
{label && {label}}
); } // Privacy-friendly click-to-load (Option A / DSGVO): renders a branded placeholder; // the third-party iframe (YouTube, Google Calendar, OSM map) is injected ONLY after // the visitor explicitly clicks — so no data (and no external preview image) reaches // the provider before consent. function ClickToLoad({ src, title, ratio, height, label, note, icon = "play", dark = true, allow, autoplayParam }) { const [loaded, setLoaded] = useState(false); const box = { position: "relative", width: "100%", ...(ratio ? { aspectRatio: ratio } : (height ? { height } : { height: "100%" })), background: dark ? "#000" : "var(--ink-100)" }; if (loaded) { const finalSrc = autoplayParam ? src + (src.includes("?") ? "&" : "?") + autoplayParam : src; return (
); } return ( ); } const NAV_LINKS = [ ["start", "index.html"], ["leistungen", "leistungen.html"], ["kooperation", "kooperation.html"], ["onboarding", "onboarding.html"], ["fortbildungen", "fortbildungen.html"], ["ueber", "ueber-uns.html"], ["kontakt", "kontakt.html"], ]; function LangToggle({ light }) { const cur = window.getLang(); const c = light ? "var(--fg-on-dark-muted)" : "var(--fg-muted)"; return (
{["de", "en"].map((l, i) => ( {i === 1 && /} ))}
); } function Nav({ active }) { const [scrolled, setScrolled] = useState(false); const [open, setOpen] = useState(false); useEffect(() => { const f = () => setScrolled(window.scrollY > 30); f(); window.addEventListener("scroll", f); return () => window.removeEventListener("scroll", f); }, []); const phone = t("contactData.phone"); const tel = "tel:" + phone.replace(/\s/g, ""); return (
Bade Zahntechnik Bade Zahntechnik
{NAV_LINKS.concat([["fotostatus", "fotostatus.html"]]).map(([key, href]) => ( {t("nav." + key)} ))}
); } function Footer() { return ( ); } const fcTitle = { fontFamily: "var(--font-sans)", fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--gold-600)", margin: "0 0 16px" }; const fcItem = { fontFamily: "var(--font-sans)", fontSize: 14, color: "var(--fg-on-dark-muted)", textDecoration: "none" }; const socialBtn = { width: 38, height: 38, borderRadius: "50%", border: "1px solid var(--line-on-dark)", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--gold-300)", textDecoration: "none" }; function FooterCol({ title, items }) { return (

{title}

{items.map(([label, href], i) => {label})}
); } function PageHeader({ eyebrow, title, lead }) { return (
); } function Page({ active, children }) { useIcons(); return (
); } Object.assign(window, { Icon, refreshIcons, useIcons, Container, Eyebrow, GoldRule, Button, SectionHead, Placeholder, ClickToLoad, Nav, Footer, Page, PageHeader, LangToggle });