// clickinPMS Kiosk — shared primitives (flex-based layout) // Portrait 1080×1920 target. Every screen composes via : // - fixed top chrome (logo + language pills) // - vertical content column that FLOWS; gaps controlled by design tokens // - fixed bottom action row (primary CTA + optional back, always at safe-area) // No more hand-placed `top: 480px` — content centers and flows. // Design tokens for kiosk layout (all relative to 1080×1920 canvas) const KIOSK = { W: 1080, H: 1920, safeTop: 200, // below logo + lang pills safeBottom: 200, // above bottom CTA row gutter: 80, stackGap: 48, // default gap between stacked items fieldGap: 24, // grid gap within clusters }; function KioskShell({ children, hideLang, lang='SI', onLangChange }) { return (
{/* photo protection gradient */}
{/* Top chrome */}
{!hideLang && (
{['SI','EN','DE','IT'].map(c => ( ))}
)}
{/* Flow container - children render as rows; screens compose their own sections */}
{children}
); } // Vertical column that centers its children; gap & align are parameters. function KioskStack({ children, gap=KIOSK.stackGap, align='center', justify='center', flex=1, style }) { return (
{children}
); } // Horizontal row with default centered layout. function KioskRow({ children, gap=40, justify='center', align='center', style }) { return (
{children}
); } // Action bar pinned to the bottom; holds primary CTA + optional back. function KioskActionBar({ back, children, style }) { return (
{back && }
{children}
); } function KioskHero({ children, size=128, muted=false }) { return (
{children}
); } function KioskSubhead({ children, size=44 }) { return (
{children}
); } function KioskButton({ variant='primary', size='hero', onClick, children, style }) { const palette = { primary: { bg:'#00BCD4', hover:'#0097A7', color:'#fff', border:'2px solid transparent', shadow:'0 16px 40px rgba(0,188,212,.4), 0 4px 12px rgba(0,188,212,.3)' }, action: { bg:'#2196F3', hover:'#1976D2', color:'#fff', border:'2px solid transparent', shadow:'0 16px 40px rgba(33,150,243,.4)' }, staff: { bg:'#FFB300', hover:'#FB8C00', color:'#1A1A1A', border:'2px solid transparent', shadow:'0 16px 40px rgba(255,179,0,.4)' }, ghost: { bg:'rgba(255,255,255,0.12)', hover:'rgba(255,255,255,0.22)', color:'#fff', border:'2px solid rgba(255,255,255,.45)', shadow:'0 4px 20px rgba(0,0,0,.3)' }, }[variant]; const sizing = size==='hero' ? { padding:'28px 96px', fontSize:52, borderRadius:40, minWidth:340 } : size==='lg' ? { padding:'24px 56px', fontSize:36, borderRadius:32, minWidth:240 } : { padding:'18px 40px', fontSize:28, borderRadius:24, minWidth:180 }; const [h, setH] = React.useState(false); const [p, setP] = React.useState(false); return ( ); } function BackButton({ onClick }) { const [h, setH] = React.useState(false); return ( ); } function FlagCircle({ code, selected, onClick, size=220 }) { const flags = { SI: (
), GB: (
), DE: (
), IT: (
), }; return ( ); } Object.assign(window, { KIOSK, KioskShell, KioskStack, KioskRow, KioskActionBar, KioskHero, KioskSubhead, KioskButton, BackButton, FlagCircle, });