import { useEffect, useState, type CSSProperties, type ReactNode } from "react";
import { ArrowRight, ArrowUpRight, Check, Compass, Layers, Minus, Sparkles } from "lucide-react";
import { CONTACT_EMAIL } from "@/lib/contact";
import { SplitTitle, type TitlePart } from "@/components/site/motion";
import { IndustryIndex, MoltenMark } from "@/components/site/creative";
import { CropsphereStory } from "@/components/site/cropsphere";
import { DoorMileStory, LoyalyStory } from "@/components/site/venture-stories";
// Section photography (Unsplash License): see src/assets/sections/CREDITS.md.
import principleEvidence from "@/assets/sections/principle-evidence.webp";
import principleEngine from "@/assets/sections/principle-engine.webp";
import principleStandalone from "@/assets/sections/principle-standalone.webp";
import modelBuild from "@/assets/sections/model-build.webp";
import modelSpinoff from "@/assets/sections/model-spinoff.webp";
import modelCompound from "@/assets/sections/model-compound.webp";
import {
Accent,
DuoPhoto,
EASE_STAGE,
Eyebrow,
FRAMEWORK,
FillWords,
NAV,
STACK,
SectionHeader,
VERTICALS,
logoFull,
logoMark,
orbitPosition,
reveal,
rise,
type SitePageName,
} from "@/components/site/sections";
/** Position of a page in the nav, as "01".."07". */
function pageNumber(page: SitePageName) {
return String(NAV.findIndex((n) => n.href === `/${page}`) + 1).padStart(2, "0");
}
// ---------------------------------------------------------------------------------------------
// Page hero
// ---------------------------------------------------------------------------------------------
/**
* Full-height opener for inner pages: page number and label, a headline whose words rise in
* one by one, the lead paragraph and a page-specific visual. As it scrolls away the visual
* drifts and the copy lifts (hero-timeline in styles.css).
*/
function PageHero({
page,
label,
title,
intro,
visual,
children,
}: {
page: SitePageName;
label: string;
title: TitlePart[];
intro: ReactNode;
visual: ReactNode;
children?: ReactNode;
}) {
return (
{/* Target for the scroll cue: the first section after the hero. */}
);
}
// ---------------------------------------------------------------------------------------------
// Hero visuals (decorative)
// ---------------------------------------------------------------------------------------------
/** Place n items evenly on a circle of the given radius (% of the box), starting at 12 o'clock. */
function ring(i: number, n: number, radius: number): CSSProperties {
const a = ((-90 + (i * 360) / n) * Math.PI) / 180;
return {
left: `${(50 + radius * Math.cos(a)).toFixed(2)}%`,
top: `${(50 + radius * Math.sin(a)).toFixed(2)}%`,
};
}
/** Studio: the shared stack orbits the studio, the ventures circle closer in. */
function StudioVisual() {
return (
{STACK.map((s, i) => (
{s.label}
))}
{VERTICALS.map((v, i) => (
{v.short}
))}
);
}
/** Framework: the six stages as a loop with a comet running round it. */
function FrameworkVisual() {
return (
);
}
// Network layout for the AI visual, in a 400×400 viewBox.
const AI_LAYERS = [3, 5, 5, 3].map((count, l, all) =>
Array.from({ length: count }, (_, i) => ({
x: 50 + (l * 300) / (all.length - 1),
y: 200 + (i - (count - 1) / 2) * 62,
})),
);
const AI_EDGES = AI_LAYERS.slice(0, -1).flatMap((layer, l) =>
layer.flatMap((a) => AI_LAYERS[l + 1].map((b) => ({ a, b }))),
);
/** AI: a small neural network with signals flowing through it. */
function AIVisual() {
return (
);
}
/** Investors: a field of companies, lighting up in a wave across the ecosystem. */
function InvestorsVisual() {
const cols = 11;
const rows = 11;
return (
{Array.from({ length: cols * rows }, (_, i) => {
const r = Math.floor(i / cols);
const c = i % cols;
const hub = r === 5 && c === 5;
return (
);
})}
);
}
function AboutVisual() {
return (
);
}
const IST = new Intl.DateTimeFormat("en-GB", {
timeZone: "Asia/Kolkata",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
/** Contact: the studio's local time inside a rotating ring of text. */
function ContactVisual() {
const [time, setTime] = useState(null);
useEffect(() => {
const tick = () => setTime(IST.format(new Date()));
tick();
const id = window.setInterval(tick, 1000);
return () => window.clearInterval(id);
}, []);
return (
Bangalore, IST
{time ?? "--:--:--"}
Studio open to new partners
);
}
// ---------------------------------------------------------------------------------------------
// Heroes per page
// ---------------------------------------------------------------------------------------------
export function StudioHero() {
return (
}
/>
);
}
export function FrameworkHero() {
return (
}
/>
);
}
export function PortfolioHero() {
return (
}
/>
);
}
export function AIHero() {
return (
}
/>
);
}
export function InvestorsHero() {
return (
}
>
Speak with our team
);
}
export function AboutHero() {
return (
}
/>
);
}
export function ContactHero() {
return (
}
>
{CONTACT_EMAIL}
);
}
// ---------------------------------------------------------------------------------------------
// New content sections
// ---------------------------------------------------------------------------------------------
const VC_ROWS = [
{
topic: "When capital arrives",
vc: "After a company already exists",
kf: "Before the company exists, once research proves the problem",
},
{
topic: "Who builds",
vc: "Founders alone, starting from scratch",
kf: "Founders with a studio team behind them from day one",
},
{
topic: "Infrastructure",
vc: "Assembled again, company by company",
kf: "Engineering, design, legal, finance and growth, built once and shared",
},
{
topic: "Technology",
vc: "AI added later, if at all",
kf: "AI-first architecture from the first line of code",
},
{
topic: "Risk",
vc: "Concentrated in a single bet",
kf: "Spread across a portfolio of ventures",
},
];
/** Studio: how the studio model differs from traditional venture capital, row by row. */
export function StudioVsVC() {
return (
Venture capital waits. We build.
>
}
>
Traditional venture capital invests in startups after they exist. KapFoundry creates
them, which changes almost everything about how a company begins.
Traditional venture capitalKapFoundry venture studio
{VC_ROWS.map((r, i) => (
0{i + 1}
{r.topic}
Traditional venture capital:
{r.vc}
KapFoundry:
{r.kf}
))}
);
}
const PRINCIPLES = [
{
t: "Evidence before capital",
img: principleEvidence,
d: "Every venture begins with market research, customer discovery and product validation, before a single rupee is deployed.",
},
{
t: "One engine, many companies",
img: principleEngine,
d: "Engineering, design, legal, finance and growth are built once and shared, so each venture launches with a mature company's stack.",
},
{
t: "Built to stand alone",
img: principleStandalone,
d: "Each venture is designed to spin off into an independent, high-growth company that strengthens the wider ecosystem.",
},
];
/** Framework: the statement and principles behind the six stages. */
export function FrameworkPrinciples() {
return (
{PRINCIPLES.map((p, i) => (
0{i + 1}
{p.t}
{p.d}
))}
);
}
/** Ventures in the studio, from each vertical's example; each gets a page at /ventures/. */
export const VENTURES = VERTICALS.filter((v) => v.example).map((v) => {
const [name, ...rest] = (v.example ?? "").split(". ");
return {
name,
slug: name
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, ""),
pitch: rest.join(". "),
vertical: v.name,
tag: v.tag,
problem: v.problem,
solution: v.solution,
img: v.img,
icon: v.icon,
};
});
/** Portfolio: ventures already taking shape in the studio. */
export function Ventures() {
return (
Ventures taking shape.
>
}
>
A first look at companies being engineered on the KapFoundry engine.
);
}
/** AI: what the foundation does inside each vertical; the row at the centre of the screen is lit. */
export function AIAcrossVerticals() {
return (
AI in every vertical
One foundation. Seven industries.
The same AI capabilities show up differently in every market we enter. Here is where
they do the heavy lifting.
);
}
const MODEL = [
{
t: "The studio builds",
img: modelBuild,
d: "Ventures are researched, validated and built on KapFoundry's shared engine.",
},
{
t: "Ventures spin off",
img: modelSpinoff,
d: "Each company grows into an independent, high-growth business in its own market.",
},
{
t: "Value compounds",
img: modelCompound,
d: "Every success strengthens the ecosystem, and investors share in the portfolio, not a single bet.",
},
];
/** Investors: how value flows from the studio to the portfolio. */
export function InvestorModel() {
return (
How value compounds.
>
}
>
A holding company at the centre, many independent companies around it.
{MODEL.map((m, i) => (
0{i + 1}
{m.t}
{m.d}
))}
);
}
// ---------------------------------------------------------------------------------------------
// Next page handoff
// ---------------------------------------------------------------------------------------------
const NEXT_BLURB: Record = {
"/studio": "How one shared engine builds many companies.",
"/framework": "Six stages from a billion-dollar problem to an independent company.",
"/portfolio": "The industries we're rebuilding, AI-first.",
"/ai": "The foundation under every venture we build.",
"/investors": "Exposure to a portfolio, not a single bet.",
"/about": "Our vision, our mission and the people behind them.",
"/contact": "Build with us, invest with us, or simply say hello.",
};
/** Giant link to the next page in nav order; grows in as it enters and fills gold on hover. */
export function NextPage({ page }: { page: SitePageName }) {
const i = NAV.findIndex((n) => n.href === `/${page}`);
const k = (i + 1) % NAV.length;
const next = NAV[k];
return (
);
}
/** Portfolio: the seven industries as a typographic index with floating photos. */
export function PortfolioIndex() {
return (
({ n: v.n, name: v.short, tag: v.tag, img: v.img }))}
/>
);
}
// ---------------------------------------------------------------------------------------------
// Venture detail page (/ventures/$slug)
// ---------------------------------------------------------------------------------------------
/** Ventures with a full story of their own; the rest get the generic vertical sections. */
const VENTURE_STORIES: Record ReactNode> = {
cropsphere: CropsphereStory,
"doormile-wings": DoorMileStory,
"loyaly-ai": LoyalyStory,
};
/** Looks a venture up by its URL slug. */
export function findVenture(slug: string) {
return VENTURES.find((v) => v.slug === slug);
}
/**
* Everything on this page comes from what the site already says about the venture and its
* vertical; nothing about stage, traction or team is implied.
*/
export function VentureDetail({ slug }: { slug: string }) {
const v = findVenture(slug);
if (!v) return null;
const i = VENTURES.indexOf(v);
const next = VENTURES[(i + 1) % VENTURES.length];
const Icon = v.icon;
const Story = VENTURE_STORIES[v.slug];
return (
<>
{/* Hero: the venture's own photo, full bleed */}
{/* Pulls back into a rounded card as the hero scrolls away (.venture-photo). */}