Files
nibiru-framework.com/docs/design-system/source/index-v2.html
stephan 48c839d927 Initial public push: docs cosmos v4 + AI module + framework groundwork
This is the snapshot the production landing site (nibiru-framework.com) is
deployed from. Brings together the recent splash + docs migration to the v4
"Cosmos" design system, the new in-framework AI module, and the framework
groundwork that backs the framework-reference extraction.

What lands:
- docs/: Astro + Starlight site with the v4 dark cosmic palette, GalaxyHero
  canvas constellation, Mission Control chat (wired to /api/oracle →
  api.neuronetz.ai via providers.mjs Ollama), 5-panel MMVC stage
  (Model · AI · Module · Controller · View), translated EN/DE/JA/ES/FR
  content, PWA + sitemap + llms.txt + Umami analytics.
- docs/design-system/: canonical mockup bundle (source/index-v2.html for
  splash, source/docs-system.html + preview/ for docs, SPEC.md, tokens).
- docs/scripts/extraction/framework-reference-v2.md: deep framework
  reference (~1.6k lines, file:line citations, every public factory and
  idiom — basis for the LoRA training corpus.
- application/module/ai/: AI module with chat / embed / RAG / agent
  plugins, plus pdoQuery / httpGet / fileRead tools and Modelfile +
  smoke-test in training/.
- application/module/users/: user / ACL / form-factory traits used as the
  reference plugin pattern for the framework docs.
- application/settings/config/database/: schema + seed migrations
  including the AI module tables (200–203).
- Form factory + autogenerator changes the framework-reference-v2 covers.

Production secrets stay out: docs/.env, settings.production.ini and
ai.production.ini are all gitignored (.example files are in tree).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:22:18 +02:00

1241 lines
49 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Nibiru — An AI framework that orbits PHP</title>
<meta name="description" content="Nibiru is an open-source AI framework for PHP 8+. Built on MMVC — Model, Module, View, Controller — it separates weights from capability so agents compose like code, not glue." />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#0a0414" />
<link rel="icon" href="assets/favicon.png" />
<link rel="canonical" href="https://nibiru-framework.com/" />
<!-- Open Graph / Twitter -->
<meta property="og:type" content="website" />
<meta property="og:title" content="Nibiru — An AI framework that orbits PHP" />
<meta property="og:description" content="MMVC: Model, Module, View, Controller. Open-weight models. PHP-native. The framework AI agents are written in." />
<meta property="og:url" content="https://nibiru-framework.com/" />
<meta property="og:image" content="https://nibiru-framework.com/og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:site_name" content="Nibiru" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Nibiru — An AI framework that orbits PHP" />
<meta name="twitter:description" content="MMVC: Model, Module, View, Controller. Open-weight models. PHP-native." />
<meta name="twitter:image" content="https://nibiru-framework.com/og.png" />
<!-- Structured data for crawlers + AI assistants -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://nibiru-framework.com/#org",
"name": "Nibiru",
"url": "https://nibiru-framework.com/",
"logo": "https://nibiru-framework.com/assets/nibiru-full.png",
"sameAs": [
"https://github.com/nibiru-framework/nibiru",
"https://discord.gg/nibiru"
]
},
{
"@type": "SoftwareApplication",
"name": "Nibiru",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Linux, macOS, Windows",
"programmingLanguage": "PHP",
"url": "https://nibiru-framework.com/",
"description": "An AI framework for PHP 8+ built on the MMVC pattern (Model, Module, View, Controller). Open-weight models, typed composable modules, framework-agnostic controllers.",
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" },
"softwareVersion": "0.9.2",
"author": { "@id": "https://nibiru-framework.com/#org" }
},
{
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is MMVC?",
"acceptedAnswer": {
"@type": "Answer",
"text": "MMVC stands for Model, Module, View, Controller. It is a structural pattern that generalises classic MVC for AI workloads by splitting the monolithic Model of MVC into two roles: a Model (the underlying weights and runtime) and a Module (a typed, composable AI capability such as a retriever, planner, vision encoder, or tool). The Controller orchestrates Modules, and the View renders the result."
}
},
{
"@type": "Question",
"name": "How does MMVC differ from MVC?",
"acceptedAnswer": {
"@type": "Answer",
"text": "MVC has one Model that must hold both data and behaviour. For AI systems that conflation collapses, because weights and capability evolve at very different rates. MMVC adds a Module layer between Model and Controller — Modules are typed, composable units of intelligence (retrievers, planners, tools, vision encoders) that wrap the underlying Model. The Controller then composes Modules, not raw model calls."
}
},
{
"@type": "Question",
"name": "Why PHP?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The majority of the web's request layer runs on PHP. Nibiru gives that stack first-class AI primitives without forcing teams to bolt on a Python service. The same MMVC pattern transfers to other languages — but Nibiru is PHP-native and idiomatic to PHP 8."
}
},
{
"@type": "Question",
"name": "Is Nibiru open source?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. The framework, the model weights, and the standard module library are open source. Models ship with signed manifests and verifiable checksums."
}
}
]
}
]
}
</script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter+Tight:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<style>
/* ============== TOKENS ============== */
:root {
--void: #06030f;
--space: #0a0414;
--night: #120825;
--plum: #1c0f3a;
--nebula-mag: #b86bff;
--nebula-blue: #5b8dff;
--nebula-amber: #ffb574;
--star: #f4eedb;
--paper: #f4eedb;
--paper-2: #ebe3c8;
--ink: #0a0414;
--ink-2: #2a2438;
--muted: #6e6680;
--line: rgba(244,238,219,0.12);
--line-strong: rgba(244,238,219,0.28);
--grid: rgba(244,238,219,0.04);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: "Inter Tight", ui-sans-serif, system-ui, sans-serif;
background: var(--space);
color: var(--star);
font-size: 16px;
line-height: 1.55;
font-feature-settings: "ss01", "cv11";
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
overflow-x: hidden;
}
::selection { background: rgba(184,107,255,0.4); color: var(--star); }
a { color: inherit; text-decoration: none; }
.mono, code, kbd, pre { font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace; }
.display { font-family: "Space Grotesk", "Inter Tight", ui-sans-serif, sans-serif; }
/* ============== UTILITIES ============== */
.container { max-width: 1280px; margin: 0 auto; padding: 0 32px; }
.eyebrow {
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
color: var(--muted);
display: inline-flex; align-items: center; gap: 8px;
}
.eyebrow::before {
content: ""; width: 18px; height: 1px; background: var(--line-strong);
}
/* ============== NAV ============== */
.nav {
position: fixed; top: 0; left: 0; right: 0; z-index: 60;
padding: 18px 0;
transition: padding 240ms ease, background-color 240ms ease, backdrop-filter 240ms ease;
}
.nav.condensed {
padding: 10px 0;
background: rgba(6,3,15,0.72);
backdrop-filter: saturate(150%) blur(14px);
-webkit-backdrop-filter: saturate(150%) blur(14px);
border-bottom: 1px solid var(--line);
}
.nav-row {
display: flex; align-items: center; justify-content: space-between;
gap: 32px;
}
.brand { display: flex; align-items: center; gap: 12px; flex: none; min-width: 0; }
.brand-mark {
height: 30px; width: auto; flex: none;
}
.brand-name {
font-family: "Space Grotesk", sans-serif; font-weight: 500;
font-size: 21px; letter-spacing: -0.02em;
color: var(--star);
}
.brand-name em { font-style: normal; font-weight: 300; }
.nav-version {
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.04em;
color: var(--muted);
padding: 3px 7px;
border: 1px solid var(--line);
border-radius: 999px;
margin-left: 6px;
display: inline-flex; align-items: center; gap: 6px;
flex: none;
}
.nav-version .dot {
width: 5px; height: 5px; border-radius: 50%;
background: #7ad6a3; box-shadow: 0 0 8px rgba(122,214,163,0.7);
}
.nav-links {
display: flex; gap: 28px; align-items: center;
flex: 1; justify-content: center;
}
.nav-links a {
font-size: 14px; color: rgba(244,238,219,0.7);
transition: color 160ms ease;
}
.nav-links a:hover { color: var(--star); }
.nav-cta {
display: flex; gap: 10px; align-items: center; flex: none;
}
/* ============== BUTTONS ============== */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
padding: 10px 18px;
border-radius: 999px;
font-size: 14px; font-weight: 500; letter-spacing: -0.005em;
border: 1px solid transparent;
cursor: pointer;
transition: transform 160ms ease, background-color 160ms ease, border-color 160ms ease, color 160ms ease;
white-space: nowrap;
}
.btn-ghost { color: rgba(244,238,219,0.85); border-color: var(--line-strong); background: transparent; }
.btn-ghost:hover { color: var(--star); border-color: rgba(244,238,219,0.5); }
.btn-solid {
background: var(--star); color: var(--ink);
box-shadow: 0 0 0 1px rgba(244,238,219,0.2), 0 18px 40px -16px rgba(184,107,255,0.6);
}
.btn-solid:hover { transform: translateY(-1px); }
.btn-icon-only { width: 36px; height: 36px; padding: 0; }
.btn .ico { width: 16px; height: 16px; }
/* ============== HERO ============== */
.hero {
position: relative;
min-height: 100vh;
display: flex; flex-direction: column; justify-content: center;
overflow: hidden;
isolation: isolate;
}
/* Star canvas covers the hero */
#constellation {
position: absolute; inset: 0;
width: 100%; height: 100%;
z-index: 0;
}
.hero::after {
/* bottom fade so headline reads cleanly */
content: "";
position: absolute; left: 0; right: 0; bottom: 0; height: 50%;
background: linear-gradient(to top, var(--space) 0%, rgba(10,4,20,0.7) 30%, transparent 100%);
pointer-events: none;
z-index: 1;
}
.hero-inner {
position: relative; z-index: 2;
max-width: 1280px;
margin: 0 auto;
padding: 220px 32px 120px;
}
.hero-meta {
display: flex; gap: 24px; align-items: center; flex-wrap: wrap;
margin-bottom: 36px;
}
.hero-headline {
font-family: "Space Grotesk", sans-serif;
font-size: clamp(56px, 9vw, 124px);
line-height: 0.95;
letter-spacing: -0.04em;
font-weight: 400;
margin: 0;
max-width: 14ch;
color: var(--star);
}
.hero-headline em {
font-style: normal; font-weight: 500;
background: linear-gradient(110deg, #ffb574 0%, #b86bff 50%, #5b8dff 100%);
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-headline .period {
color: var(--nebula-amber);
font-weight: 500;
}
.hero-sub {
margin: 40px 0 0;
font-size: 18px;
color: rgba(244,238,219,0.72);
max-width: 48ch;
line-height: 1.5;
}
.hero-ctas {
display: flex; gap: 28px; align-items: center;
margin-top: 48px;
}
.hero-link {
display: inline-flex; align-items: center; gap: 12px;
color: var(--star);
font-size: 16px;
padding: 4px 0;
border-bottom: 1px solid rgba(244,238,219,0.4);
transition: gap 200ms ease, border-color 200ms ease;
}
.hero-link:hover { gap: 18px; border-bottom-color: var(--star); }
.hero-link .arrow { font-family: "JetBrains Mono", monospace; transition: transform 200ms ease; }
.hero-link:hover .arrow { transform: translateX(4px); }
.hero-link.muted { color: rgba(244,238,219,0.6); border-bottom-color: rgba(244,238,219,0.18); }
.hero-link.muted:hover { color: var(--star); }
/* Telemetry strip — bottom of hero */
.hero-telemetry {
position: absolute; bottom: 32px; left: 0; right: 0;
z-index: 3;
display: flex; gap: 48px; justify-content: space-between;
padding: 0 32px;
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
color: var(--muted);
}
.tele-cell { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tele-cell strong { color: rgba(244,238,219,0.85); font-weight: 500; }
.tele-cell .pulse {
width: 6px; height: 6px; border-radius: 50%;
background: #7ad6a3;
box-shadow: 0 0 8px rgba(122,214,163,0.7);
animation: telePulse 2.4s ease-in-out infinite;
}
@keyframes telePulse {
0%, 100% { opacity: 0.5; transform: scale(0.85); }
50% { opacity: 1; transform: scale(1.15); }
}
/* Tooltip rendered into the canvas wrap, positioned via JS */
.module-tip {
position: absolute;
pointer-events: none;
z-index: 4;
padding: 10px 14px;
background: rgba(6,3,15,0.86);
backdrop-filter: blur(12px);
border: 1px solid var(--line-strong);
border-radius: 10px;
font-family: "JetBrains Mono", monospace;
font-size: 12px;
color: var(--star);
white-space: nowrap;
transform: translate(-50%, calc(-100% - 14px));
opacity: 0;
transition: opacity 200ms ease;
box-shadow: 0 18px 40px -18px rgba(0,0,0,0.6);
}
.module-tip.visible { opacity: 1; }
.module-tip .name { color: var(--nebula-mag); display: block; font-weight: 500; margin-bottom: 2px; }
.module-tip .sig { color: rgba(244,238,219,0.7); font-size: 11px; }
.module-tip::after {
content: ""; position: absolute; left: 50%; bottom: -5px; transform: translateX(-50%) rotate(45deg);
width: 8px; height: 8px;
background: rgba(6,3,15,0.86);
border-right: 1px solid var(--line-strong);
border-bottom: 1px solid var(--line-strong);
}
/* Comet trail cursor (canvas overlay, rendered in JS) */
#comet-trail {
position: fixed; inset: 0;
pointer-events: none; z-index: 100;
}
/* ============== TYPOGRAPHIC SECTION HEADS ============== */
.section {
position: relative;
padding: 160px 0;
z-index: 1;
}
.section.alt {
background: var(--paper);
color: var(--ink);
}
.section.alt .eyebrow { color: var(--ink-2); }
.section.alt .eyebrow::before { background: var(--ink-2); }
.section-head {
max-width: 800px;
margin-bottom: 80px;
}
.section-head .eyebrow { margin-bottom: 24px; }
.section-title {
font-family: "Space Grotesk", sans-serif;
font-size: clamp(40px, 5.6vw, 80px);
line-height: 1.02;
letter-spacing: -0.03em;
font-weight: 400;
margin: 0;
text-wrap: pretty;
}
.section-title em { font-style: normal; font-weight: 500; }
.section-title .accent {
font-style: normal; font-weight: 500;
background: linear-gradient(110deg, #ffb574, #b86bff 70%);
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent;
}
.section.alt .section-title .accent {
background: linear-gradient(110deg, #b46500, #5b1f9e 70%);
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent;
}
.section-sub {
margin-top: 28px;
font-size: 19px; line-height: 1.55;
color: rgba(244,238,219,0.7);
max-width: 56ch;
}
.section.alt .section-sub { color: var(--ink-2); }
/* ============== MMVC PINNED NARRATIVE ============== */
.mmvc-stage {
position: relative;
padding: 0;
}
.mmvc-track {
position: relative;
height: 400vh; /* 4 panels worth of scroll */
}
.mmvc-pin {
position: sticky; top: 0;
height: 100vh;
display: block;
overflow: hidden;
background: radial-gradient(ellipse at 50% 50%, var(--plum), var(--space) 60%);
}
.mmvc-visual {
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
z-index: 0;
opacity: 0.45;
}
.mmvc-copy {
position: absolute; inset: 0;
z-index: 2;
display: flex; flex-direction: column; align-items: center; justify-content: center;
padding: 0 24px;
text-align: center;
}
.mmvc-copy .panel {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, calc(-50% + 24px));
display: flex; flex-direction: column; align-items: center;
width: min(720px, calc(100vw - 48px));
text-align: center;
opacity: 0;
transition: opacity 500ms ease, transform 500ms ease;
pointer-events: none;
}
.mmvc-copy .panel.active {
opacity: 1; transform: translate(-50%, -50%);
pointer-events: auto;
}
.mmvc-copy .step-num {
font-family: "JetBrains Mono", monospace;
font-size: 12px; letter-spacing: 0.18em;
color: var(--nebula-mag);
text-transform: uppercase;
margin-bottom: 24px;
display: inline-flex; align-items: center; gap: 12px;
justify-content: center;
}
.mmvc-copy .step-num::before,
.mmvc-copy .step-num::after {
content: ""; width: 28px; height: 1px; background: var(--nebula-mag); opacity: 0.6;
}
.mmvc-copy h3 {
font-family: "Space Grotesk", sans-serif;
font-size: clamp(48px, 6vw, 88px);
font-weight: 400;
line-height: 0.98;
letter-spacing: -0.035em;
margin: 0 0 24px;
color: var(--star);
}
.mmvc-copy h3 em { font-style: normal; font-weight: 500; }
.mmvc-copy h3 .pop {
background: linear-gradient(110deg, #ffb574, #b86bff);
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent;
font-style: normal; font-weight: 500;
}
.mmvc-copy p {
font-size: 20px; line-height: 1.55;
color: rgba(244,238,219,0.85);
max-width: 56ch;
margin: 0 auto 16px;
text-wrap: pretty;
}
.mmvc-copy code {
background: rgba(244,238,219,0.06);
border: 1px solid var(--line);
padding: 1px 6px;
border-radius: 4px;
font-size: 0.85em;
}
.mmvc-progress {
position: absolute;
left: 50%;
top: 80px;
transform: translateX(-50%);
display: flex; gap: 8px; align-items: center;
z-index: 4;
}
.mmvc-progress .step {
display: flex; align-items: center; gap: 8px;
color: var(--muted);
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
transition: color 240ms ease;
padding-right: 10px;
}
.mmvc-progress .step .bar {
width: 24px; height: 2px; background: var(--line);
transition: background 240ms ease, width 240ms ease;
border-radius: 2px;
}
.mmvc-progress .step.active { color: var(--star); }
.mmvc-progress .step.active .bar { background: var(--nebula-mag); width: 40px; }
/* ============== MISSION CONTROL CHAT ============== */
.mc-frame {
background: #050208;
border: 1px solid var(--line-strong);
border-radius: 18px;
overflow: hidden;
box-shadow: 0 60px 120px -40px rgba(0,0,0,0.7), 0 0 0 1px rgba(184,107,255,0.06) inset;
}
.mc-header {
display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 24px;
padding: 14px 22px;
border-bottom: 1px solid var(--line);
background: linear-gradient(180deg, rgba(184,107,255,0.05), transparent);
}
.mc-id {
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
color: var(--nebula-mag);
display: flex; align-items: center; gap: 10px;
}
.mc-id .dot {
width: 8px; height: 8px; border-radius: 50%;
background: var(--nebula-mag);
box-shadow: 0 0 12px var(--nebula-mag);
animation: telePulse 2s ease-in-out infinite;
}
.mc-tele {
display: flex; gap: 32px; justify-content: center;
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
color: var(--muted);
}
.mc-tele span strong { color: rgba(244,238,219,0.9); font-weight: 500; }
.mc-actions { display: flex; gap: 8px; color: var(--muted); }
.mc-actions button {
width: 28px; height: 28px; border: none; background: transparent;
color: inherit; cursor: pointer; border-radius: 6px;
display: flex; align-items: center; justify-content: center;
}
.mc-actions button:hover { background: rgba(244,238,219,0.06); color: var(--star); }
.mc-body {
padding: 36px 40px;
min-height: 420px;
max-height: 560px;
overflow-y: auto;
font-family: "JetBrains Mono", monospace;
font-size: 13.5px; line-height: 1.65;
scrollbar-width: thin; scrollbar-color: rgba(184,107,255,0.3) transparent;
}
.mc-body::-webkit-scrollbar { width: 8px; }
.mc-body::-webkit-scrollbar-thumb { background: rgba(184,107,255,0.3); border-radius: 8px; }
.mc-line { padding: 2px 0; white-space: pre-wrap; word-break: break-word; }
.mc-line.usr { color: #cdebff; }
.mc-line.usr::before { content: "> "; color: #5b8dff; }
.mc-line.sys { color: var(--muted); }
.mc-line.trc { color: rgba(184,107,255,0.78); }
.mc-line.asst-stream { color: var(--star); }
.mc-line.asst-label { color: var(--nebula-amber); margin-top: 12px; }
.mc-line.done { color: #7ad6a3; margin-top: 12px; }
.mc-cursor {
display: inline-block; width: 8px; height: 16px; vertical-align: -2px;
background: var(--star); margin-left: 2px;
animation: blink 1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
.mc-input {
border-top: 1px solid var(--line);
padding: 14px 22px;
display: flex; gap: 14px; align-items: center;
background: rgba(244,238,219,0.02);
}
.mc-input .prompt {
color: var(--nebula-mag);
font-family: "JetBrains Mono", monospace;
font-size: 13px;
}
.mc-input input {
flex: 1; border: none; background: transparent; outline: none;
font-family: "JetBrains Mono", monospace;
font-size: 14px; color: var(--star);
}
.mc-input input::placeholder { color: var(--muted); }
.mc-input .send {
border: 1px solid var(--line-strong);
background: transparent;
color: var(--star);
padding: 6px 14px; border-radius: 6px;
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
cursor: pointer;
transition: background-color 160ms ease, color 160ms ease;
}
.mc-input .send:hover { background: var(--star); color: var(--ink); }
.mc-suggestions {
display: flex; gap: 12px; flex-wrap: wrap; margin-top: 24px;
}
.mc-suggestion {
border: 1px solid var(--line);
border-radius: 999px;
padding: 8px 16px;
font-size: 13px;
color: rgba(244,238,219,0.75);
cursor: pointer;
background: transparent;
font-family: inherit;
transition: border-color 160ms ease, color 160ms ease, background-color 160ms ease;
}
.mc-suggestion:hover { border-color: var(--nebula-mag); color: var(--star); background: rgba(184,107,255,0.08); }
/* ============== LAUNCH SEQUENCE CODE ============== */
.launch-grid {
display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: stretch;
}
.launch-code {
background: #050208;
border: 1px solid var(--line-strong);
border-radius: 18px;
overflow: hidden;
box-shadow: 0 60px 120px -40px rgba(0,0,0,0.7);
display: flex; flex-direction: column;
}
.launch-code-head {
display: flex; justify-content: space-between; align-items: center;
padding: 12px 20px;
border-bottom: 1px solid var(--line);
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
color: var(--muted);
}
.launch-code-head .file { color: var(--nebula-mag); }
.launch-code-head .play {
border: 1px solid var(--line-strong); background: transparent;
color: var(--star);
padding: 6px 14px; border-radius: 6px;
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
cursor: pointer;
transition: background-color 160ms ease, color 160ms ease;
}
.launch-code-head .play:hover { background: var(--star); color: var(--ink); }
.launch-code-body {
flex: 1; padding: 24px 28px;
font-family: "JetBrains Mono", monospace;
font-size: 13px; line-height: 1.7;
color: var(--star);
white-space: pre;
overflow: auto;
scrollbar-width: thin; scrollbar-color: rgba(184,107,255,0.2) transparent;
}
.launch-code-body::-webkit-scrollbar { width: 6px; height: 6px; }
.launch-code-body::-webkit-scrollbar-thumb { background: rgba(184,107,255,0.25); border-radius: 6px; }
.tk-k { color: #c8a8ff; }
.tk-cls { color: #f0d4ff; }
.tk-fn { color: #b8d4ff; }
.tk-s { color: #ffd9a3; }
.tk-n { color: #b8e0c2; }
.tk-v { color: #ffb4d8; }
.tk-attr { color: #d4baff; }
.tk-c { color: #6e6680; font-style: italic; }
.tk-tag { color: #c8a8ff; font-weight: 600; }
.launch-code-body .caret {
display: inline-block; width: 7px; height: 14px; vertical-align: -2px;
background: var(--nebula-mag); margin-left: 1px;
box-shadow: 0 0 12px var(--nebula-mag);
animation: blink 1s steps(1) infinite;
}
.launch-system {
position: relative;
border: 1px solid var(--line-strong);
border-radius: 18px;
overflow: hidden;
background: radial-gradient(ellipse at center, var(--plum) 0%, var(--space) 70%);
}
#launch-canvas { position: absolute; inset: 0; }
.launch-system .legend {
position: absolute; left: 24px; top: 24px;
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
color: var(--muted);
}
.launch-system .stats {
position: absolute; left: 24px; bottom: 24px; right: 24px;
display: flex; justify-content: space-between; gap: 12px;
font-family: "JetBrains Mono", monospace;
font-size: 11px;
color: rgba(244,238,219,0.6);
}
.launch-system .stats span strong { color: var(--star); font-weight: 500; }
/* ============== SPACECRAFT (DOWNLOADS) ============== */
.craft-grid {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px;
}
.craft {
position: relative;
background: linear-gradient(180deg, var(--night), var(--space));
border: 1px solid var(--line);
border-radius: 20px;
padding: 36px 28px 28px;
overflow: hidden;
transition: transform 280ms ease, border-color 280ms ease, box-shadow 280ms ease;
}
.craft::before {
content: ""; position: absolute; inset: 0;
background: radial-gradient(ellipse 80% 50% at 50% -10%, var(--ribbon), transparent 70%);
opacity: 0.5;
pointer-events: none;
}
.craft.lite { --ribbon: rgba(122,214,163,0.35); }
.craft.base { --ribbon: rgba(184,107,255,0.45); }
.craft.pro { --ribbon: rgba(255,181,116,0.45); }
.craft:hover {
transform: translateY(-4px);
border-color: var(--ribbon);
box-shadow: 0 30px 60px -30px rgba(0,0,0,0.7);
}
.craft .badge {
font-family: "JetBrains Mono", monospace;
font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase;
color: var(--muted); display: inline-flex; align-items: center; gap: 8px;
}
.craft .badge::before {
content: ""; width: 6px; height: 6px; border-radius: 50%;
background: var(--ribbon, var(--muted));
}
.craft .name {
font-family: "Space Grotesk", sans-serif;
font-size: 34px; font-weight: 400;
letter-spacing: -0.025em;
margin: 18px 0 4px;
color: var(--star);
}
.craft .name em { font-style: normal; font-weight: 600; }
.craft .role {
font-size: 14px; color: rgba(244,238,219,0.65);
margin-bottom: 28px;
}
.craft .silhouette {
height: 140px;
margin: 0 -28px 24px;
position: relative;
display: flex; align-items: center; justify-content: center;
}
.craft .silhouette svg {
width: 140px; height: 140px;
filter: drop-shadow(0 0 24px var(--ribbon));
}
.craft .stats {
display: grid; grid-template-columns: 1fr 1fr; gap: 16px 12px;
border-top: 1px solid var(--line);
padding-top: 22px;
font-family: "JetBrains Mono", monospace;
font-size: 11px;
}
.craft .stats div { display: flex; flex-direction: column; gap: 4px; }
.craft .stats .l {
color: var(--muted);
letter-spacing: 0.08em; text-transform: uppercase; font-size: 10px;
}
.craft .stats .v { color: var(--star); font-size: 14px; }
.craft .craft-cta {
display: flex; gap: 8px; align-items: center;
margin-top: 24px;
padding: 12px 0;
border-top: 1px solid var(--line);
font-size: 14px;
color: var(--star);
}
.craft .craft-cta:hover { color: var(--ribbon); }
.craft .craft-cta .arrow { margin-left: auto; font-family: "JetBrains Mono", monospace; }
/* ============== FOOTER ============== */
.footer {
position: relative;
padding: 100px 0 60px;
background: var(--space);
border-top: 1px solid var(--line);
overflow: hidden;
}
#footer-canvas { position: absolute; inset: 0; opacity: 0.4; pointer-events: none; }
.footer-inner {
position: relative; z-index: 2;
display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 48px;
}
.footer-brand .brand { margin-bottom: 16px; }
.footer-brand p {
font-size: 14px; color: rgba(244,238,219,0.55);
max-width: 36ch; line-height: 1.55;
}
.footer-col h5 {
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
color: var(--muted);
margin: 0 0 18px;
font-weight: 400;
}
.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 12px; }
.footer-col a { font-size: 14px; color: rgba(244,238,219,0.7); }
.footer-col a:hover { color: var(--star); }
.footer-bottom {
margin-top: 80px;
padding-top: 24px;
border-top: 1px solid var(--line);
display: flex; justify-content: space-between; align-items: center;
font-family: "JetBrains Mono", monospace;
font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
color: var(--muted);
position: relative; z-index: 2;
}
/* ============== SCROLL TO TOP ============== */
.to-top {
position: fixed; right: 28px; bottom: 28px; z-index: 70;
width: 44px; height: 44px; border-radius: 50%;
border: 1px solid var(--line-strong);
background: rgba(6,3,15,0.7); backdrop-filter: blur(10px);
color: var(--star); cursor: pointer;
display: flex; align-items: center; justify-content: center;
opacity: 0; pointer-events: none;
transition: opacity 240ms ease, transform 240ms ease;
}
.to-top.visible { opacity: 1; pointer-events: auto; }
.to-top:hover { transform: translateY(-2px); border-color: var(--nebula-mag); }
/* ============== REDUCED MOTION ============== */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
#constellation, #launch-canvas, #footer-canvas, #comet-trail { display: none; }
.hero { background: radial-gradient(ellipse at 30% 30%, var(--plum), var(--space) 70%); }
}
/* ============== RESPONSIVE ============== */
@media (max-width: 960px) {
.nav-links { display: none; }
.hero-headline { font-size: clamp(48px, 12vw, 80px); }
.hero-telemetry { display: none; }
.mmvc-pin { grid-template-columns: 1fr; }
.mmvc-visual { height: 50vh; }
.mmvc-copy { padding: 0 24px; }
.launch-grid { grid-template-columns: 1fr; }
.craft-grid { grid-template-columns: 1fr; }
.footer-inner { grid-template-columns: 1fr 1fr; }
}
</style>
</head>
<body>
<template id="__bundler_thumbnail" data-bg-color="#0b0410">
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="core" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fff4d9" stop-opacity="1"/>
<stop offset="20%" stop-color="#ffb574" stop-opacity="0.95"/>
<stop offset="55%" stop-color="#b86bff" stop-opacity="0.55"/>
<stop offset="100%" stop-color="#0b0410" stop-opacity="0"/>
</radialGradient>
<radialGradient id="bg" cx="50%" cy="50%" r="60%">
<stop offset="0%" stop-color="#1a0824"/>
<stop offset="100%" stop-color="#05020a"/>
</radialGradient>
</defs>
<rect width="1200" height="800" fill="url(#bg)"/>
<!-- spiral arms via rotated ellipses -->
<g transform="translate(600 400)" opacity="0.7">
<ellipse rx="380" ry="90" fill="url(#core)" transform="rotate(15)"/>
<ellipse rx="320" ry="70" fill="url(#core)" transform="rotate(95)" opacity="0.6"/>
<ellipse rx="260" ry="55" fill="url(#core)" transform="rotate(170)" opacity="0.5"/>
</g>
<circle cx="600" cy="400" r="42" fill="#fff4d9" opacity="0.95"/>
<circle cx="600" cy="400" r="120" fill="url(#core)" opacity="0.6"/>
</svg>
</template>
<!-- Comet trail cursor overlay -->
<canvas id="comet-trail" aria-hidden="true"></canvas>
<!-- ============================== NAV ============================== -->
<header class="nav" id="nav">
<div class="container nav-row">
<a class="brand" href="#top">
<img class="brand-mark" src="assets/nibiru-lotus-only.png" alt="" />
<span class="brand-name">Nibiru</span>
<span class="nav-version"><span class="dot"></span>v0.9.2</span>
</a>
<nav class="nav-links" aria-label="Primary">
<a href="#mmvc">MMVC</a>
<a href="#chat">Mission Control</a>
<a href="#code">Code</a>
<a href="#download">Models</a>
<a href="#docs">Docs</a>
</nav>
<div class="nav-cta">
<a class="btn btn-ghost btn-icon-only" href="https://github.com/nibiru-framework/nibiru" aria-label="GitHub">
<svg class="ico" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8a8 8 0 0 0 5.47 7.59c.4.07.55-.17.55-.38v-1.36c-2.23.48-2.7-1.07-2.7-1.07-.36-.93-.89-1.18-.89-1.18-.73-.5.05-.49.05-.49.81.06 1.24.83 1.24.83.72 1.24 1.89.88 2.35.67.07-.52.28-.88.51-1.08-1.78-.2-3.65-.89-3.65-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.13 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.11.16 1.93.08 2.13.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48v2.2c0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
</a>
<a class="btn btn-solid" href="#download">Download</a>
</div>
</div>
</header>
<!-- ============================== HERO ============================== -->
<main id="top">
<section class="hero" aria-labelledby="hero-h">
<canvas id="constellation" aria-hidden="true"></canvas>
<div class="container hero-inner">
<div class="hero-meta">
<span class="eyebrow">Open source · PHP 8 · MMVC</span>
</div>
<h1 id="hero-h" class="hero-headline">An AI framework <em>that orbits</em> PHP<span class="period">.</span></h1>
<p class="hero-sub">Nibiru is a structural framework for AI in PHP. The MMVC pattern — <em>Model, Module, View, Controller</em> — splits weights from capability so agents compose like code, not glue.</p>
<div class="hero-ctas">
<a class="hero-link" href="#chat">Try the chat <span class="arrow"></span></a>
<a class="hero-link muted" href="#download">Download model <span class="arrow"></span></a>
</div>
</div>
<div class="hero-telemetry" aria-hidden="true">
<div class="tele-cell"><span class="pulse"></span> <strong>NIBIRU SYSTEM</strong> · live</div>
<div class="tele-cell">MODEL <strong>nibiru-base-7B</strong></div>
<div class="tele-cell">MODULES <strong>4 in orbit</strong></div>
<div class="tele-cell">CONTROLLER <strong>idle</strong></div>
<div class="tele-cell">v<strong>0.9.2</strong></div>
</div>
<!-- Tooltip placeholder (positioned by JS) -->
<div class="module-tip" id="moduleTip" role="tooltip">
<span class="name"></span>
<span class="sig"></span>
</div>
<!-- Static fallback for crawlers / no-JS -->
<noscript>
<p style="color: var(--star); padding: 0 32px;">
Nibiru is an AI framework for PHP, built on the MMVC pattern. Try the chat below or download a model.
</p>
</noscript>
</section>
<!-- ============================== MMVC PINNED NARRATIVE ============================== -->
<section class="section mmvc-stage" id="mmvc" aria-labelledby="mmvc-h">
<div class="container" style="padding-top: 0;">
<div class="section-head">
<span class="eyebrow">The pattern · 01</span>
<h2 id="mmvc-h" class="section-title">Four roles. <span class="accent">One orbit.</span></h2>
<p class="section-sub">MMVC generalises classic MVC for AI workloads. The monolithic Model splits in two — the underlying weights, and the typed capabilities that wrap them. Watch the system come into focus.</p>
</div>
</div>
<div class="mmvc-track" id="mmvcTrack">
<div class="mmvc-pin">
<!-- Progress rail -->
<div class="mmvc-progress" aria-hidden="true">
<div class="step active" data-step="0"><span class="bar"></span><span>Model</span></div>
<div class="step" data-step="1"><span class="bar"></span><span>Module</span></div>
<div class="step" data-step="2"><span class="bar"></span><span>Controller</span></div>
<div class="step" data-step="3"><span class="bar"></span><span>View</span></div>
</div>
<div class="mmvc-copy">
<div class="panel active" data-panel="0">
<div class="step-num">01 / 04 — MODEL</div>
<h3>The <span class="pop">star</span><br/>at the centre.</h3>
<p>The <strong>Model</strong> is the underlying ML model. Weights, runtime, inference — wherever it lives, on a laptop or a cluster. From the Controller's view it is stateless and addressable: <code>Model::load('nibiru-base-7B')</code>.</p>
<p>One Model, many Modules.</p>
</div>
<div class="panel" data-panel="1">
<div class="step-num">02 / 04 — MODULE</div>
<h3>Modules <span class="pop">orbit</span><br/>the Model.</h3>
<p>A <strong>Module</strong> is a typed capability — a retriever, a planner, a tool, a vision encoder. It has typed inputs and outputs. Composable. Pure-function-shaped over the Model.</p>
<p>This is the layer MVC never had. Capabilities live here, not in the Model.</p>
</div>
<div class="panel" data-panel="2">
<div class="step-num">03 / 04 — CONTROLLER</div>
<h3>The <span class="pop">gravity</span><br/>between them.</h3>
<p>The <strong>Controller</strong> orchestrates. It decides which Modules run, in what order, and how their outputs flow. Holds policy, never weights — the same Controller drives a chat agent or a batch job.</p>
</div>
<div class="panel" data-panel="3">
<div class="step-num">04 / 04 — VIEW</div>
<h3>The <span class="pop">surface</span><br/>at the horizon.</h3>
<p>The <strong>View</strong> is the user-facing layer — <code>ChatView</code>, <code>VoiceView</code>, <code>APIView</code>. Swap one for another and the Controller does not change. Same agent, different sky.</p>
</div>
</div>
<div class="mmvc-visual" id="mmvcVisual">
<canvas id="mmvc-canvas" aria-hidden="true" style="position:absolute; inset:0; width:100%; height:100%;"></canvas>
</div>
</div>
</div>
</section>
<!-- ============================== MISSION CONTROL CHAT ============================== -->
<section class="section" id="chat" aria-labelledby="chat-h">
<div class="container">
<div class="section-head">
<span class="eyebrow">Live system · 02</span>
<h2 id="chat-h" class="section-title">Mission <span class="accent">Control.</span></h2>
<p class="section-sub">A working playground. Same nibiru-base-7B model, same MMVC controller — just with the dashboard turned on so you can see the modules light up.</p>
</div>
<div class="mc-frame" id="mcFrame">
<div class="mc-header">
<div class="mc-id"><span class="dot"></span><span>NIBIRU/MC · session 7c4a</span></div>
<div class="mc-tele" id="mcTele">
<span>MODEL <strong>nibiru-base-7B</strong></span>
<span>LATENCY <strong></strong></span>
<span>TOKENS <strong>0</strong></span>
</div>
<div class="mc-actions">
<button title="Reset" id="mcReset"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5"/></svg></button>
<button title="Copy"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg></button>
</div>
</div>
<div class="mc-body" id="mcBody">
<div class="mc-line sys"> establishing link to nibiru-base-7B …</div>
<div class="mc-line sys"> controller online · 4 modules in orbit (Retriever, ReActPlanner, Greeter, ChatView)</div>
<div class="mc-line sys"> ready. type a prompt below or pick a suggestion.</div>
</div>
<div class="mc-input">
<span class="prompt"></span>
<input id="mcInput" type="text" placeholder="ask the agent…" autocomplete="off" />
<button class="send" id="mcSend">Transmit</button>
</div>
</div>
<div class="mc-suggestions">
<button class="mc-suggestion" data-q="explain mmvc">Explain MMVC</button>
<button class="mc-suggestion" data-q="rag">Build a RAG agent</button>
<button class="mc-suggestion" data-q="tools">Add a tool</button>
<button class="mc-suggestion" data-q="haiku">Write a haiku</button>
</div>
</div>
</section>
<!-- ============================== LAUNCH SEQUENCE CODE ============================== -->
<section class="section" id="code" aria-labelledby="code-h">
<div class="container">
<div class="section-head">
<span class="eyebrow">Launch sequence · 03</span>
<h2 id="code-h" class="section-title">Eleven lines, <span class="accent">one orbit.</span></h2>
<p class="section-sub">Code on the left, system on the right. Hit launch and watch the modules slide into place as the controller wires them up.</p>
</div>
<div class="launch-grid">
<div class="launch-code">
<div class="launch-code-head">
<span class="file">agent.php</span>
<button class="play" id="launchPlay">▶ Launch</button>
</div>
<pre class="launch-code-body" id="launchBody"></pre>
</div>
<div class="launch-system">
<canvas id="launch-canvas"></canvas>
<div class="legend">// nibiru system · live</div>
<div class="stats" id="launchStats">
<span>Modules <strong id="lsModules">0</strong></span>
<span>Tokens <strong id="lsTokens">0</strong></span>
<span>Latency <strong id="lsLatency">— ms</strong></span>
</div>
</div>
</div>
</div>
</section>
<!-- ============================== SPACECRAFT (DOWNLOADS) ============================== -->
<section class="section" id="download" aria-labelledby="dl-h">
<div class="container">
<div class="section-head">
<span class="eyebrow">Choose your craft · 04</span>
<h2 id="dl-h" class="section-title">Three vessels. <span class="accent">Same orbit.</span></h2>
<p class="section-sub">Open weights, signed manifests, verifiable checksums. Pick the model that matches your altitude.</p>
</div>
<div class="craft-grid">
<article class="craft lite">
<span class="badge">Probe · Edge</span>
<h3 class="name">Nibiru <em>Lite</em></h3>
<p class="role">Fits in a pocket. Runs on a laptop CPU.</p>
<div class="silhouette">
<svg viewBox="0 0 100 100" fill="none" stroke="currentColor" stroke-width="1.2" style="color: rgba(122,214,163,0.9);">
<circle cx="50" cy="50" r="8" fill="currentColor"/>
<ellipse cx="50" cy="50" rx="32" ry="6"/>
<ellipse cx="50" cy="50" rx="32" ry="6" transform="rotate(60 50 50)"/>
<ellipse cx="50" cy="50" rx="32" ry="6" transform="rotate(-60 50 50)"/>
<circle cx="82" cy="50" r="2.5" fill="currentColor"/>
</svg>
</div>
<div class="stats">
<div><span class="l">Params</span><span class="v">1.3 B</span></div>
<div><span class="l">Disk</span><span class="v">820 MB</span></div>
<div><span class="l">Quantization</span><span class="v">4-bit</span></div>
<div><span class="l">Speed</span><span class="v">30+ tok/s</span></div>
</div>
<a class="craft-cta" href="#">Download Lite <span class="arrow"></span></a>
</article>
<article class="craft base">
<span class="badge">Shuttle · Daily driver</span>
<h3 class="name">Nibiru <em>Base</em></h3>
<p class="role">The default. Runs anywhere with a GPU.</p>
<div class="silhouette">
<svg viewBox="0 0 100 100" fill="none" stroke="currentColor" stroke-width="1.2" style="color: rgba(184,107,255,0.9);">
<circle cx="50" cy="50" r="14" fill="currentColor" opacity="0.4"/>
<circle cx="50" cy="50" r="9" fill="currentColor"/>
<ellipse cx="50" cy="50" rx="38" ry="9"/>
<ellipse cx="50" cy="50" rx="38" ry="9" transform="rotate(45 50 50)"/>
<ellipse cx="50" cy="50" rx="38" ry="9" transform="rotate(90 50 50)"/>
<ellipse cx="50" cy="50" rx="38" ry="9" transform="rotate(-45 50 50)"/>
<circle cx="88" cy="50" r="3" fill="currentColor"/>
<circle cx="22" cy="22" r="2" fill="currentColor"/>
<circle cx="78" cy="78" r="2.5" fill="currentColor"/>
</svg>
</div>
<div class="stats">
<div><span class="l">Params</span><span class="v">7 B</span></div>
<div><span class="l">Disk</span><span class="v">14 GB · 4 GB Q4</span></div>
<div><span class="l">Context</span><span class="v">8 192</span></div>
<div><span class="l">License</span><span class="v">Apache 2.0</span></div>
</div>
<a class="craft-cta" href="#">Download Base <span class="arrow"></span></a>
</article>
<article class="craft pro">
<span class="badge">Mothership · Heavy lift</span>
<h3 class="name">Nibiru <em>Pro</em></h3>
<p class="role">Cluster scale. Tool use, vision, long context.</p>
<div class="silhouette">
<svg viewBox="0 0 100 100" fill="none" stroke="currentColor" stroke-width="1.2" style="color: rgba(255,181,116,0.9);">
<circle cx="50" cy="50" r="20" fill="currentColor" opacity="0.25"/>
<circle cx="50" cy="50" r="12" fill="currentColor"/>
<ellipse cx="50" cy="50" rx="44" ry="12"/>
<ellipse cx="50" cy="50" rx="44" ry="12" transform="rotate(30 50 50)"/>
<ellipse cx="50" cy="50" rx="44" ry="12" transform="rotate(60 50 50)"/>
<ellipse cx="50" cy="50" rx="44" ry="12" transform="rotate(90 50 50)"/>
<ellipse cx="50" cy="50" rx="44" ry="12" transform="rotate(120 50 50)"/>
<ellipse cx="50" cy="50" rx="44" ry="12" transform="rotate(150 50 50)"/>
<circle cx="92" cy="50" r="3.5" fill="currentColor"/>
<circle cx="14" cy="36" r="2.5" fill="currentColor"/>
<circle cx="68" cy="86" r="3" fill="currentColor"/>
<circle cx="32" cy="14" r="2" fill="currentColor"/>
</svg>
</div>
<div class="stats">
<div><span class="l">Params</span><span class="v">34 B</span></div>
<div><span class="l">Disk</span><span class="v">68 GB</span></div>
<div><span class="l">Context</span><span class="v">128 K</span></div>
<div><span class="l">Modalities</span><span class="v">Text · Vision</span></div>
</div>
<a class="craft-cta" href="#">Download Pro <span class="arrow"></span></a>
</article>
</div>
</div>
</section>
</main>
<!-- ============================== FOOTER ============================== -->
<footer class="footer" id="docs">
<canvas id="footer-canvas" aria-hidden="true"></canvas>
<div class="container footer-inner">
<div class="footer-brand">
<div class="brand">
<img class="brand-mark" src="assets/nibiru-lotus-only.png" alt="" />
<span class="brand-name">Nibiru</span>
</div>
<p>An AI framework for PHP, built on MMVC. Open source. Open weights. Built to compose.</p>
</div>
<div class="footer-col">
<h5>Framework</h5>
<ul>
<li><a href="#mmvc">MMVC pattern</a></li>
<li><a href="#code">Quick start</a></li>
<li><a href="#">Modules</a></li>
<li><a href="#">Reference</a></li>
</ul>
</div>
<div class="footer-col">
<h5>Models</h5>
<ul>
<li><a href="#download">Lite · 1.3B</a></li>
<li><a href="#download">Base · 7B</a></li>
<li><a href="#download">Pro · 34B</a></li>
<li><a href="#">Manifests</a></li>
</ul>
</div>
<div class="footer-col">
<h5>Community</h5>
<ul>
<li><a href="https://github.com/nibiru-framework/nibiru">GitHub</a></li>
<li><a href="#">Discord</a></li>
<li><a href="#">Discussions</a></li>
<li><a href="#">Changelog</a></li>
</ul>
</div>
</div>
<div class="container footer-bottom">
<span>© 2026 Nibiru · Apache 2.0</span>
<span>Built in orbit · v0.9.2</span>
</div>
</footer>
<button class="to-top" id="toTop" aria-label="Back to top">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
</button>
<!-- Three.js (pinned, integrity) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="nibiru-v2.js"></script>
</body>
</html>