// Shared primitives — dark, minimal, lighter weights const { ArrowRight, ArrowDown, Plus } = window.Icons; const Container = ({children, style, className=""}) => (
{children}
); const Eyebrow = ({children, color='var(--pink)'}) => (
{children}
); const Btn = ({children, variant='primary', href='#', icon=true, size='md', onClick}) => { const sizes = { sm: {padding:'9px 18px', fontSize:12.5, gap:8}, md: {padding:'13px 24px', fontSize:13, gap:10}, lg: {padding:'17px 30px', fontSize:14, gap:12} }[size]; const base = { display:'inline-flex', alignItems:'center', ...sizes, borderRadius:99, fontWeight:500, letterSpacing:'0.005em', textDecoration:'none', border:'1px solid transparent', transition:'all .35s cubic-bezier(.2,.8,.2,1)', cursor:'pointer', whiteSpace:'nowrap', position:'relative', // Isolate so body film-grain / hero radial gradients can't bleed through via mix-blend-mode isolation:'isolate', transform:'translateZ(0)', backfaceVisibility:'hidden', }; const variants = { primary: { background:'linear-gradient(180deg, #FFA8CC 0%, #F47AAE 100%)', color:'#240914', border:'1px solid rgba(255,255,255,0.22)', boxShadow:'inset 0 1px 0 rgba(255,255,255,0.42), 0 10px 26px -10px rgba(255,127,181,0.55)', }, indigo: { background:'linear-gradient(180deg, #A797FF 0%, #7B5BF0 100%)', color:'#fff', border:'1px solid rgba(255,255,255,0.20)', boxShadow:'inset 0 1px 0 rgba(255,255,255,0.32), 0 10px 26px -10px rgba(138,107,255,0.55)', }, pink: { background:'linear-gradient(180deg, #FFA8CC 0%, #F47AAE 100%)', color:'#240914', border:'1px solid rgba(255,255,255,0.22)', boxShadow:'inset 0 1px 0 rgba(255,255,255,0.42), 0 10px 26px -10px rgba(255,127,181,0.55)', }, ghost: { background:'rgba(245,241,230,0.02)', color:'var(--fg)', border:'1px solid var(--line-strong)', boxShadow:'inset 0 1px 0 rgba(255,255,255,0.04)', }, dark: {background:'var(--bg-3)', color:'var(--fg)', border:'1px solid var(--line)'}, light: {background:'var(--fg)', color:'var(--bg)'}, }[variant]; return ( { const r = e.currentTarget.getBoundingClientRect(); const x = (e.clientX - r.left - r.width/2) * 0.12; const y = (e.clientY - r.top - r.height/2) * 0.12; e.currentTarget.style.transform = `translate(${x}px, ${y}px)`; }} onMouseLeave={e=>{e.currentTarget.style.transform = 'translate(0,0)';}}> {children} {icon && } ); }; // Soft tinted image placeholder const Placeholder = ({ratio='4/5', label='image', accent='indigo', style={}, children}) => { const colors = { indigo: ['#3A2E78','#231C49'], pink: ['#7A2C53','#4B1B33'], cream: ['#2A2538','#1F1B2A'], ink: ['#27232f','#1a1722'], }[accent]; return (
◐ {label}
{children}
); }; // Tag pill — subtler const Tag = ({children, tone='indigo'}) => { const tones = { indigo: {bg:'rgba(107,83,255,0.10)', fg:'#B8AAFF', bd:'rgba(107,83,255,0.24)'}, pink: {bg:'rgba(255,111,168,0.10)', fg:'#FFC2D8', bd:'rgba(255,111,168,0.24)'}, ink: {bg:'rgba(239,234,224,0.04)', fg:'var(--fg-2)', bd:'var(--line)'}, }[tone]; return ( {children} ); }; // Reveal-on-scroll wrapper — refined for smooth motion across all pages. // - Triggers slightly before fully entering view (rootMargin) for a natural feel // - On mount, anything already fully visible reveals immediately (no flash on reload mid-page) // - Once revealed, stays revealed (no re-trigger jitter when scrolling back up) const Reveal = ({children, delay=0, kind='reveal-up', as='div', style={}}) => { const ref = React.useRef(null); React.useEffect(()=>{ const el = ref.current; if(!el) return; // If reduce-motion preferred, just show immediately, no animation const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduce) { el.classList.add('in', 'no-anim'); return; } // If already in viewport at mount (e.g. above the fold, or scroll position restored), reveal immediately const rect = el.getBoundingClientRect(); const vh = window.innerHeight || document.documentElement.clientHeight; if (rect.top < vh * 0.85 && rect.bottom > 0) { // small RAF so it transitions in cleanly even when immediate requestAnimationFrame(()=> setTimeout(()=> el.classList.add('in'), Math.min(delay, 200))); return; } const io = new IntersectionObserver((entries)=>{ entries.forEach(e=>{ if(e.isIntersecting){ setTimeout(()=>el.classList.add('in'), delay); io.unobserve(el); } }); }, {threshold:0.08, rootMargin: '0px 0px -8% 0px'}); io.observe(el); return ()=>io.disconnect(); }, [delay]); const Tag = as; return {children}; }; // Word-by-word reveal — same robustness as Reveal const RevealWords = ({children, delay=0, gap=40}) => { const ref = React.useRef(null); React.useEffect(()=>{ const el = ref.current; if(!el) return; const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; const trigger = () => { const words = el.querySelectorAll('.word'); words.forEach((w,i)=>{ w.style.transitionDelay = `${delay + i*gap}ms`; }); el.classList.add('in'); }; if (reduce) { el.classList.add('in', 'no-anim'); return; } const rect = el.getBoundingClientRect(); const vh = window.innerHeight || document.documentElement.clientHeight; if (rect.top < vh * 0.85 && rect.bottom > 0) { requestAnimationFrame(()=> setTimeout(trigger, 50)); return; } const io = new IntersectionObserver((entries)=>{ entries.forEach(e=>{ if(e.isIntersecting){ trigger(); io.unobserve(el); } }); }, {threshold:0.1, rootMargin:'0px 0px -6% 0px'}); io.observe(el); return ()=>io.disconnect(); }, [delay,gap]); const splitText = (s) => s.split(/(\s+)/).map((p,i) => /\s/.test(p) ? p : {p}); const process = (node) => { if (typeof node === 'string') return splitText(node); if (Array.isArray(node)) return node.map(process); if (React.isValidElement(node)) { const newChildren = React.Children.map(node.props.children, ch => typeof ch === 'string' ? splitText(ch) : ch ); return React.cloneElement(node, {key: node.key}, newChildren); } return node; }; return {process(children)}; }; // Section opener — used at the top of each non-home page const PageOpener = ({eyebrow, title, accent, lead, bg, bgLabel}) => (
{bg && (
{/* Base photograph, slow drift */}
{/* Cinematic gradient — bottom-heavy for type, dark sky at top */}
{/* Magenta / violet film wash — gives the "Netflix India" cast */}
{/* Tight vignette */}
{/* Soft film grain — heavier than before */}
")` }}/>
)} {!bg && (<>
)} {eyebrow}

{title}

{lead && (

{lead}

)} {false && bgLabel && (
◐ {bgLabel}
)}
); window.Primitives = { Container, Eyebrow, Btn, Placeholder, Tag, Reveal, RevealWords, PageOpener };