/* Shared components & primitives — Cinco Ranch Village (JAL-JCP) */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ------------------------------------------------------------------ */
/*  Real deal data — CRV                                               */
/* ------------------------------------------------------------------ */
const DEAL = {
  sponsor: 'JAL-JCP Real Estate Partners',
  principals: [
    { name:'Justin A. Levine', email:'jlevine@jalstrategies.com', firm:'JAL-JCP Real Estate Partners' },
    { name:'James C. Pappas', email:'jcp@jcpinv.com', firm:'JAL-JCP Real Estate Partners' },
  ],
  property: 'Cinco Ranch Village',
  address: '23144 Cinco Ranch Blvd · Katy, TX 77494',
  gla: '20,155 SF',
  acres: 2.01,
  occupancy: '100%',
  tenants: 9,
  walt: '5.0 yrs',
  purchase: '$9,600,000',
  basis: '$9,796,000',
  basisPSF: '$476 / SF',
  capIn: '6.80%',
  noiY1: '$653,169',
  lpEquity: '$4,036,000',
  ltv: '60%',
  debt: '$5,760,000',
  rate: '6.00%',
  hold: 10,
  projIRR: '16.3%',
  projMult: '3.01×',
  lpIRR: '14.9%',
  lpMult: '2.66×',
  exitCap: '6.25%',
  exitGross: '$15,128,992',
  lpTotal: '$10,734,772',
  refiY5: '$2,757,708',
};

const PALETTES = {
  institutional: {
    name: 'Midnight',
    ivory:'#0A0A0A', ivory2:'#141414', ink:'#F4E9C8', ink2:'#EADFB8',
    muted:'#6E6A61', rule:'#2A2418', accent:'#D4A94A', accentSoft:'#B8872B',
  },
  editorial: {
    name: 'Aubergine',
    ivory:'#0A0A0A', ivory2:'#141414', ink:'#D4A94A', ink2:'#E8C76B',
    muted:'#6E6A61', rule:'#2A2418', accent:'#F4E9C8', accentSoft:'#B8872B',
  },
  verdant: {
    name: 'Slate',
    ivory:'#0A0A0A', ivory2:'#141414', ink:'#F4E9C8', ink2:'#EADFB8',
    muted:'#6E6A61', rule:'#2A2418', accent:'#B8872B', accentSoft:'#D4A94A',
  },
};

function applyPalette(key){
  const p = PALETTES[key] || PALETTES.institutional;
  const r = document.documentElement.style;
  r.setProperty('--ivory', p.ivory);
  r.setProperty('--ivory-2', p.ivory2);
  r.setProperty('--ink', p.ink);
  r.setProperty('--ink-2', p.ink2);
  r.setProperty('--muted', p.muted);
  r.setProperty('--rule', p.rule);
  r.setProperty('--gold', p.accent);
  r.setProperty('--gold-soft', p.accentSoft);
}

/* Utils */
const fmtUSD = (n, d=0) => '$' + Number(n).toLocaleString(undefined,{maximumFractionDigits:d});
const fmtUSDshort = (n) => {
  if (n >= 1_000_000) return '$' + (n/1_000_000).toFixed(n>=10_000_000?1:2).replace(/\.0+$/,'') + 'M';
  if (n >= 1_000) return '$' + Math.round(n/1_000) + 'K';
  return '$' + n;
};
const fmtPct = (n, d=1) => `${n.toFixed(d)}%`;

function useInView(options={threshold:0.15}){
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(()=>{
    const el = ref.current; if(!el) return;
    const check = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (r.top < vh * 0.9 && r.bottom > 0) { setInView(true); return true; }
      return false;
    };
    if (check()) return;
    const io = new IntersectionObserver(([e])=>{
      if(e.isIntersecting){ setInView(true); io.disconnect(); }
    }, options);
    io.observe(el);
    const t = setTimeout(()=>{ if(check()) io.disconnect(); }, 100);
    return ()=>{ io.disconnect(); clearTimeout(t); };
  },[]);
  return [ref, inView];
}

function useCounter(target, active, duration=1400){
  const [val, setVal] = useState(0);
  useEffect(()=>{
    if(!active) return;
    let raf, start;
    const tick = t => {
      if(!start) start = t;
      const p = Math.min(1, (t-start)/duration);
      const eased = 1 - Math.pow(1-p, 3);
      setVal(target * eased);
      if(p<1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return ()=>cancelAnimationFrame(raf);
  },[active,target,duration]);
  return val;
}

/* Atoms */
function Eyebrow({children, color}){
  return <div style={{
    fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:11, letterSpacing:'0.22em',
    textTransform:'uppercase', color: color || 'var(--muted)', marginBottom:18
  }}>{children}</div>;
}

function Btn({children, variant='primary', onClick, full, style, href, target}){
  const base = {
    display:'inline-flex', alignItems:'center', justifyContent:'center', gap:10,
    padding:'14px 22px', border:'1px solid transparent', fontSize:13,
    letterSpacing:'0.04em', fontWeight:500, transition:'all .2s ease',
    width: full?'100%':'auto', cursor:'pointer', textDecoration:'none',
  };
  const variants = {
    primary:{ background:'var(--ink)', color:'var(--ivory)', borderColor:'var(--ink)' },
    ghost:{ background:'transparent', color:'var(--ink)', borderColor:'var(--ink)' },
    gold:{ background:'var(--gold)', color:'var(--ivory)', borderColor:'var(--gold)' },
    light:{ background:'var(--ivory)', color:'var(--ink)', borderColor:'var(--ivory)' },
    lightGhost:{ background:'transparent', color:'var(--ivory)', borderColor:'rgba(10,10,10,0.4)' },
  };
  const enter = e=>{e.currentTarget.style.transform='translateY(-1px)'};
  const leave = e=>{e.currentTarget.style.transform='translateY(0)'};
  if(href){
    return <a href={href} target={target} onClick={onClick}
      style={{...base, ...variants[variant], ...style}}
      onMouseEnter={enter} onMouseLeave={leave}>{children}</a>;
  }
  return <button onClick={onClick} style={{...base, ...variants[variant], ...style}}
    onMouseEnter={enter} onMouseLeave={leave}>
    {children}
  </button>;
}

function Stat({label, value, sub, big}){
  return <div>
    <div style={{fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:10, letterSpacing:'0.22em',
      textTransform:'uppercase', color:'var(--muted)', marginBottom:10}}>{label}</div>
    <div style={{fontFamily:"'Jost',sans-serif", fontSize: big?64:40, lineHeight:0.95,
      fontWeight:300, letterSpacing:'-0.02em'}} className="tnum">{value}</div>
    {sub && <div style={{fontSize:12, color:'var(--muted)', marginTop:8}}>{sub}</div>}
  </div>;
}

function Monogram({size=40}){
  return <div style={{
    width:size, height:size, border:'1px solid var(--ink)',
    display:'flex', alignItems:'center', justifyContent:'center',
    fontFamily:"'Jost',sans-serif", fontSize:size*0.38, fontStyle:'italic',
    letterSpacing:'-0.02em'
  }}>CRV</div>;
}

function SectionLabel({num, title}){
  return <div style={{display:'flex', alignItems:'baseline', gap:20,
    fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:11, letterSpacing:'0.22em',
    textTransform:'uppercase', color:'var(--muted)', marginBottom:40}}>
    <span>§ {num}</span>
    <span style={{flex:1, height:1, background:'var(--rule)'}}/>
    <span>{title}</span>
  </div>;
}

function Nav({onCTA}){
  const [scrolled, setScrolled] = useState(false);
  const [activeId, setActiveId] = useState('overview');
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(()=>{
    const onScroll = ()=> setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onScroll, {passive:true});
    return ()=>window.removeEventListener('scroll', onScroll);
  },[]);
  const links = [
    ['Snapshot','overview'],
    ['Property','property'],
    ['Rent Roll','rentroll'],
    ['Thesis','thesis'],
    ['Financials','financials'],
    ['Returns','returns'],
    ['Sponsor','sponsor'],
  ];
  useEffect(()=>{
    const ids = links.map(([,id])=>id);
    const els = ids.map(id=>document.getElementById(id)).filter(Boolean);
    if(!els.length) return;
    const observer = new IntersectionObserver((entries)=>{
      const visible = entries
        .filter(e=>e.isIntersecting)
        .sort((a,b)=>a.target.getBoundingClientRect().top - b.target.getBoundingClientRect().top);
      if(visible.length) setActiveId(visible[0].target.id);
    }, { rootMargin: '-80px 0px -60% 0px', threshold: 0 });
    els.forEach(el=>observer.observe(el));
    return ()=>observer.disconnect();
  },[]);
  const scrollTo = id => {
    const el = document.getElementById(id);
    if(el){ window.scrollTo({top: el.offsetTop - 60, behavior:'smooth'}); }
    setMenuOpen(false);
  };
  return <>
    <nav style={{
      position:'fixed', top:0, left:0, right:0, zIndex:100,
      padding: scrolled ? '14px 40px' : '22px 40px',
      background: scrolled || menuOpen ? 'rgba(10,10,10,0.92)' : 'transparent',
      backdropFilter: scrolled || menuOpen ? 'blur(10px)' : 'none',
      borderBottom: scrolled ? '1px solid var(--rule)' : '1px solid transparent',
      display:'flex', alignItems:'center', gap:40, transition:'all .25s ease',
    }}>
      <div style={{display:'flex', alignItems:'center', gap:14, cursor:'pointer', flexShrink:0, minWidth:0}}
        onClick={()=>{ setMenuOpen(false); window.scrollTo({top:0, behavior:'smooth'}); }}>
        <Monogram size={36}/>
        <div style={{minWidth:0}}>
          <div style={{fontFamily:"'Jost',sans-serif", fontSize:16, lineHeight:1, whiteSpace:'nowrap'}}>Cinco Ranch Village</div>
          <div style={{fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:9, letterSpacing:'0.2em',
            textTransform:'uppercase', color:'var(--muted)', marginTop:3, whiteSpace:'nowrap'}}>JAL-JCP · April 2026</div>
        </div>
      </div>
      <div style={{flex:1}}/>
      <div data-nav="links" style={{display:'flex', gap:24}}>
        {links.map(([l,id]) => {
          const isActive = activeId === id;
          return <a key={id} onClick={()=>scrollTo(id)} style={{
            fontSize:12, letterSpacing:'0.04em', cursor:'pointer',
            color: isActive ? 'var(--gold)' : 'var(--ink)',
            paddingBottom: 3,
            borderBottom: isActive ? '1px solid var(--gold)' : '1px solid transparent',
            transition: 'color .2s ease, border-color .2s ease',
          }}>{l}</a>;
        })}
      </div>
      <button data-nav="hamburger" onClick={()=>setMenuOpen(v=>!v)}
        aria-label={menuOpen ? 'Close menu' : 'Open menu'} aria-expanded={menuOpen}
        style={{
          display:'none', background:'transparent', border:'1px solid var(--rule)',
          color:'var(--ink)', width:40, height:40, padding:0,
          alignItems:'center', justifyContent:'center', flexShrink:0, cursor:'pointer'
        }}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
          {menuOpen ? (
            <g stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
              <line x1="6" y1="6" x2="18" y2="18"/>
              <line x1="18" y1="6" x2="6" y2="18"/>
            </g>
          ) : (
            <g stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
              <line x1="4" y1="7" x2="20" y2="7"/>
              <line x1="4" y1="12" x2="20" y2="12"/>
              <line x1="4" y1="17" x2="20" y2="17"/>
            </g>
          )}
        </svg>
      </button>
      <Btn variant="primary" onClick={onCTA} style={{padding:'10px 18px', fontSize:12}}>
        Request Package <span style={{opacity:0.6}}>→</span>
      </Btn>
    </nav>
    {menuOpen && <div data-nav="menu" onClick={()=>setMenuOpen(false)} style={{
      position:'fixed', top:0, left:0, right:0, bottom:0, zIndex:99,
      paddingTop: 68, background:'rgba(10,10,10,0.96)', backdropFilter:'blur(14px)',
    }}>
      <div onClick={e=>e.stopPropagation()} style={{
        borderTop:'1px solid var(--rule)', maxHeight:'calc(100vh - 68px)', overflowY:'auto'
      }}>
        {links.map(([l,id]) => {
          const isActive = activeId === id;
          return <div key={id} onClick={()=>scrollTo(id)} style={{
            padding: '18px 24px', fontSize:16, cursor:'pointer',
            color: isActive ? 'var(--gold)' : 'var(--ink)',
            borderBottom: '1px solid var(--rule)',
            borderLeft: isActive ? '2px solid var(--gold)' : '2px solid transparent',
            transition:'color .15s ease',
          }}>{l}</div>;
        })}
      </div>
    </div>}
  </>;
}

function Placeholder({label, height='100%', dark, style}){
  return <div className={"ph-stripes" + (dark?' ph-dark':'')} data-ph={label}
    style={{width:'100%', height, ...style}}/>;
}

function PhotoTile({src, caption, style, label}){
  return <div style={{position:'relative', width:'100%', height:'100%', overflow:'hidden', background:'#0A0A0A', ...style}}>
    {src ? <img src={src} alt={caption||''} loading="lazy"
      style={{width:'100%', height:'100%', objectFit:'cover', display:'block'}}/>
    : <Placeholder label={label || caption || 'Photo'} dark/>}
    {caption && <div style={{position:'absolute', left:0, right:0, bottom:0, padding:'10px 12px',
      background:'linear-gradient(to top, rgba(0,0,0,0.85), rgba(0,0,0,0))',
      fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:10, letterSpacing:'0.14em',
      textTransform:'uppercase', color:'rgba(244,233,200,0.95)'}}>{caption}</div>}
  </div>;
}

function TweaksPanel({open, tweaks, setTweaks, onClose}){
  if(!open) return null;
  const update = (k,v) => {
    const next = {...tweaks, [k]:v};
    setTweaks(next);
    window.parent?.postMessage({type:'__edit_mode_set_keys', edits:{[k]:v}}, '*');
  };
  return <div style={{
    position:'fixed', bottom:24, right:24, width:320, zIndex:200,
    background:'var(--ink)', color:'var(--ivory)', padding:24,
    boxShadow:'0 30px 60px rgba(0,0,0,0.25)', fontFamily:"'Geist',sans-serif"
  }}>
    <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:20}}>
      <div style={{fontFamily:"'Jost',sans-serif", fontSize:20}}>Tweaks</div>
      <button onClick={onClose} style={{background:'none', border:'1px solid rgba(10,10,10,0.3)',
        color:'var(--ivory)', width:28, height:28, padding:0}}>×</button>
    </div>
    <div style={{marginBottom:20}}>
      <div style={{fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:10, letterSpacing:'0.2em',
        textTransform:'uppercase', opacity:0.6, marginBottom:10}}>Palette</div>
      <div style={{display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:8}}>
        {Object.entries(PALETTES).map(([k,p])=>(
          <button key={k} onClick={()=>update('palette', k)} style={{
            padding:'10px 6px', background: tweaks.palette===k ? 'var(--gold)' : 'transparent',
            color:'var(--ivory)', border:'1px solid rgba(10,10,10,0.25)',
            fontSize:11, letterSpacing:'0.04em', cursor:'pointer',
            display:'flex', flexDirection:'column', gap:8, alignItems:'center'
          }}>
            <div style={{display:'flex', gap:3}}>
              <span style={{width:12,height:12, background:p.ivory, border:'1px solid rgba(10,10,10,0.3)'}}/>
              <span style={{width:12,height:12, background:p.ink}}/>
              <span style={{width:12,height:12, background:p.accent}}/>
            </div>
            {p.name}
          </button>
        ))}
      </div>
    </div>
    <div style={{marginBottom:20}}>
      <div style={{display:'flex', justifyContent:'space-between',
        fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:10, letterSpacing:'0.2em',
        textTransform:'uppercase', opacity:0.6, marginBottom:10}}>
        <span>Type scale</span><span>{tweaks.fontScale.toFixed(2)}×</span>
      </div>
      <input type="range" min="0.9" max="1.15" step="0.01" value={tweaks.fontScale}
        onChange={e=>update('fontScale', parseFloat(e.target.value))}
        style={{width:'100%', accentColor:'var(--gold)'}}/>
    </div>
  </div>;
}

function RequestModal({open, onClose}){
  const [step, setStep] = useState(0);
  const [form, setForm] = useState({name:'', email:'', firm:'', accredited:false});
  useEffect(()=>{ if(open) setStep(0); },[open]);
  if(!open) return null;
  const field = (k, label, type='text') => (
    <label style={{display:'block', marginBottom:18}}>
      <div style={{fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:10, letterSpacing:'0.2em',
        textTransform:'uppercase', color:'var(--muted)', marginBottom:8}}>{label}</div>
      <input type={type} value={form[k]} onChange={e=>setForm({...form, [k]:e.target.value})}
        style={{width:'100%', padding:'12px 0', border:'none', borderBottom:'1px solid var(--rule)',
          background:'transparent', fontSize:16, fontFamily:"'Jost',sans-serif",
          color:'var(--ink)', outline:'none'}}
        onFocus={e=>e.target.style.borderBottomColor='var(--ink)'}
        onBlur={e=>e.target.style.borderBottomColor='var(--rule)'}/>
    </label>
  );
  return <div style={{
    position:'fixed', inset:0, zIndex:300, background:'rgba(244,233,200,0.65)',
    backdropFilter:'blur(4px)', display:'flex', alignItems:'center', justifyContent:'center', padding:24,
  }} onClick={onClose}>
    <div onClick={e=>e.stopPropagation()} style={{
      width:'min(520px, 100%)', background:'var(--ivory)', padding:'48px 48px 40px',
      position:'relative', maxHeight:'90vh', overflow:'auto'
    }}>
      <button onClick={onClose} style={{position:'absolute', top:20, right:20,
        background:'none', border:'1px solid var(--rule)', width:32, height:32, fontSize:18}}>×</button>
      {step===0 && <>
        <Eyebrow>Investor Access · Step 1 of 2</Eyebrow>
        <h2 style={{fontSize:36, marginBottom:14, letterSpacing:'-0.015em'}}>
          Request the full <em>investment package</em>.
        </h2>
        <p style={{color:'var(--muted)', fontSize:14, marginBottom:28, maxWidth:400}}>
          We'll share the financial model, offering memorandum, and rent roll upon NDA execution.
        </p>
        {field('name','Full name')}
        {field('email','Email', 'email')}
        {field('firm','Firm / family office (optional)')}
        <label style={{display:'flex', alignItems:'flex-start', gap:12, cursor:'pointer', marginBottom:28, fontSize:13, color:'var(--muted)'}}>
          <input type="checkbox" checked={form.accredited}
            onChange={e=>setForm({...form, accredited:e.target.checked})}
            style={{marginTop:3, accentColor:'var(--gold)'}}/>
          I represent that I am an <strong style={{color:'var(--ink)'}}>accredited investor</strong> as defined in Rule 501 of Regulation&nbsp;D.
        </label>
        <Btn variant="primary" full onClick={()=>setStep(1)}>Continue →</Btn>
      </>}
      {step===1 && <>
        <Eyebrow>Investor Access · Step 2 of 2</Eyebrow>
        <h2 style={{fontSize:36, marginBottom:14, letterSpacing:'-0.015em'}}>
          Thank you, {form.name ? form.name.split(' ')[0] : 'there'}.
        </h2>
        <p style={{color:'var(--muted)', fontSize:14, marginBottom:28, maxWidth:400}}>
          The package has been sent to <strong style={{color:'var(--ink)'}}>{form.email || 'your email'}</strong>.
          Justin or James will reach out within one business day.
        </p>
        <div style={{background:'var(--ivory-2)', padding:24, marginBottom:24,
          borderLeft:'2px solid var(--gold)'}}>
          <div style={{fontFamily:"'JetBrains Mono',ui-monospace,monospace", fontSize:10, letterSpacing:'0.2em',
            textTransform:'uppercase', color:'var(--muted)', marginBottom:8}}>Next step</div>
          <div style={{fontFamily:"'Jost',sans-serif", fontSize:20, lineHeight:1.3}}>
            A principal will contact you directly to walk through the offering.
          </div>
        </div>
        <Btn variant="primary" full onClick={onClose}>Close</Btn>
      </>}
    </div>
  </div>;
}

Object.assign(window, {
  DEAL, PALETTES, applyPalette, fmtUSD, fmtUSDshort, fmtPct,
  useInView, useCounter, Eyebrow, Btn, Stat, Monogram, SectionLabel,
  Nav, Placeholder, PhotoTile, TweaksPanel, RequestModal,
});
