// ─── Investor archetypes ───────────────────────────────────────────── const INVESTOR_TYPES = { visionary: { label: 'Visionary', tag: 'OFF-MARKET', short: 'Wants to know what comes next.', desc: 'For those who want to know what will come from a developer before it exists. The way in is a direct conversation about off-market opportunities — before renders, before pricing, before the market.', }, pragmatist: { label: 'Pragmatist', tag: 'LISTA CERO', short: 'Believes in structure already in place.', desc: 'For those who believe in what already has structure. Entry into our Lista Cero with preferential terms — the earliest formal access, before public launch.', }, early: { label: 'Early Adopter', tag: 'UNDER CONSTRUCTION', short: 'A faster, safer position.', desc: 'For projects already under construction. Faster delivery, a safer position, and an investor most likely thinking about keeping the apartment rather than flipping it.', }, rent: { label: 'Rent Investor', tag: 'RENTAL YIELD', short: 'Income over appreciation.', desc: 'For those buying to rent rather than to appreciate. Modest valuation growth — around 4–5% per year — with the real return coming from rental income and occupancy.', }, }; // ─── Core products (featured) ──────────────────────────────────────── const CORE = [ { name: 'Bioma', developer: 'TheVelopers', loc: 'Panama City', best: 'pragmatist', sketch: 'StandardTower' }, { name: 'Mova', developer: 'Pacific Developers', loc: 'Obarrio', best: 'early', sketch: 'LowRiseBuilding' }, { name: 'Playa Escondida', developer: 'Playa Escondida', loc: 'María Chiquita, Colón', best: 'pragmatist', sketch: 'CoastalTower' }, { name: 'Nayamara', developer: 'TheVelopers', loc: 'Panama City', best: 'early', sketch: 'FinancialTower' }, { name: 'Boreal', developer: 'GK Developers', loc: 'Obarrio', best: 'early', sketch: 'StandardTower' }, ]; // ─── Full portfolio, grouped by developer ──────────────────────────── const DEVELOPERS = [ { name: 'TheVelopers', projects: [ { name: 'Bioma', best: 'pragmatist' }, { name: 'Cavarrosa', best: 'pragmatist' }, { name: 'Nayamara', best: 'early' }, { name: 'Dovle Selva', best: 'rent' }, { name: 'Dovle Cincuentenario', best: 'rent' }, { name: 'Victory Wellness', best: 'rent' }, { name: 'Victory Sports', best: 'rent' }, { name: 'Vita', best: 'rent' }, { name: 'Velure', best: 'rent' }, ]}, { name: 'Pacific Developers', projects: [ { name: 'Mova', best: 'pragmatist' }, ]}, { name: 'Playa Escondida', projects: [ { name: 'Playa Escondida', best: 'pragmatist' }, ]}, { name: 'Sartoriale', projects: [ { name: 'Gesti 68', best: 'early' }, { name: 'Gesti 66', best: 'early' }, { name: 'Gesti 65', best: 'early' }, ]}, { name: 'Urbania', projects: [ { name: 'Sky Parc', loc: 'Costa del Este', best: 'early' }, ]}, { name: 'F&F', projects: [ { name: 'Next', best: 'rent' }, { name: 'X', best: 'early' }, { name: 'Regalia', best: 'rent' }, ]}, { name: 'Durex', projects: [ { name: 'Wanders & YOO', best: 'rent' }, { name: 'La Maison by Casa Fendi', best: 'rent' }, ]}, { name: 'GK Developers', projects: [ { name: 'Boreal', loc: 'Obarrio', best: 'early' }, ]}, ]; // ─── Flashcard — clicking opens the project's page ─────────────────── const Flashcard = ({ project, developer, featured, accent, showType, openProject }) => { const [hov, setHov] = React.useState(false); const type = INVESTOR_TYPES[project.best]; const Sketch = featured && project.sketch ? window[project.sketch] : null; const TypeBadge = showType && React.createElement('span', { style: { display: 'inline-block', fontFamily: "'DM Mono',monospace", fontSize: 7, letterSpacing: '0.1em', textTransform: 'uppercase', padding: '2px 7px', border: `1px solid ${accent}`, color: accent, }, }, `Best for · ${type.label}`); return React.createElement('div', { onClick: () => openProject(project.name), onMouseEnter: () => setHov(true), onMouseLeave: () => setHov(false), 'data-hover': '', style: { position: 'relative', cursor: 'pointer', overflow: 'hidden', border: '1px solid rgba(44,44,42,0.14)', background: hov ? 'rgba(44,44,42,0.03)' : '#F4F1EC', display: 'flex', flexDirection: 'column', minHeight: featured ? 360 : 168, transition: 'background 250ms', }, }, Sketch && React.createElement('div', { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '6%', minHeight: 0 } }, React.createElement(Sketch) ), React.createElement('div', { style: { padding: featured ? '20px 22px' : '16px 18px', borderTop: Sketch ? '1px solid rgba(44,44,42,0.08)' : 'none' } }, developer && React.createElement('div', { style: { marginBottom: featured ? 14 : 12, minHeight: featured ? 46 : 42, display: 'flex', alignItems: 'center' } }, React.createElement(DeveloperLogo, { name: developer, height: featured ? (developer === 'TheVelopers' ? 34 : 44) : 34, compact: !featured, maxWidth: featured ? (developer === 'TheVelopers' ? 190 : 240) : 210 })), React.createElement('div', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: featured ? 24 : 18, fontWeight: 300, color: '#2C2C2A', lineHeight: 1.15, marginBottom: project.loc ? 3 : 8 } }, project.name), project.loc && React.createElement('div', { style: { fontFamily: "'DM Mono',monospace", fontSize: 8, color: '#8A8A85', marginBottom: 8, letterSpacing: '0.06em' } }, project.loc), React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8, marginTop: 8 } }, TypeBadge || React.createElement('span'), React.createElement('span', { style: { fontFamily: "'DM Mono',monospace", fontSize: 7, letterSpacing: '0.14em', textTransform: 'uppercase', color: hov ? accent : '#B8B5AE', transition: 'color 200ms', whiteSpace: 'nowrap' } }, 'Open project →') ) ), React.createElement('div', { style: { position: 'absolute', bottom: 0, left: 0, right: 0, height: 2, background: accent, transform: hov ? 'scaleX(1)' : 'scaleX(0)', transformOrigin: 'left', transition: 'transform 320ms ease' } }) ); }; // ─── Investor key ──────────────────────────────────────────────────── const InvestorKey = ({ accent }) => React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 2 } }, ['visionary', 'pragmatist', 'early', 'rent'].map(k => { const t = INVESTOR_TYPES[k]; return React.createElement('div', { key: k, style: { border: '1px solid rgba(44,44,42,0.14)', padding: '24px 22px', background: k === 'visionary' ? 'rgba(44,44,42,0.03)' : 'transparent' } }, React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14 } }, React.createElement('div', { style: { width: 12, height: 1, background: accent } }), React.createElement('span', { style: { fontFamily: "'DM Mono',monospace", fontSize: 7, letterSpacing: '0.12em', textTransform: 'uppercase', color: accent } }, t.tag) ), React.createElement('div', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: 22, fontWeight: 300, color: '#2C2C2A', marginBottom: 10 } }, t.label), React.createElement('p', { style: { fontFamily: "'DM Mono',monospace", fontSize: 9.5, fontWeight: 300, color: '#8A8A85', lineHeight: 1.85 } }, t.desc) ); }) ); // ─── Portfolio Page ────────────────────────────────────────────────── const PortfolioPage = ({ navigate, t, openProject }) => { useReveal(); const tw = t || {}; const accent = tw.accent || '#B8922A'; const showType = tw.showInvestorTypes !== false; const layout = tw.buildersLayout || 'grouped'; const open = openProject || (() => {}); const allFlat = DEVELOPERS.flatMap(d => d.projects.map(p => ({ ...p, _dev: d.name }))); return React.createElement('div', { style: { paddingTop: 66 } }, // ── Header ──────────────────────────────────────────────── React.createElement('section', { style: { background: '#EAE6DE', padding: '80px 0 60px' } }, React.createElement('div', { style: { maxWidth: 1200, margin: '0 auto', padding: '0 52px' } }, React.createElement('div', { 'data-reveal': '' }, React.createElement('div', { style: { fontFamily: "'DM Mono',monospace", fontSize: 8, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8A8A85', marginBottom: 20 } }, 'Active Portfolio'), React.createElement('h1', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: 'clamp(32px,5vw,72px)', fontWeight: 300, color: '#2C2C2A', lineHeight: 1.1, marginBottom: 20 } }, 'Each project,', React.createElement('br'), React.createElement('em', null, 'a curated thesis.') ), React.createElement('p', { style: { fontFamily: "'DM Mono',monospace", fontSize: 10, fontWeight: 300, color: '#8A8A85', lineHeight: 1.9, maxWidth: 560 } }, 'Every project is matched to the investor it serves best. Turn any card to see which thesis it answers — and to reach us about what is still off-market.' ) ) ) ), // ── Core products ───────────────────────────────────────── React.createElement('section', { style: { background: '#F4F1EC', padding: '60px 0 0' } }, React.createElement('div', { style: { maxWidth: 1200, margin: '0 auto', padding: '0 52px' } }, React.createElement('div', { 'data-reveal': '', style: { marginBottom: 40 } }, React.createElement('div', { style: { fontFamily: "'DM Mono',monospace", fontSize: 8, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8A8A85', marginBottom: 16 } }, 'Core Products'), React.createElement('h2', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: 'clamp(22px,3vw,40px)', fontWeight: 300, color: '#2C2C2A', lineHeight: 1.2 } }, 'Where we are placing capital ', React.createElement('em', null, 'now.') ) ), React.createElement('div', { 'data-reveal': '', 'data-delay': '1', style: { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 2 } }, CORE.map((p, i) => React.createElement(Flashcard, { key: i, project: p, developer: p.developer, featured: true, accent, showType, openProject: open }) ) ) ) ), // ── Investor key ────────────────────────────────────────── React.createElement('section', { style: { background: '#F4F1EC', padding: '80px 0 0' } }, React.createElement('div', { style: { maxWidth: 1200, margin: '0 auto', padding: '0 52px' } }, React.createElement('div', { style: { height: 1, background: 'rgba(44,44,42,0.12)', marginBottom: 56 } }), React.createElement('div', { 'data-reveal': '', style: { marginBottom: 40 } }, React.createElement('div', { style: { fontFamily: "'DM Mono',monospace", fontSize: 8, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8A8A85', marginBottom: 16 } }, 'Who each project is for'), React.createElement('h2', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: 'clamp(22px,3vw,40px)', fontWeight: 300, color: '#2C2C2A', lineHeight: 1.2, marginBottom: 12 } }, 'Four ways ', React.createElement('em', null, 'to enter.') ), React.createElement('p', { style: { fontFamily: "'DM Mono',monospace", fontSize: 10, color: '#8A8A85', lineHeight: 1.9, maxWidth: 560 } }, 'Every project carries a Visionary route — the off-market conversation, open on all of them. Beyond that, each one answers one investor type most precisely.' ) ), React.createElement('div', { 'data-reveal': '', 'data-delay': '1' }, React.createElement(InvestorKey, { accent }) ) ) ), // ── Builders behind the portfolio ───────────────────────── React.createElement('section', { style: { background: '#F4F1EC', padding: '80px 0 100px' } }, React.createElement('div', { style: { maxWidth: 1200, margin: '0 auto', padding: '0 52px' } }, React.createElement('div', { style: { height: 1, background: 'rgba(44,44,42,0.12)', marginBottom: 56 } }), React.createElement('div', { 'data-reveal': '', style: { marginBottom: 48 } }, React.createElement('div', { style: { fontFamily: "'DM Mono',monospace", fontSize: 8, letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8A8A85', marginBottom: 16 } }, 'Developer Partners'), React.createElement('h2', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: 'clamp(24px,3.5vw,52px)', fontWeight: 300, color: '#2C2C2A', lineHeight: 1.15, marginBottom: 12 } }, 'The builders behind ', React.createElement('em', null, 'our portfolio.') ), React.createElement('p', { style: { fontFamily: "'DM Mono',monospace", fontSize: 10, color: '#8A8A85', lineHeight: 1.9, maxWidth: 560 } }, 'We work with a curated group of developers. Each one has passed our qualification framework — and each project below is turnable to its best-fit investor.' ) ), // GROUPED layout layout === 'grouped' ? DEVELOPERS.map((dev, di) => React.createElement('div', { key: di, 'data-reveal': '', style: { marginBottom: 52 } }, React.createElement('div', { style: { display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 20, borderBottom: '1px solid rgba(44,44,42,0.12)', paddingBottom: 14 } }, React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', minWidth: 190, minHeight: 58 } }, React.createElement(DeveloperLogo, { name: dev.name, height: 48, maxWidth: 260 })), React.createElement('span', { style: { fontFamily: "'DM Mono',monospace", fontSize: 8, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#B8B5AE' } }, `${dev.projects.length} project${dev.projects.length > 1 ? 's' : ''}`) ), React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 2 } }, dev.projects.map((p, pi) => React.createElement(Flashcard, { key: pi, project: p, featured: false, accent, showType, openProject: open }) ) ) ) ) // FLAT layout : React.createElement('div', { 'data-reveal': '', style: { display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 2 } }, allFlat.map((p, i) => React.createElement(Flashcard, { key: i, project: p, developer: p._dev, featured: false, accent, showType, openProject: open }) ) ) ) ), // ── CTA ─────────────────────────────────────────────────── React.createElement('section', { style: { background: '#2C2C2A', padding: '80px 0' } }, React.createElement('div', { style: { maxWidth: 1200, margin: '0 auto', padding: '0 52px' } }, React.createElement('div', { 'data-reveal': '', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 24 } }, React.createElement('div', null, React.createElement('h2', { style: { fontFamily: "'Cormorant Garamond',serif", fontSize: 'clamp(22px,3vw,40px)', fontWeight: 300, color: '#F4F1EC', lineHeight: 1.2, marginBottom: 8 } }, 'The best opportunities are not on this page.' ), React.createElement('p', { style: { fontFamily: "'DM Mono',monospace", fontSize: 10, color: 'rgba(244,241,236,0.45)', lineHeight: 1.85, maxWidth: 460 } }, 'Our Visionary pipeline cannot be shown — because for the market, it does not yet exist. That conversation starts with you.' ) ), React.createElement('button', { onClick: () => navigate('contact'), className: 'btn-primary', style: { borderColor: accent }, }, React.createElement('span', null, 'Discuss off-market →')) ) ) ) ); }; Object.assign(window, { PortfolioPage, INVESTOR_TYPES, DEVELOPERS, CORE });