// Shared primitives for the SannaTrip site // Designed to work identically at mobile and desktop widths — consumer passes container width via CSS. // ── Placeholder imagery: striped SVG with a monospace label calling out what goes there ── function Imagery({ label, aspect = '3/2', tone = 'navy', mono = true, src, alt, objectPosition = 'center', style = {} }) { const tones = { navy: { bg: '#E8EDF3', stripe: '#D3DCE7', ink: '#1b3661' }, pink: { bg: '#F3E7EE', stripe: '#EAD7E1', ink: '#7A3A62' }, ivory: { bg: '#F0EADF', stripe: '#E5DCC9', ink: '#6B5A3B' }, moss: { bg: '#E5EAE2', stripe: '#D0D8CA', ink: '#3E5A3E' }, warm: { bg: '#EFE6DC', stripe: '#DFD1BD', ink: '#5C4A35' }, charcoal: { bg: '#2A2F36', stripe: '#353A42', ink: '#E8EAED' }, }[tone] || { bg: '#E8EDF3', stripe: '#D3DCE7', ink: '#1b3661' }; return (
{src && ( {alt )} {!src && mono && (
{label}
)}
); } // ── Eyebrow label (navy, uppercase, tracked) ── function Eyebrow({ children, color, style = {} }) { return (
{children}
); } // ── Editorial serif display title ── function Display({ children, size = 'lg', style = {} }) { const sizes = { xl: { fs: 'clamp(44px, 7vw, 88px)', lh: 0.95, wt: 340 }, lg: { fs: 'clamp(32px, 5vw, 56px)', lh: 1.02, wt: 360 }, md: { fs: 'clamp(24px, 3.5vw, 38px)', lh: 1.1, wt: 380 }, sm: { fs: 'clamp(20px, 2.4vw, 26px)', lh: 1.15, wt: 420 }, }[size]; return (

{children}

); } // ── Button (primary navy, secondary ghost, accent pink) ── function Btn({ children, variant = 'primary', size = 'md', style = {}, onClick, type }) { const sizes = { md: { pad: '14px 24px', fs: 14 }, lg: { pad: '18px 30px', fs: 15 }, sm: { pad: '10px 18px', fs: 13 }, }[size]; const variants = { primary: { background: TOKENS.color.navy, color: '#fff', border: `1px solid ${TOKENS.color.navy}`, }, ghost: { background: 'transparent', color: TOKENS.color.navy, border: `1px solid ${TOKENS.color.hairline}`, }, accent: { background: TOKENS.color.pink, color: TOKENS.color.navy, border: `1px solid ${TOKENS.color.pink}`, }, ink: { background: 'transparent', color: TOKENS.color.navy, border: 'none', padding: 0, textDecoration: 'underline', textUnderlineOffset: '4px', textDecorationColor: TOKENS.color.pink, textDecorationThickness: '1px', }, }[variant]; return ( ); } // ── Hairline rule ── function Rule({ color, style = {} }) { return
; } // ── Section container with configurable padding ── function Section({ children, bg, pad = 'lg', narrow = false, id, style = {} }) { const pads = { lg: 'clamp(48px, 9vw, 120px) clamp(20px, 5vw, 80px)', md: 'clamp(36px, 6vw, 80px) clamp(20px, 5vw, 80px)', }[pad]; return (
{children}
); } Object.assign(window, { Imagery, Eyebrow, Display, Btn, Rule, Section });