/* Detail page renderer — takes project slug + custom case-study sections */ const { Titlebar, Statusbar, ProjectThumb } = window; const PROJECTS = window.PORTFOLIO_PROJECTS; function getProject(slug) { return PROJECTS.find(p => p.slug === slug); } function getNeighbors(slug) { const i = PROJECTS.findIndex(p => p.slug === slug); return { prev: i > 0 ? PROJECTS[i - 1] : PROJECTS[PROJECTS.length - 1], next: i < PROJECTS.length - 1 ? PROJECTS[i + 1] : PROJECTS[0], }; } function DetailHero({ p, lede }) { const titleParts = p.italWord ? p.title.split(p.italWord) : [p.title]; return (
~/portfolio / projects / {p.slug}
{p.num} / 07  ·  {p.role}  ·  {p.year}

{titleParts[0]} {p.italWord && {p.italWord}} {titleParts[1]}

{lede || p.summary}

Role
{p.role}
Year
{p.year}
Company
{p.company}
Status
Shipped
Stack
{p.tags.map(t => {t})}
); } function HeroVisual({ p }) { return (
cover · {p.slug}
); } function NextNav({ slug }) { const { prev, next } = getNeighbors(slug); return ( ); } function Section({ num, title, italWord, children }) { const parts = italWord ? title.split(italWord) : [title]; return (
{num}

{parts[0]} {italWord && {italWord}} {parts[1]}

{children}
); } function DetailPage({ slug, lede, children }) { const p = getProject(slug); if (!p) return
Project not found
; // Set theme accent to project accent for this page React.useEffect(() => { document.documentElement.style.setProperty('--accent', p.accent); }, [p]); return (
{children}
); } window.DetailPage = DetailPage; window.Section = Section; window.getProject = getProject;