// Primitives — Wohnung Prags const Eyebrow = ({ children, tone = "mute", style }) => { const colors = { mute: "var(--fg-muted)", muteDark: "rgba(245,241,234,0.62)", gold: "var(--gold)" }; return ( {children}); }; const Diamond = ({ size = 6, color = "var(--gold)", style }) => ; const HairlineGold = ({ width = 56, style }) => ; const RuleDiamond = ({ color = "var(--gold)", maxWidth = 220, style }) =>
; // Renders an array of strings as stacked headline lines. // Strings may contain ... for italic-gold emphasis. const Headline = ({ lines, size = 72, light = false, style }) =>

{lines.map((ln, i) => )}

; // Reveal-on-scroll wrapper. Adds a soft fade+rise as the element enters viewport. const Reveal = ({ children, delay = 0, y = 24, style }) => { const ref = React.useRef(null); const [seen, setSeen] = React.useState(false); React.useEffect(() => { if (!ref.current) return; const obs = new IntersectionObserver( (entries) => entries.forEach((e) => {if (e.isIntersecting) {setSeen(true);obs.disconnect();}}), { threshold: 0.18, rootMargin: "0px 0px -10% 0px" } ); obs.observe(ref.current); return () => obs.disconnect(); }, []); return (
{children}
); }; // Photo plate with crop motion modes: static / kenburns / parallax. const Plate = ({ src, mode = "static", position = "center", aspect, height, style, children, overlay = false }) => { const ref = React.useRef(null); const [parallaxY, setParallaxY] = React.useState(0); React.useEffect(() => { if (mode !== "parallax") return; const onScroll = () => { if (!ref.current) return; const rect = ref.current.getBoundingClientRect(); const winH = window.innerHeight; const progress = (rect.top + rect.height / 2 - winH / 2) / winH; setParallaxY(-progress * 40); }; onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, [mode]); return (
{overlay &&
} {children}
); }; // Monogram SV·31 — typographic mark for St. Veit 31/B. const Monogram = ({ size = 44, light = false }) => { const c = light ? "var(--bone)" : "var(--ink)"; return ( ); }; // CTA button. const Button = ({ children, onClick, variant = "primary", dark = false, type = "button", as = "button", href }) => { const base = { display: "inline-flex", alignItems: "center", justifyContent: "center", fontFamily: "var(--font-sans)", fontSize: 11, fontWeight: 500, letterSpacing: "0.22em", textTransform: "uppercase", padding: "14px 26px", border: "1px solid", cursor: "pointer", background: "transparent", textDecoration: "none", transition: "background 280ms, color 280ms, border-color 280ms" }; const styles = { primary: dark ? { background: "var(--gold)", color: "var(--ink)", borderColor: "var(--gold)" } : { background: "var(--ink)", color: "var(--bone)", borderColor: "var(--ink)" }, ghost: dark ? { background: "transparent", color: "var(--bone)", borderColor: "rgba(245,241,234,0.5)" } : { background: "transparent", color: "var(--ink)", borderColor: "var(--ink)" } }; const Tag = as === "a" ? "a" : "button"; return ( {children}); }; Object.assign(window, { Eyebrow, Diamond, HairlineGold, RuleDiamond, Headline, Reveal, Plate, Monogram, Button });