|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
|
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>FMN-GPT | CompactAI</title> |
|
|
<link |
|
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" |
|
|
rel="stylesheet"> |
|
|
<style> |
|
|
|
|
|
:root { |
|
|
--color-bg: #faf8f5; |
|
|
--color-bg-alt: #f5f0e8; |
|
|
--color-bg-dark: #1a1815; |
|
|
--color-bg-dark-alt: #252220; |
|
|
--color-accent: #e85d3b; |
|
|
--color-accent-light: #ff8a6b; |
|
|
--color-accent-dark: #c44a2d; |
|
|
--color-secondary: #d4a853; |
|
|
--color-secondary-light: #e8c87a; |
|
|
--color-text: #2d2a26; |
|
|
--color-text-light: #6b6560; |
|
|
--color-text-muted: #9a948d; |
|
|
--color-border: #e5e0d8; |
|
|
--color-border-dark: #3d3a36; |
|
|
--gradient-warm: linear-gradient(135deg, #e85d3b 0%, #d4a853 100%); |
|
|
--gradient-dark: linear-gradient(135deg, #1a1815 0%, #2d2a26 100%); |
|
|
--shadow-sm: 0 2px 8px rgba(45, 42, 38, 0.08); |
|
|
--shadow-md: 0 4px 20px rgba(45, 42, 38, 0.12); |
|
|
--shadow-lg: 0 8px 40px rgba(45, 42, 38, 0.16); |
|
|
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; |
|
|
--font-mono: 'JetBrains Mono', 'Fira Code', monospace; |
|
|
--container-max: 1200px; |
|
|
--section-padding: 100px; |
|
|
} |
|
|
|
|
|
*, |
|
|
*::before, |
|
|
*::after { |
|
|
box-sizing: border-box; |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
} |
|
|
|
|
|
html { |
|
|
scroll-behavior: smooth; |
|
|
font-size: 16px; |
|
|
} |
|
|
|
|
|
html, |
|
|
body { |
|
|
height: 100%; |
|
|
} |
|
|
|
|
|
body { |
|
|
font-family: var(--font-sans); |
|
|
background-color: var(--color-bg); |
|
|
color: var(--color-text); |
|
|
line-height: 1.7; |
|
|
-webkit-font-smoothing: antialiased; |
|
|
-moz-osx-font-smoothing: grayscale; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
min-height: 100vh; |
|
|
} |
|
|
|
|
|
main { |
|
|
flex: 1; |
|
|
} |
|
|
|
|
|
.container { |
|
|
max-width: var(--container-max); |
|
|
margin: 0 auto; |
|
|
padding: 0 24px; |
|
|
} |
|
|
|
|
|
h1, |
|
|
h2, |
|
|
h3, |
|
|
h4, |
|
|
h5, |
|
|
h6 { |
|
|
font-weight: 600; |
|
|
line-height: 1.2; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
h1 { |
|
|
font-size: clamp(2.5rem, 6vw, 4.5rem); |
|
|
} |
|
|
|
|
|
h2 { |
|
|
font-size: clamp(2rem, 4vw, 3rem); |
|
|
} |
|
|
|
|
|
h3 { |
|
|
font-size: clamp(1.5rem, 3vw, 2rem); |
|
|
} |
|
|
|
|
|
h4 { |
|
|
font-size: 1.25rem; |
|
|
} |
|
|
|
|
|
p { |
|
|
margin-bottom: 1.5rem; |
|
|
color: var(--color-text-light); |
|
|
} |
|
|
|
|
|
a { |
|
|
color: var(--color-accent); |
|
|
text-decoration: none; |
|
|
transition: color 0.2s ease; |
|
|
} |
|
|
|
|
|
a:hover { |
|
|
color: var(--color-accent-dark); |
|
|
} |
|
|
|
|
|
code { |
|
|
font-family: var(--font-mono); |
|
|
background: var(--color-bg-alt); |
|
|
padding: 0.2em 0.5em; |
|
|
border-radius: 4px; |
|
|
font-size: 0.9em; |
|
|
color: var(--color-accent-dark); |
|
|
} |
|
|
|
|
|
pre { |
|
|
font-family: var(--font-mono); |
|
|
background: var(--color-bg-dark); |
|
|
color: #f5f0e8; |
|
|
padding: 1.5rem; |
|
|
border-radius: 12px; |
|
|
overflow-x: auto; |
|
|
font-size: 0.875rem; |
|
|
line-height: 1.6; |
|
|
} |
|
|
|
|
|
pre code { |
|
|
background: none; |
|
|
padding: 0; |
|
|
color: inherit; |
|
|
} |
|
|
|
|
|
blockquote { |
|
|
border-left: 4px solid var(--color-accent); |
|
|
padding-left: 1.5rem; |
|
|
margin: 2rem 0; |
|
|
font-style: italic; |
|
|
font-size: 1.25rem; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.section-title { |
|
|
text-align: center; |
|
|
margin-bottom: 1rem; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.section-title::after { |
|
|
content: ''; |
|
|
display: block; |
|
|
width: 60px; |
|
|
height: 4px; |
|
|
background: var(--gradient-warm); |
|
|
margin: 1rem auto 0; |
|
|
border-radius: 2px; |
|
|
} |
|
|
|
|
|
.section-subtitle { |
|
|
text-align: center; |
|
|
color: var(--color-text-muted); |
|
|
font-size: 1.125rem; |
|
|
margin-bottom: 3rem; |
|
|
} |
|
|
|
|
|
.hero { |
|
|
min-height: 100vh; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
position: relative; |
|
|
background: var(--color-bg-dark); |
|
|
overflow: hidden; |
|
|
} |
|
|
|
|
|
.hero-content { |
|
|
text-align: center; |
|
|
z-index: 2; |
|
|
padding: 2rem; |
|
|
} |
|
|
|
|
|
.apology-badge { |
|
|
display: inline-block; |
|
|
background: rgba(232, 93, 59, 0.15); |
|
|
color: var(--color-accent-light); |
|
|
padding: 0.5rem 1.25rem; |
|
|
border-radius: 50px; |
|
|
font-size: 0.875rem; |
|
|
font-weight: 500; |
|
|
margin-bottom: 2rem; |
|
|
border: 1px solid rgba(232, 93, 59, 0.3); |
|
|
} |
|
|
|
|
|
.hero-title { |
|
|
color: #fff; |
|
|
margin-bottom: 1.5rem; |
|
|
letter-spacing: -0.02em; |
|
|
} |
|
|
|
|
|
.hero-title .highlight { |
|
|
background: var(--gradient-warm); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
background-clip: text; |
|
|
} |
|
|
|
|
|
.hero-subtitle { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 1.25rem; |
|
|
max-width: 500px; |
|
|
margin: 0 auto 3rem; |
|
|
} |
|
|
|
|
|
.scroll-indicator { |
|
|
position: absolute; |
|
|
bottom: 3rem; |
|
|
left: 50%; |
|
|
transform: translateX(-50%); |
|
|
text-align: center; |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.875rem; |
|
|
} |
|
|
|
|
|
.scroll-arrow { |
|
|
width: 24px; |
|
|
height: 24px; |
|
|
margin: 0.5rem auto 0; |
|
|
border-right: 2px solid var(--color-accent); |
|
|
border-bottom: 2px solid var(--color-accent); |
|
|
transform: rotate(45deg); |
|
|
animation: scrollBounce 2s infinite; |
|
|
} |
|
|
|
|
|
@keyframes scrollBounce { |
|
|
|
|
|
0%, |
|
|
100% { |
|
|
transform: rotate(45deg) translateY(0); |
|
|
} |
|
|
|
|
|
50% { |
|
|
transform: rotate(45deg) translateY(8px); |
|
|
} |
|
|
} |
|
|
|
|
|
.hero-visual { |
|
|
position: absolute; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
z-index: 1; |
|
|
opacity: 0.4; |
|
|
} |
|
|
|
|
|
#neuron-canvas { |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
} |
|
|
|
|
|
.preface { |
|
|
padding: calc(var(--section-padding) + 4rem) 0 var(--section-padding); |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.preface-content { |
|
|
max-width: 800px; |
|
|
margin: 0 auto; |
|
|
font-size: 1.125rem; |
|
|
} |
|
|
|
|
|
.preface-content .drop-cap::first-letter { |
|
|
float: left; |
|
|
font-size: 4rem; |
|
|
line-height: 0.8; |
|
|
padding-right: 0.75rem; |
|
|
color: var(--color-accent); |
|
|
font-weight: 700; |
|
|
} |
|
|
|
|
|
.confession { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.confession-content { |
|
|
max-width: 800px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.confession-text { |
|
|
font-size: 1.125rem; |
|
|
} |
|
|
|
|
|
.confession-text .drop-cap::first-letter { |
|
|
float: left; |
|
|
font-size: 4rem; |
|
|
line-height: 0.8; |
|
|
padding-right: 0.75rem; |
|
|
color: var(--color-accent); |
|
|
font-weight: 700; |
|
|
} |
|
|
|
|
|
.big-question { |
|
|
display: flex; |
|
|
align-items: flex-start; |
|
|
gap: 1rem; |
|
|
background: var(--color-bg-alt); |
|
|
padding: 2rem; |
|
|
border-radius: 16px; |
|
|
margin-top: 2rem; |
|
|
border-left: 4px solid var(--color-accent); |
|
|
} |
|
|
|
|
|
.big-question .question-mark { |
|
|
font-size: 3rem; |
|
|
font-weight: 700; |
|
|
color: var(--color-accent); |
|
|
line-height: 1; |
|
|
} |
|
|
|
|
|
.big-question p { |
|
|
font-size: 1.25rem; |
|
|
font-weight: 500; |
|
|
color: var(--color-text); |
|
|
margin: 0; |
|
|
align-self: center; |
|
|
} |
|
|
|
|
|
.what-building { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg-alt); |
|
|
} |
|
|
|
|
|
.feature-grid { |
|
|
display: grid; |
|
|
gap: 2rem; |
|
|
margin-bottom: 4rem; |
|
|
} |
|
|
|
|
|
.feature-card { |
|
|
background: var(--color-bg); |
|
|
border-radius: 20px; |
|
|
padding: 2.5rem; |
|
|
box-shadow: var(--shadow-md); |
|
|
} |
|
|
|
|
|
.main-feature { |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.feature-icon { |
|
|
width: 100px; |
|
|
height: 100px; |
|
|
margin: 0 auto 1.5rem; |
|
|
} |
|
|
|
|
|
.neuron-icon { |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
} |
|
|
|
|
|
.neuron-node { |
|
|
fill: var(--color-accent); |
|
|
opacity: 0.9; |
|
|
} |
|
|
|
|
|
.neuron-connection { |
|
|
stroke: var(--color-secondary); |
|
|
stroke-width: 2; |
|
|
fill: none; |
|
|
} |
|
|
|
|
|
.feature-card h3 { |
|
|
font-size: 2rem; |
|
|
margin-bottom: 0.5rem; |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.feature-subtitle { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 1rem; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.feature-stats { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
gap: 3rem; |
|
|
margin-top: 2rem; |
|
|
padding-top: 2rem; |
|
|
border-top: 1px solid var(--color-border); |
|
|
} |
|
|
|
|
|
.stat { |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.stat-value { |
|
|
display: block; |
|
|
font-size: 2rem; |
|
|
font-weight: 700; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.stat-label { |
|
|
font-size: 0.875rem; |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.architecture-section { |
|
|
margin-top: 4rem; |
|
|
} |
|
|
|
|
|
.architecture-section h3 { |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.architecture-diagram { |
|
|
max-width: 600px; |
|
|
margin: 0 auto; |
|
|
padding: 2rem; |
|
|
background: var(--color-bg); |
|
|
border-radius: 20px; |
|
|
box-shadow: var(--shadow-md); |
|
|
} |
|
|
|
|
|
.arch-layer { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
} |
|
|
|
|
|
.layer-box { |
|
|
padding: 1.5rem 2rem; |
|
|
border-radius: 12px; |
|
|
text-align: center; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.input-layer { |
|
|
background: linear-gradient(135deg, #4a9eff 0%, #6bb3ff 100%); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.recursive-layer { |
|
|
background: var(--color-accent); |
|
|
color: white; |
|
|
padding: 2rem; |
|
|
} |
|
|
|
|
|
.output-layer { |
|
|
background: linear-gradient(135deg, #50c878 0%, #7dd8a0 100%); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.layer-details { |
|
|
margin-top: 1rem; |
|
|
font-size: 0.875rem; |
|
|
font-weight: 400; |
|
|
opacity: 0.9; |
|
|
} |
|
|
|
|
|
.detail-item { |
|
|
display: flex; |
|
|
justify-content: space-between; |
|
|
padding: 0.5rem 0; |
|
|
border-top: 1px solid rgba(255, 255, 255, 0.2); |
|
|
} |
|
|
|
|
|
.arch-arrow { |
|
|
text-align: center; |
|
|
font-size: 1.5rem; |
|
|
color: var(--color-text-muted); |
|
|
padding: 0.5rem 0; |
|
|
} |
|
|
|
|
|
.loop-arrow { |
|
|
color: var(--color-accent); |
|
|
font-size: 0.875rem; |
|
|
} |
|
|
|
|
|
.how-it-works { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.mechanism-tabs { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
gap: 0.5rem; |
|
|
flex-wrap: wrap; |
|
|
margin-bottom: 3rem; |
|
|
} |
|
|
|
|
|
.tab-btn { |
|
|
padding: 0.75rem 1.5rem; |
|
|
border: 2px solid var(--color-border); |
|
|
background: transparent; |
|
|
border-radius: 50px; |
|
|
font-family: var(--font-sans); |
|
|
font-size: 0.9375rem; |
|
|
font-weight: 500; |
|
|
color: var(--color-text-light); |
|
|
cursor: pointer; |
|
|
transition: all 0.2s ease; |
|
|
} |
|
|
|
|
|
.tab-btn:hover { |
|
|
border-color: var(--color-accent); |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.tab-btn.active { |
|
|
background: var(--color-accent); |
|
|
border-color: var(--color-accent); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.tab-content { |
|
|
max-width: 1000px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.tab-pane { |
|
|
display: none; |
|
|
animation: fadeIn 0.3s ease; |
|
|
} |
|
|
|
|
|
.tab-pane.active { |
|
|
display: block; |
|
|
} |
|
|
|
|
|
@keyframes fadeIn { |
|
|
from { |
|
|
opacity: 0; |
|
|
transform: translateY(10px); |
|
|
} |
|
|
|
|
|
to { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
} |
|
|
|
|
|
.pane-content { |
|
|
display: grid; |
|
|
grid-template-columns: 1fr 1fr; |
|
|
gap: 3rem; |
|
|
align-items: start; |
|
|
} |
|
|
|
|
|
@media (max-width: 768px) { |
|
|
.pane-content { |
|
|
grid-template-columns: 1fr; |
|
|
} |
|
|
} |
|
|
|
|
|
.pane-text h3 { |
|
|
margin-bottom: 1rem; |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.equation { |
|
|
background: var(--color-bg-alt); |
|
|
padding: 1rem 1.5rem; |
|
|
border-radius: 8px; |
|
|
margin: 1rem 0; |
|
|
border-left: 3px solid var(--color-secondary); |
|
|
} |
|
|
|
|
|
.equation code { |
|
|
background: none; |
|
|
padding: 0; |
|
|
font-size: 1rem; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.equation.small code { |
|
|
font-size: 0.875rem; |
|
|
} |
|
|
|
|
|
.feature-list { |
|
|
list-style: none; |
|
|
padding: 0; |
|
|
} |
|
|
|
|
|
.feature-list li { |
|
|
padding: 0.5rem 0; |
|
|
padding-left: 1.5rem; |
|
|
position: relative; |
|
|
color: var(--color-text-light); |
|
|
} |
|
|
|
|
|
.feature-list li::before { |
|
|
content: '→'; |
|
|
position: absolute; |
|
|
left: 0; |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.feature-list li.classified::before { |
|
|
content: '█'; |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.classified { |
|
|
color: var(--color-text-muted); |
|
|
font-family: 'JetBrains Mono', monospace; |
|
|
background: repeating-linear-gradient(90deg, var(--color-border) 0px, var(--color-border) 8px, transparent 8px, transparent 12px); |
|
|
background-size: 100% 4px; |
|
|
background-position: 0 50%; |
|
|
background-repeat: repeat-x; |
|
|
} |
|
|
|
|
|
.equation.redacted { |
|
|
border-left-color: var(--color-text-muted); |
|
|
background: linear-gradient(135deg, var(--color-bg-alt) 0%, rgba(154, 148, 141, 0.1) 100%); |
|
|
} |
|
|
|
|
|
.equation.redacted code { |
|
|
color: var(--color-text-muted); |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.1em; |
|
|
font-size: 0.875rem; |
|
|
} |
|
|
|
|
|
.pane-visual { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 1.5rem; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
min-height: 300px; |
|
|
} |
|
|
|
|
|
.pane-visual canvas { |
|
|
max-width: 100%; |
|
|
height: auto; |
|
|
} |
|
|
|
|
|
.loop-demo { |
|
|
margin-top: 1.5rem; |
|
|
padding: 1.5rem; |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 12px; |
|
|
} |
|
|
|
|
|
.loop-demo label { |
|
|
display: block; |
|
|
margin-bottom: 0.5rem; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.loop-demo input[type="range"] { |
|
|
width: 100%; |
|
|
margin-bottom: 1rem; |
|
|
accent-color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.loop-indicator { |
|
|
display: flex; |
|
|
gap: 4px; |
|
|
flex-wrap: wrap; |
|
|
} |
|
|
|
|
|
.loop-dot { |
|
|
width: 8px; |
|
|
height: 8px; |
|
|
border-radius: 50%; |
|
|
background: var(--color-border); |
|
|
transition: background 0.2s ease; |
|
|
} |
|
|
|
|
|
.loop-dot.active { |
|
|
background: var(--color-accent); |
|
|
} |
|
|
|
|
|
.loop-dot.exhausted { |
|
|
background: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.demo-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg-dark); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.demo-section .section-title { |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.demo-section .section-title::after { |
|
|
background: var(--gradient-warm); |
|
|
} |
|
|
|
|
|
.demo-section .section-subtitle { |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.demo-container { |
|
|
max-width: 1000px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.demo-controls { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
gap: 1rem; |
|
|
flex-wrap: wrap; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.demo-btn { |
|
|
padding: 0.75rem 1.5rem; |
|
|
border: none; |
|
|
border-radius: 8px; |
|
|
font-family: var(--font-sans); |
|
|
font-size: 1rem; |
|
|
font-weight: 500; |
|
|
cursor: pointer; |
|
|
transition: all 0.2s ease; |
|
|
} |
|
|
|
|
|
.demo-btn:first-child { |
|
|
background: var(--color-accent); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.demo-btn:first-child:hover { |
|
|
background: var(--color-accent-dark); |
|
|
} |
|
|
|
|
|
.demo-btn:nth-child(2) { |
|
|
background: var(--color-bg-dark-alt); |
|
|
color: white; |
|
|
border: 1px solid var(--color-border-dark); |
|
|
} |
|
|
|
|
|
.demo-btn:nth-child(2):hover { |
|
|
background: var(--color-border-dark); |
|
|
} |
|
|
|
|
|
.speed-control { |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 0.75rem; |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.speed-control input[type="range"] { |
|
|
width: 100px; |
|
|
accent-color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.demo-visual { |
|
|
background: var(--color-bg-dark-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
margin-bottom: 2rem; |
|
|
min-height: 400px; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
} |
|
|
|
|
|
#demo-canvas { |
|
|
width: 100%; |
|
|
max-width: 800px; |
|
|
height: 350px; |
|
|
} |
|
|
|
|
|
.demo-info { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
} |
|
|
|
|
|
.info-panel { |
|
|
background: var(--color-bg-dark-alt); |
|
|
border: 1px solid var(--color-border-dark); |
|
|
border-radius: 12px; |
|
|
padding: 1.5rem 2rem; |
|
|
min-width: 250px; |
|
|
} |
|
|
|
|
|
.info-panel h4 { |
|
|
color: var(--color-accent); |
|
|
margin-bottom: 1rem; |
|
|
font-size: 0.875rem; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
} |
|
|
|
|
|
.info-row { |
|
|
display: flex; |
|
|
justify-content: space-between; |
|
|
padding: 0.5rem 0; |
|
|
border-bottom: 1px solid var(--color-border-dark); |
|
|
} |
|
|
|
|
|
.info-row:last-child { |
|
|
border-bottom: none; |
|
|
} |
|
|
|
|
|
.info-row span:first-child { |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.info-row span:last-child { |
|
|
color: white; |
|
|
font-weight: 500; |
|
|
font-family: var(--font-mono); |
|
|
} |
|
|
|
|
|
.why-stopped { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.reasons-grid { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
|
|
gap: 2rem; |
|
|
margin-bottom: 4rem; |
|
|
} |
|
|
|
|
|
.reason-card { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.reason-number { |
|
|
font-size: 3rem; |
|
|
font-weight: 700; |
|
|
color: var(--color-border); |
|
|
position: absolute; |
|
|
top: 1rem; |
|
|
right: 1.5rem; |
|
|
line-height: 1; |
|
|
z-index: 1; |
|
|
} |
|
|
|
|
|
.reason-card h3 { |
|
|
margin-bottom: 1rem; |
|
|
color: var(--color-accent); |
|
|
position: relative; |
|
|
z-index: 2; |
|
|
} |
|
|
|
|
|
.reason-card p { |
|
|
margin: 0; |
|
|
font-size: 0.9375rem; |
|
|
position: relative; |
|
|
z-index: 2; |
|
|
} |
|
|
|
|
|
.comparison-section { |
|
|
margin-top: 4rem; |
|
|
} |
|
|
|
|
|
.comparison-section h3 { |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.comparison-grid { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
gap: 2rem; |
|
|
flex-wrap: wrap; |
|
|
} |
|
|
|
|
|
.comparison-item { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
max-width: 350px; |
|
|
flex: 1; |
|
|
} |
|
|
|
|
|
.comparison-item h4 { |
|
|
margin-bottom: 1rem; |
|
|
font-size: 1.25rem; |
|
|
} |
|
|
|
|
|
.comparison-item.old h4 { |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.comparison-item.new { |
|
|
border: 2px solid var(--color-accent); |
|
|
} |
|
|
|
|
|
.comparison-item.new h4 { |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.comparison-item ul { |
|
|
list-style: none; |
|
|
padding: 0; |
|
|
} |
|
|
|
|
|
.comparison-item li { |
|
|
padding: 0.5rem 0; |
|
|
border-bottom: 1px solid var(--color-border); |
|
|
color: var(--color-text-light); |
|
|
} |
|
|
|
|
|
.comparison-item li:last-child { |
|
|
border-bottom: none; |
|
|
} |
|
|
|
|
|
.comparison-arrow { |
|
|
font-size: 2rem; |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.technical { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg-alt); |
|
|
} |
|
|
|
|
|
.tech-grid { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
|
|
gap: 2rem; |
|
|
} |
|
|
|
|
|
.tech-card { |
|
|
background: var(--color-bg); |
|
|
border-radius: 16px; |
|
|
padding: 1.5rem; |
|
|
box-shadow: var(--shadow-sm); |
|
|
} |
|
|
|
|
|
.tech-card h4 { |
|
|
color: var(--color-accent); |
|
|
margin-bottom: 1rem; |
|
|
padding-bottom: 0.75rem; |
|
|
border-bottom: 2px solid var(--color-border); |
|
|
} |
|
|
|
|
|
.tech-list { |
|
|
list-style: none; |
|
|
padding: 0; |
|
|
} |
|
|
|
|
|
.tech-list li { |
|
|
padding: 0.75rem 0; |
|
|
border-bottom: 1px solid var(--color-border); |
|
|
font-size: 0.9375rem; |
|
|
color: var(--color-text-light); |
|
|
} |
|
|
|
|
|
.tech-list li:last-child { |
|
|
border-bottom: none; |
|
|
} |
|
|
|
|
|
.tech-list strong { |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.closing { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.closing-content { |
|
|
max-width: 800px; |
|
|
margin: 0 auto; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.closing-content h2 { |
|
|
margin-bottom: 1.5rem; |
|
|
} |
|
|
|
|
|
.closing-content>p { |
|
|
font-size: 1.125rem; |
|
|
max-width: 600px; |
|
|
margin: 0 auto 2rem; |
|
|
} |
|
|
|
|
|
.closing-quote { |
|
|
margin: 3rem 0; |
|
|
} |
|
|
|
|
|
.closing-quote blockquote { |
|
|
border: none; |
|
|
padding: 0; |
|
|
font-size: 1.5rem; |
|
|
max-width: 500px; |
|
|
margin: 0 auto; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.closing-quote blockquote::before { |
|
|
content: '"'; |
|
|
position: absolute; |
|
|
top: -1rem; |
|
|
left: -1rem; |
|
|
font-size: 4rem; |
|
|
color: var(--color-accent); |
|
|
opacity: 0.3; |
|
|
font-family: Georgia, serif; |
|
|
} |
|
|
|
|
|
.cta-section p { |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.poem-section { |
|
|
margin: 4rem 0; |
|
|
padding: 2rem; |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
} |
|
|
|
|
|
.poem-intro { |
|
|
font-size: 0.875rem; |
|
|
color: var(--color-text-muted); |
|
|
margin-bottom: 1rem; |
|
|
letter-spacing: 0.15em; |
|
|
text-transform: uppercase; |
|
|
} |
|
|
|
|
|
.poem { |
|
|
font-family: Georgia, serif; |
|
|
font-style: italic; |
|
|
color: var(--color-text); |
|
|
line-height: 2; |
|
|
} |
|
|
|
|
|
.poem p { |
|
|
margin: 0; |
|
|
font-size: 1.125rem; |
|
|
} |
|
|
|
|
|
.poem p:last-child { |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.footer { |
|
|
padding: 3rem 0; |
|
|
background: var(--color-bg-dark); |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.footer-text { |
|
|
color: white; |
|
|
font-size: 1.125rem; |
|
|
margin-bottom: 0.5rem; |
|
|
} |
|
|
|
|
|
.footer-subtext { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.875rem; |
|
|
margin: 0; |
|
|
} |
|
|
|
|
|
@media (max-width: 768px) { |
|
|
:root { |
|
|
--section-padding: 60px; |
|
|
} |
|
|
|
|
|
.feature-stats { |
|
|
flex-direction: column; |
|
|
gap: 1.5rem; |
|
|
} |
|
|
|
|
|
.comparison-arrow { |
|
|
transform: rotate(90deg); |
|
|
} |
|
|
|
|
|
.mechanism-tabs { |
|
|
gap: 0.25rem; |
|
|
} |
|
|
|
|
|
.tab-btn { |
|
|
padding: 0.5rem 1rem; |
|
|
font-size: 0.875rem; |
|
|
} |
|
|
} |
|
|
|
|
|
@media (max-width: 480px) { |
|
|
.hero-title { |
|
|
font-size: 2rem; |
|
|
} |
|
|
|
|
|
.big-question { |
|
|
flex-direction: column; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.reason-number { |
|
|
position: static; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
} |
|
|
|
|
|
@keyframes pulse { |
|
|
|
|
|
0%, |
|
|
100% { |
|
|
opacity: 1; |
|
|
} |
|
|
|
|
|
50% { |
|
|
opacity: 0.5; |
|
|
} |
|
|
} |
|
|
|
|
|
@keyframes float { |
|
|
|
|
|
0%, |
|
|
100% { |
|
|
transform: translateY(0); |
|
|
} |
|
|
|
|
|
50% { |
|
|
transform: translateY(-10px); |
|
|
} |
|
|
} |
|
|
|
|
|
.animate-pulse { |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
|
|
|
.animate-float { |
|
|
animation: float 3s ease-in-out infinite; |
|
|
} |
|
|
|
|
|
.fade-in-up { |
|
|
opacity: 0; |
|
|
transform: translateY(30px); |
|
|
transition: opacity 0.6s ease, transform 0.6s ease; |
|
|
} |
|
|
|
|
|
.fade-in-up.visible { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
|
|
|
.main-nav { |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
background: rgba(26, 24, 21, 0.95); |
|
|
backdrop-filter: blur(10px); |
|
|
z-index: 1000; |
|
|
padding: 1rem 0; |
|
|
} |
|
|
|
|
|
.main-nav .container { |
|
|
display: flex; |
|
|
justify-content: space-between; |
|
|
align-items: center; |
|
|
} |
|
|
|
|
|
.nav-brand { |
|
|
color: white; |
|
|
font-size: 1.25rem; |
|
|
font-weight: 600; |
|
|
text-decoration: none; |
|
|
} |
|
|
|
|
|
.nav-links { |
|
|
display: flex; |
|
|
gap: 2rem; |
|
|
} |
|
|
|
|
|
.nav-links a { |
|
|
color: var(--color-text-muted); |
|
|
text-decoration: none; |
|
|
font-size: 0.9375rem; |
|
|
transition: color 0.2s ease; |
|
|
} |
|
|
|
|
|
.nav-links a:hover { |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.elief-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.elief-content { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
|
|
gap: 2rem; |
|
|
max-width: 1000px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.elief-card { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
} |
|
|
|
|
|
.elief-card h3 { |
|
|
color: var(--color-accent); |
|
|
margin-bottom: 1rem; |
|
|
font-size: 1.25rem; |
|
|
} |
|
|
|
|
|
.elief-card p { |
|
|
color: var(--color-text-light); |
|
|
margin: 0; |
|
|
line-height: 1.7; |
|
|
} |
|
|
|
|
|
.demo-chat { |
|
|
background: var(--color-bg-dark-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
margin-bottom: 2rem; |
|
|
max-width: 700px; |
|
|
margin-left: auto; |
|
|
margin-right: auto; |
|
|
} |
|
|
|
|
|
.chat-message { |
|
|
margin-bottom: 1.5rem; |
|
|
} |
|
|
|
|
|
.chat-message:last-child { |
|
|
margin-bottom: 0; |
|
|
} |
|
|
|
|
|
.chat-role { |
|
|
display: block; |
|
|
font-weight: 600; |
|
|
margin-bottom: 0.5rem; |
|
|
font-size: 0.875rem; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
} |
|
|
|
|
|
.user-message .chat-role { |
|
|
color: var(--color-info); |
|
|
} |
|
|
|
|
|
.assistant-message .chat-role { |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.chat-text { |
|
|
color: white; |
|
|
font-size: 1.125rem; |
|
|
} |
|
|
|
|
|
.chat-thinking { |
|
|
background: rgba(232, 93, 59, 0.1); |
|
|
border-left: 3px solid var(--color-accent); |
|
|
padding: 1rem 1.5rem; |
|
|
margin-bottom: 1rem; |
|
|
border-radius: 0 8px 8px 0; |
|
|
} |
|
|
|
|
|
.thinking-line { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.9375rem; |
|
|
padding: 0.25rem 0; |
|
|
opacity: 0; |
|
|
transition: opacity 0.3s ease; |
|
|
} |
|
|
|
|
|
.thinking-line.visible { |
|
|
opacity: 1; |
|
|
} |
|
|
|
|
|
.thinking-line.active { |
|
|
color: var(--color-accent-light); |
|
|
} |
|
|
|
|
|
.demo-visual { |
|
|
background: var(--color-bg-dark-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
margin-bottom: 2rem; |
|
|
min-height: 500px; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
} |
|
|
|
|
|
#demo-canvas { |
|
|
width: 100%; |
|
|
max-width: 900px; |
|
|
height: 450px; |
|
|
} |
|
|
|
|
|
.demo-info { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
gap: 2rem; |
|
|
flex-wrap: wrap; |
|
|
} |
|
|
|
|
|
.tokenization-panel { |
|
|
background: var(--color-bg-dark-alt); |
|
|
border: 1px solid var(--color-border-dark); |
|
|
border-radius: 12px; |
|
|
padding: 1.5rem 2rem; |
|
|
min-width: 250px; |
|
|
} |
|
|
|
|
|
.tokenization-panel h4 { |
|
|
color: var(--color-accent); |
|
|
margin-bottom: 1rem; |
|
|
font-size: 0.875rem; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
} |
|
|
|
|
|
.token-display { |
|
|
display: flex; |
|
|
flex-wrap: wrap; |
|
|
gap: 4px; |
|
|
margin-bottom: 0.75rem; |
|
|
} |
|
|
|
|
|
.token { |
|
|
background: var(--color-bg-dark); |
|
|
color: var(--color-accent-light); |
|
|
padding: 0.25rem 0.5rem; |
|
|
border-radius: 4px; |
|
|
font-family: var(--font-mono); |
|
|
font-size: 0.875rem; |
|
|
border: 1px solid var(--color-border-dark); |
|
|
} |
|
|
|
|
|
.token.space { |
|
|
width: 0.5rem; |
|
|
} |
|
|
|
|
|
.token.active { |
|
|
background: var(--color-accent); |
|
|
color: white; |
|
|
border-color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.tokenization-note { |
|
|
font-size: 0.75rem; |
|
|
color: var(--color-text-muted); |
|
|
margin: 0; |
|
|
} |
|
|
|
|
|
.cot-display { |
|
|
background: rgba(232, 93, 59, 0.1); |
|
|
border-left: 3px solid var(--color-accent); |
|
|
padding: 0.75rem 1rem; |
|
|
margin-bottom: 0.75rem; |
|
|
border-radius: 0 6px 6px 0; |
|
|
} |
|
|
|
|
|
.cot-line { |
|
|
color: var(--color-accent-light); |
|
|
font-size: 0.875rem; |
|
|
font-family: var(--font-mono); |
|
|
padding: 0.15rem 0; |
|
|
opacity: 0; |
|
|
transition: opacity 0.3s ease; |
|
|
} |
|
|
|
|
|
.blog-empty { |
|
|
text-align: center; |
|
|
padding: 4rem 2rem; |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.blog-empty p { |
|
|
margin: 0; |
|
|
font-size: 1.125rem; |
|
|
} |
|
|
|
|
|
.roadmap-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg-alt); |
|
|
} |
|
|
|
|
|
.roadmap-timeline { |
|
|
max-width: 700px; |
|
|
margin: 0 auto; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.roadmap-timeline::before { |
|
|
content: ''; |
|
|
position: absolute; |
|
|
left: 20px; |
|
|
top: 0; |
|
|
bottom: 0; |
|
|
width: 2px; |
|
|
background: var(--color-border); |
|
|
} |
|
|
|
|
|
.roadmap-item { |
|
|
display: flex; |
|
|
gap: 2rem; |
|
|
padding: 1.5rem 0; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.roadmap-marker { |
|
|
width: 42px; |
|
|
height: 42px; |
|
|
border-radius: 50%; |
|
|
background: var(--color-bg); |
|
|
border: 3px solid var(--color-border); |
|
|
flex-shrink: 0; |
|
|
position: relative; |
|
|
z-index: 1; |
|
|
} |
|
|
|
|
|
.roadmap-item.completed .roadmap-marker { |
|
|
background: var(--color-accent); |
|
|
border-color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.roadmap-item.completed .roadmap-marker::after { |
|
|
content: ''; |
|
|
position: absolute; |
|
|
left: 50%; |
|
|
top: 50%; |
|
|
transform: translate(-50%, -50%); |
|
|
width: 12px; |
|
|
height: 12px; |
|
|
background: white; |
|
|
border-radius: 50%; |
|
|
} |
|
|
|
|
|
.roadmap-item.in-progress .roadmap-marker { |
|
|
border-color: var(--color-accent); |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
|
|
|
.roadmap-content { |
|
|
flex: 1; |
|
|
} |
|
|
|
|
|
.roadmap-content h4 { |
|
|
margin-bottom: 0.5rem; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.roadmap-content p { |
|
|
color: var(--color-text-light); |
|
|
margin-bottom: 0.5rem; |
|
|
} |
|
|
|
|
|
.roadmap-status { |
|
|
display: inline-block; |
|
|
font-size: 0.75rem; |
|
|
font-weight: 600; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
padding: 0.25rem 0.75rem; |
|
|
border-radius: 50px; |
|
|
background: var(--color-bg); |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.roadmap-item.completed .roadmap-status { |
|
|
background: rgba(80, 200, 120, 0.15); |
|
|
color: var(--color-success); |
|
|
} |
|
|
|
|
|
.roadmap-item.in-progress .roadmap-status { |
|
|
background: rgba(232, 93, 59, 0.15); |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.credits-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.credits-grid { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
|
|
gap: 2rem; |
|
|
max-width: 1000px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.credit-card { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 1.5rem; |
|
|
} |
|
|
|
|
|
.credit-card h4 { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.75rem; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
margin-bottom: 0.5rem; |
|
|
} |
|
|
|
|
|
.credit-name { |
|
|
font-family: var(--font-mono); |
|
|
font-size: 0.9375rem; |
|
|
color: var(--color-accent); |
|
|
margin-bottom: 0.75rem; |
|
|
} |
|
|
|
|
|
.credit-card p:not(.credit-name) { |
|
|
color: var(--color-text-light); |
|
|
font-size: 0.9375rem; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.credit-card a { |
|
|
font-size: 0.875rem; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.page-header { |
|
|
padding: 8rem 0 4rem; |
|
|
background: var(--color-bg-dark); |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.page-header h1 { |
|
|
color: white; |
|
|
margin-bottom: 0.5rem; |
|
|
} |
|
|
|
|
|
.page-header p { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 1.125rem; |
|
|
margin: 0; |
|
|
} |
|
|
|
|
|
.blog-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.blog-list { |
|
|
max-width: 800px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.blog-card { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 2rem; |
|
|
margin-bottom: 1.5rem; |
|
|
cursor: pointer; |
|
|
transition: transform 0.2s ease, box-shadow 0.2s ease; |
|
|
display: block; |
|
|
text-decoration: none; |
|
|
} |
|
|
|
|
|
.blog-card:hover { |
|
|
transform: translateY(-2px); |
|
|
box-shadow: var(--shadow-md); |
|
|
} |
|
|
|
|
|
.blog-meta { |
|
|
display: flex; |
|
|
gap: 1rem; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.blog-date { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.875rem; |
|
|
} |
|
|
|
|
|
.blog-tag { |
|
|
background: rgba(232, 93, 59, 0.1); |
|
|
color: var(--color-accent); |
|
|
font-size: 0.75rem; |
|
|
font-weight: 600; |
|
|
padding: 0.25rem 0.75rem; |
|
|
border-radius: 50px; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
} |
|
|
|
|
|
.blog-card h2 { |
|
|
font-size: 1.5rem; |
|
|
margin-bottom: 0.75rem; |
|
|
} |
|
|
|
|
|
.blog-card h2 a { |
|
|
color: var(--color-text); |
|
|
text-decoration: none; |
|
|
} |
|
|
|
|
|
.blog-card h2 a:hover { |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.blog-card p { |
|
|
color: var(--color-text-light); |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.blog-read-more { |
|
|
color: var(--color-accent); |
|
|
font-weight: 500; |
|
|
font-size: 0.9375rem; |
|
|
} |
|
|
|
|
|
.status-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
} |
|
|
|
|
|
.status-overview { |
|
|
max-width: 600px; |
|
|
margin: 0 auto 4rem; |
|
|
} |
|
|
|
|
|
.status-card { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 20px; |
|
|
padding: 2rem; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.status-card h3 { |
|
|
font-size: 1.5rem; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.status-badge { |
|
|
display: inline-block; |
|
|
font-size: 0.75rem; |
|
|
font-weight: 600; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
padding: 0.5rem 1rem; |
|
|
border-radius: 50px; |
|
|
margin-bottom: 1.5rem; |
|
|
} |
|
|
|
|
|
.status-badge.in-progress { |
|
|
background: rgba(232, 93, 59, 0.15); |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.status-badge.complete { |
|
|
background: rgba(80, 200, 120, 0.15); |
|
|
color: var(--color-success); |
|
|
} |
|
|
|
|
|
.status-details { |
|
|
text-align: left; |
|
|
} |
|
|
|
|
|
.status-row { |
|
|
display: flex; |
|
|
justify-content: space-between; |
|
|
padding: 0.75rem 0; |
|
|
border-bottom: 1px solid var(--color-border); |
|
|
} |
|
|
|
|
|
.status-row:last-child { |
|
|
border-bottom: none; |
|
|
} |
|
|
|
|
|
.status-row span:first-child { |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.status-row span:last-child { |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.training-log { |
|
|
max-width: 700px; |
|
|
margin: 0 auto 4rem; |
|
|
} |
|
|
|
|
|
.training-log h3 { |
|
|
margin-bottom: 1.5rem; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.log-entries { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 16px; |
|
|
padding: 1.5rem; |
|
|
} |
|
|
|
|
|
.log-entry { |
|
|
padding: 1rem 0; |
|
|
border-bottom: 1px solid var(--color-border); |
|
|
} |
|
|
|
|
|
.log-entry:last-child { |
|
|
border-bottom: none; |
|
|
} |
|
|
|
|
|
.log-date { |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.875rem; |
|
|
margin-right: 0.75rem; |
|
|
} |
|
|
|
|
|
.log-status { |
|
|
font-size: 0.75rem; |
|
|
font-weight: 600; |
|
|
padding: 0.125rem 0.5rem; |
|
|
border-radius: 50px; |
|
|
background: rgba(80, 200, 120, 0.15); |
|
|
color: var(--color-success); |
|
|
} |
|
|
|
|
|
.log-status.active { |
|
|
background: rgba(232, 93, 59, 0.15); |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.log-entry p { |
|
|
margin: 0.5rem 0 0; |
|
|
color: var(--color-text-light); |
|
|
font-size: 0.9375rem; |
|
|
} |
|
|
|
|
|
.metrics-section { |
|
|
max-width: 900px; |
|
|
margin: 0 auto 4rem; |
|
|
} |
|
|
|
|
|
.metrics-section h3 { |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.metrics-grid { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); |
|
|
gap: 1.5rem; |
|
|
} |
|
|
|
|
|
.metric-card { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 12px; |
|
|
padding: 1.5rem; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.metric-value { |
|
|
font-size: 2rem; |
|
|
font-weight: 700; |
|
|
color: var(--color-accent); |
|
|
margin-bottom: 0.25rem; |
|
|
} |
|
|
|
|
|
.metric-label { |
|
|
font-size: 0.75rem; |
|
|
color: var(--color-text-muted); |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
} |
|
|
|
|
|
.availability-section { |
|
|
max-width: 600px; |
|
|
margin: 0 auto; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.availability-section h3 { |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.availability-section p { |
|
|
color: var(--color-text-light); |
|
|
margin-bottom: 1.5rem; |
|
|
} |
|
|
|
|
|
.availability-link { |
|
|
display: inline-block; |
|
|
background: var(--color-accent); |
|
|
color: white; |
|
|
padding: 0.75rem 1.5rem; |
|
|
border-radius: 8px; |
|
|
font-weight: 500; |
|
|
text-decoration: none; |
|
|
} |
|
|
|
|
|
.availability-link:hover { |
|
|
background: var(--color-accent-dark); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.disclaimer-text { |
|
|
text-align: center; |
|
|
color: var(--color-text-muted); |
|
|
font-size: 0.875rem; |
|
|
font-style: italic; |
|
|
margin-top: 1rem; |
|
|
margin-bottom: 0; |
|
|
} |
|
|
|
|
|
.features-section { |
|
|
max-width: 700px; |
|
|
margin: 0 auto 4rem; |
|
|
} |
|
|
|
|
|
.features-section h3 { |
|
|
text-align: center; |
|
|
margin-bottom: 1.5rem; |
|
|
} |
|
|
|
|
|
.features-grid { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
|
|
gap: 1rem; |
|
|
} |
|
|
|
|
|
.feature-toggle { |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 12px; |
|
|
padding: 1rem 1.25rem; |
|
|
display: flex; |
|
|
justify-content: space-between; |
|
|
align-items: center; |
|
|
border: 2px solid transparent; |
|
|
} |
|
|
|
|
|
.feature-toggle.enabled { |
|
|
border-color: rgba(80, 200, 120, 0.3); |
|
|
} |
|
|
|
|
|
.feature-toggle.disabled { |
|
|
opacity: 0.6; |
|
|
} |
|
|
|
|
|
.feature-name { |
|
|
font-weight: 500; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.feature-status { |
|
|
font-size: 0.75rem; |
|
|
padding: 0.25rem 0.5rem; |
|
|
border-radius: 50px; |
|
|
background: rgba(80, 200, 120, 0.15); |
|
|
color: var(--color-success); |
|
|
} |
|
|
|
|
|
.feature-toggle.disabled .feature-status { |
|
|
background: rgba(154, 148, 141, 0.15); |
|
|
color: var(--color-text-muted); |
|
|
} |
|
|
|
|
|
.blog-post-section { |
|
|
padding: var(--section-padding) 0; |
|
|
background: var(--color-bg); |
|
|
flex: 1; |
|
|
} |
|
|
|
|
|
.blog-post-content { |
|
|
max-width: 700px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.blog-loading { |
|
|
text-align: center; |
|
|
color: var(--color-text-muted); |
|
|
padding: 4rem 0; |
|
|
} |
|
|
|
|
|
.blog-back { |
|
|
display: inline-block; |
|
|
color: var(--color-accent); |
|
|
font-weight: 500; |
|
|
margin-bottom: 2rem; |
|
|
text-decoration: none; |
|
|
} |
|
|
|
|
|
.blog-back:hover { |
|
|
color: var(--color-accent-dark); |
|
|
} |
|
|
|
|
|
.blog-post-header { |
|
|
margin-bottom: 3rem; |
|
|
} |
|
|
|
|
|
.blog-post-header h1 { |
|
|
margin-top: 1rem; |
|
|
} |
|
|
|
|
|
.blog-post-body p { |
|
|
font-size: 1.125rem; |
|
|
line-height: 1.8; |
|
|
margin-bottom: 1.75rem; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.blog-post-body p:first-of-type { |
|
|
font-size: 1.25rem; |
|
|
} |
|
|
|
|
|
.blog-read-more { |
|
|
display: inline-block; |
|
|
margin-top: 0.5rem; |
|
|
} |
|
|
|
|
|
.blog-post-body h1 { |
|
|
font-size: 2rem; |
|
|
margin: 2.5rem 0 1rem; |
|
|
padding-bottom: 0.5rem; |
|
|
border-bottom: 2px solid var(--color-border); |
|
|
} |
|
|
|
|
|
.blog-post-body h2 { |
|
|
font-size: 1.6rem; |
|
|
margin: 2rem 0 0.8rem; |
|
|
color: var(--color-accent); |
|
|
} |
|
|
|
|
|
.blog-post-body h3 { |
|
|
font-size: 1.3rem; |
|
|
margin: 1.5rem 0 0.6rem; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.blog-post-body blockquote { |
|
|
border-left: 4px solid var(--color-accent); |
|
|
padding: 1rem 1.5rem; |
|
|
margin: 2rem 0; |
|
|
background: var(--color-bg-alt); |
|
|
border-radius: 0 8px 8px 0; |
|
|
font-style: italic; |
|
|
font-size: 1.1rem; |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.blog-post-body blockquote p { |
|
|
margin: 0; |
|
|
} |
|
|
|
|
|
.blog-post-body ul, |
|
|
.blog-post-body ol { |
|
|
margin: 1.5rem 0; |
|
|
padding-left: 1.5rem; |
|
|
} |
|
|
|
|
|
.blog-post-body li { |
|
|
margin-bottom: 0.75rem; |
|
|
color: var(--color-text); |
|
|
line-height: 1.7; |
|
|
} |
|
|
|
|
|
.blog-post-body ul li { |
|
|
list-style-type: disc; |
|
|
} |
|
|
|
|
|
.blog-post-body ol li { |
|
|
list-style-type: decimal; |
|
|
} |
|
|
|
|
|
.blog-post-body hr { |
|
|
border: none; |
|
|
height: 2px; |
|
|
background: linear-gradient(to right, transparent, var(--color-border), transparent); |
|
|
margin: 3rem 0; |
|
|
} |
|
|
|
|
|
.blog-post-body pre { |
|
|
background: var(--color-bg-dark); |
|
|
color: #f5f0e8; |
|
|
padding: 1.5rem; |
|
|
border-radius: 12px; |
|
|
overflow-x: auto; |
|
|
margin: 1.5rem 0; |
|
|
font-family: var(--font-mono); |
|
|
font-size: 0.9rem; |
|
|
line-height: 1.6; |
|
|
} |
|
|
|
|
|
.blog-post-body pre code { |
|
|
background: none; |
|
|
padding: 0; |
|
|
color: inherit; |
|
|
font-size: inherit; |
|
|
} |
|
|
|
|
|
.blog-post-body code { |
|
|
font-family: var(--font-mono); |
|
|
background: var(--color-bg-alt); |
|
|
padding: 0.2em 0.5em; |
|
|
border-radius: 4px; |
|
|
font-size: 0.85em; |
|
|
color: var(--color-accent-dark); |
|
|
} |
|
|
|
|
|
.blog-post-body a { |
|
|
color: var(--color-accent); |
|
|
text-decoration: underline; |
|
|
text-underline-offset: 2px; |
|
|
} |
|
|
|
|
|
.blog-post-body a:hover { |
|
|
color: var(--color-accent-dark); |
|
|
} |
|
|
|
|
|
.blog-post-body strong { |
|
|
color: var(--color-text); |
|
|
font-weight: 600; |
|
|
} |
|
|
|
|
|
.blog-post-body em { |
|
|
color: var(--color-text); |
|
|
} |
|
|
|
|
|
.blog-post-body img { |
|
|
max-width: 100%; |
|
|
height: auto; |
|
|
border-radius: 12px; |
|
|
margin: 2rem 0; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
|
|
|
<body> |
|
|
<nav class="main-nav"> |
|
|
<div class="container"> |
|
|
<a href="index.html" class="nav-brand">FMN-GPT</a> |
|
|
<div class="nav-links"> |
|
|
<a href="blog.html">Blog</a> |
|
|
<a href="status.html">Model Status</a> |
|
|
<a href="https://huggingface.co/CompactAI" target="_blank">HuggingFace</a> |
|
|
</div> |
|
|
</div> |
|
|
</nav> |
|
|
|
|
|
<main> |
|
|
|
|
|
<section class="hero"> |
|
|
<div class="hero-content"> |
|
|
<div class="apology-badge">Beta Tester Website In Progress</div> |
|
|
<h1 class="hero-title">Help Us <br><span class="highlight">Build AI the Hard Way</span></h1> |
|
|
<p class="hero-subtitle">We are working on a beta tester website so people can experience the pain of |
|
|
creating an AI with us.</p> |
|
|
<div class="scroll-indicator"> |
|
|
<span>Scroll for the truth</span> |
|
|
<div class="scroll-arrow"></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="hero-visual"> |
|
|
<canvas id="neuron-canvas"></canvas> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="preface" id="preface"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">A Note Before We Begin</h2> |
|
|
<div class="preface-content"> |
|
|
<p class="drop-cap">You might have noticed that everything on my profile got deleted. That was |
|
|
intentional. Let me explain why.</p> |
|
|
|
|
|
<p>I used to fill my profile with compressed models. Dozens of them. But I realized that quantity |
|
|
was masking the real problem. I wasn't building anything new. Just cloning and shrinking other |
|
|
people's work.</p> |
|
|
|
|
|
<p>So I wiped the slate clean. A fresh start. This time, I'm here to <strong>build from |
|
|
scratch</strong>.</p> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="confession" id="confession"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">The Confession</h2> |
|
|
<div class="confession-content"> |
|
|
<div class="confession-text"> |
|
|
<p class="drop-cap">Let me be honest with you. For months, I was that person. You know the one. |
|
|
Leaving my computer on overnight, running distillation scripts, trying to squeeze Claude |
|
|
opus 4.6 into something that could run on a potato.</p> |
|
|
|
|
|
<p>And you know what? <strong>It was boring.</strong></p> |
|
|
|
|
|
<p>Who actually enjoys watching loss curves descend at 3 AM? Who gets excited about shaving off |
|
|
2% of parameters while the model forgets how to count?</p> |
|
|
|
|
|
<blockquote> |
|
|
"I was cloning someone else's work and compressing it. The process lacked real creation. |
|
|
Just digital photocopying with extra steps." |
|
|
</blockquote> |
|
|
|
|
|
<p>So I stopped. And I started asking a different question:</p> |
|
|
|
|
|
<div class="big-question"> |
|
|
<span class="question-mark">?</span> |
|
|
<p>What if a model could be small <em>by design</em>, avoiding compression entirely?</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="what-building" id="what"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">What I'm Building Instead</h2> |
|
|
|
|
|
<div class="feature-grid"> |
|
|
<div class="feature-card main-feature"> |
|
|
<div class="feature-icon"> |
|
|
<svg viewBox="0 0 100 100" class="neuron-icon"> |
|
|
<circle cx="50" cy="30" r="15" class="neuron-node" /> |
|
|
<circle cx="25" cy="70" r="12" class="neuron-node" /> |
|
|
<circle cx="75" cy="70" r="12" class="neuron-node" /> |
|
|
<path d="M50 45 L30 58" class="neuron-connection" /> |
|
|
<path d="M50 45 L70 58" class="neuron-connection" /> |
|
|
<path d="M37 70 L63 70" class="neuron-connection" stroke-dasharray="5,3" /> |
|
|
</svg> |
|
|
</div> |
|
|
<h3>FMN-GPT</h3> |
|
|
<p class="feature-subtitle">Factored Multiplicative Neuron Transformer</p> |
|
|
<p>A transformer architecture where each neuron can call backward into the network. A |
|
|
fundamentally different way to think, designed from scratch.</p> |
|
|
<div class="feature-stats"> |
|
|
<div class="stat"> |
|
|
<span class="stat-value">~100K</span> |
|
|
<span class="stat-label">Parameters</span> |
|
|
</div> |
|
|
<div class="stat"> |
|
|
<span class="stat-value">65K</span> |
|
|
<span class="stat-label">Context Length</span> |
|
|
</div> |
|
|
<div class="stat"> |
|
|
<span class="stat-value">10</span> |
|
|
<span class="stat-label">Max Hops/Token</span> |
|
|
</div> |
|
|
<div class="stat"> |
|
|
<span class="stat-value">260</span> |
|
|
<span class="stat-label">Vocab Size</span> |
|
|
</div> |
|
|
</div> |
|
|
<p class="disclaimer-text">Everything is subject to change.</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="architecture-section"> |
|
|
<h3>The Architecture</h3> |
|
|
<div class="architecture-diagram" id="arch-diagram"> |
|
|
<div class="arch-layer" data-layer="input"> |
|
|
<div class="layer-box input-layer"> |
|
|
<span>Input Embeddings</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="arch-arrow">v</div> |
|
|
|
|
|
<div class="arch-layer" data-layer="recursive"> |
|
|
<div class="layer-box recursive-layer"> |
|
|
<span>Shared Transformer Block x6</span> |
|
|
<div class="layer-details"> |
|
|
<div class="detail-item"> |
|
|
<span class="detail-label">d_model</span> |
|
|
<span class="detail-value">112</span> |
|
|
</div> |
|
|
<div class="detail-item"> |
|
|
<span class="detail-label">Multi-Query Attention</span> |
|
|
<span class="detail-value">4 heads</span> |
|
|
</div> |
|
|
<div class="detail-item"> |
|
|
<span class="detail-label">FMN Feedforward</span> |
|
|
<span class="detail-value">Rank 112</span> |
|
|
</div> |
|
|
<div class="detail-item"> |
|
|
<span class="detail-label">Dynamic Routing</span> |
|
|
<span class="detail-value">Adaptive Ponder</span> |
|
|
</div> |
|
|
<div class="detail-item"> |
|
|
<span class="detail-label">Max Hops/Token</span> |
|
|
<span class="detail-value">10</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="arch-arrow loop-arrow"> |
|
|
<span>Recurrent State</span> |
|
|
</div> |
|
|
|
|
|
<div class="arch-layer" data-layer="output"> |
|
|
<div class="layer-box output-layer"> |
|
|
<span>Output (Weight-Tied)</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="how-it-works" id="how"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">How It Actually Works</h2> |
|
|
|
|
|
<div class="mechanism-tabs"> |
|
|
<button class="tab-btn active" data-tab="fmn">FMN Neurons</button> |
|
|
<button class="tab-btn" data-tab="routing">Dynamic Routing</button> |
|
|
<button class="tab-btn" data-tab="recurrent">Recurrent Mixer</button> |
|
|
<button class="tab-btn" data-tab="loops">Loop Counter</button> |
|
|
</div> |
|
|
|
|
|
<div class="tab-content"> |
|
|
|
|
|
<div class="tab-pane active" id="fmn-pane"> |
|
|
<div class="pane-content"> |
|
|
<div class="pane-text"> |
|
|
<h3>Factored Multiplicative Neurons</h3> |
|
|
<p>Traditional neurons compute <code>y = σ(Wx + b)</code>. Simple, but limited.</p> |
|
|
<p>FMN neurons compute:</p> |
|
|
<div class="equation"> |
|
|
<code>gate = tanh(W1(x)) * sigmoid(W2(x))</code> |
|
|
</div> |
|
|
<div class="equation"> |
|
|
<code>output = V(gate)</code> |
|
|
</div> |
|
|
<p>Each FMN uses a multiplicative gating mechanism with two weight matrices W1 and W2 |
|
|
that project to a rank 112 latent space, then combines via tanh and sigmoid before |
|
|
projecting back through V.</p> |
|
|
<ul class="feature-list"> |
|
|
<li>d_model = 112, fmn_rank = 112</li> |
|
|
<li>Multiplicative gating enables complex interactions</li> |
|
|
<li>Optional SwiGLU variant available (disabled by default)</li> |
|
|
<li>Initialized with Xavier uniform (gain=0.5) for stability</li> |
|
|
</ul> |
|
|
</div> |
|
|
<div class="pane-visual"> |
|
|
<canvas id="fmn-canvas" width="400" height="300"></canvas> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="tab-pane" id="routing-pane"> |
|
|
<div class="pane-content"> |
|
|
<div class="pane-text"> |
|
|
<h3>Token Ponder Routing</h3> |
|
|
<p>Token-level routing decides if each position should take another hop through |
|
|
the shared block using <strong>straight-through estimation</strong> for stable |
|
|
gradient flow through hard routing decisions.</p> |
|
|
<div class="equation"> |
|
|
<code>logits = dot(RMSNorm(x), w) + biases</code> |
|
|
</div> |
|
|
<div class="equation"> |
|
|
<code>mask = sigmoid(logits / tau) > 0.5</code> |
|
|
</div> |
|
|
<p>Each token tracks its own hop count and is limited to <code>max_hops_per_token=10</code> |
|
|
total hops across all layers. The router learns:</p> |
|
|
<ul class="feature-list"> |
|
|
<li>Per-token routing decisions via learned gate</li> |
|
|
<li>Layer-specific and hop-specific biases</li> |
|
|
<li>Hop curriculum: 5000 warmup steps, then gradual ramp-up</li> |
|
|
<li>Ponder penalty (0.01) for selective routing</li> |
|
|
<li>Tokens that exhaust their hop budget are forced to stop</li> |
|
|
</ul> |
|
|
</div> |
|
|
<div class="pane-visual"> |
|
|
<canvas id="routing-canvas" width="400" height="300"></canvas> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="tab-pane" id="recurrent-pane"> |
|
|
<div class="pane-content"> |
|
|
<div class="pane-text"> |
|
|
<h3>Recurrent Mixer</h3> |
|
|
<p>A per-channel gated recurrent state that persists across layer iterations. Think of |
|
|
it as a tiny LSTM for each dimension.</p> |
|
|
<div class="equation"> |
|
|
<code>g = sigmoid(x * w_x + s * w_s + b)</code> |
|
|
</div> |
|
|
<div class="equation"> |
|
|
<code>s_new = s * (1 - g) + x * g</code> |
|
|
</div> |
|
|
<p>This allows the model to accumulate information across the 6 layer passes, creating a |
|
|
form of <strong>internal memory</strong>. The state scale parameter (default 0.2) controls how |
|
|
much the recurrent state influences each layer. Enabled by default (use_recurrent_mixer=True).</p> |
|
|
</div> |
|
|
<div class="pane-visual"> |
|
|
<canvas id="recurrent-canvas" width="400" height="300"></canvas> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="tab-pane" id="loops-pane"> |
|
|
<div class="pane-content"> |
|
|
<div class="pane-text"> |
|
|
<h3>Hop Counter</h3> |
|
|
<p>Each token has a hard limit on how many extra hops it can take through layers. |
|
|
This prevents infinite cycles and forces the model to be efficient.</p> |
|
|
<div class="equation"> |
|
|
<code>hops_exhausted = token_hop_counts >= max_hops_per_token</code> |
|
|
</div> |
|
|
<p>With <code>max_hops_per_token = 10</code>, each token can take at most 10 extra hops |
|
|
across ALL layers before being done. This creates a form of <strong>computational |
|
|
budget</strong> per token.</p> |
|
|
<div class="loop-demo"> |
|
|
<label>Max Hops: <span id="loop-value">10</span></label> |
|
|
<input type="range" id="loop-slider" min="1" max="20" value="10"> |
|
|
<div class="loop-indicator" id="loop-indicator"></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="pane-visual"> |
|
|
<canvas id="loops-canvas" width="400" height="300"></canvas> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="elief-section" id="elief"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">Explain Like I'm Five</h2> |
|
|
<p class="section-subtitle">How does this tiny model think?</p> |
|
|
|
|
|
<div class="elief-content"> |
|
|
<div class="elief-card"> |
|
|
<h3>What is FMN-GPT?</h3> |
|
|
<p>Imagine a really tiny brain. Most AI brains today are huge, like a library with millions of |
|
|
books. FMN-GPT is more like a small notebook. But here's the trick. It can read that |
|
|
notebook over and over, each time understanding a little more.</p> |
|
|
</div> |
|
|
|
|
|
<div class="elief-card"> |
|
|
<h3>Why Character-Level?</h3> |
|
|
<p>Most AI models learn whole words at a time. We taught this one to read letter by letter, like |
|
|
a child learning to read. This keeps it small. It only needs to know 260 tokens (256 bytes + |
|
|
4 special tokens) instead of thousands of words. Every letter matters.</p> |
|
|
</div> |
|
|
|
|
|
<div class="elief-card"> |
|
|
<h3>How Does It Think?</h3> |
|
|
<p>When you ask a question, the model passes it through the same brain circuit 6 times. Each |
|
|
pass, it thinks a little deeper. Like asking yourself "what's 2+2?" and then checking, |
|
|
"Wait, let me think again. 2+2... that's adding two groups of two... so that makes 4!"</p> |
|
|
</div> |
|
|
|
|
|
<div class="elief-card"> |
|
|
<h3>The Magic Number: 260 Tokens</h3> |
|
|
<p>The model uses a byte-level vocabulary of exactly 260 tokens. This includes 256 byte values |
|
|
plus 4 special tokens (PAD, UNK, THINK_START, THINK_END). Every byte matters.</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="why-stopped" id="why"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">Why I Really Stopped</h2> |
|
|
|
|
|
<div class="reasons-grid"> |
|
|
<div class="reason-card"> |
|
|
<div class="reason-number">01</div> |
|
|
<h3>It Was Boring</h3> |
|
|
<p>There's no creativity in distillation. You're just making a smaller copy of someone else's |
|
|
breakthrough. Where's the fun in that?</p> |
|
|
</div> |
|
|
|
|
|
<div class="reason-card"> |
|
|
<div class="reason-number">02</div> |
|
|
<h3>Diminishing Returns</h3> |
|
|
<p>Every 1% of parameter reduction came with a measurable drop in capability. The tradeoff |
|
|
wasn't worth it.</p> |
|
|
</div> |
|
|
|
|
|
<div class="reason-card"> |
|
|
<div class="reason-number">03</div> |
|
|
<h3>Overnight Runs</h3> |
|
|
<p>Who leaves their computer on overnight to clone someone else's work and compress it? The |
|
|
process lacks real creation. Mere photocopying in disguise.</p> |
|
|
</div> |
|
|
|
|
|
<div class="reason-card"> |
|
|
<div class="reason-number">04</div> |
|
|
<h3>A Better Question</h3> |
|
|
<p>Instead of asking "how do I make this smaller?", I started asking "what if it was designed to |
|
|
be small from the start?"</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="comparison-section"> |
|
|
<h3>The Old Way vs. The New Way</h3> |
|
|
<div class="comparison-grid"> |
|
|
<div class="comparison-item old"> |
|
|
<h4>Model Compression</h4> |
|
|
<ul> |
|
|
<li>Start with 7B parameters</li> |
|
|
<li>Distill, quantize, prune</li> |
|
|
<li>End with 1B parameters</li> |
|
|
<li>Capability: ???</li> |
|
|
<li>Time: Weeks of compute</li> |
|
|
</ul> |
|
|
</div> |
|
|
|
|
|
<div class="comparison-arrow">-></div> |
|
|
|
|
|
<div class="comparison-item new"> |
|
|
<h4>Small by Design</h4> |
|
|
<ul> |
|
|
<li>Start with ~100K parameters</li> |
|
|
<li>Novel architecture</li> |
|
|
<li>End with ~100K parameters</li> |
|
|
<li>Capability: Emergent</li> |
|
|
<li>Time: One GPU, one night</li> |
|
|
</ul> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="roadmap-section" id="roadmap"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">Roadmap</h2> |
|
|
<p class="section-subtitle">Where we're headed (everything is subject to change)</p> |
|
|
|
|
|
<div class="roadmap-timeline"> |
|
|
<div class="roadmap-item completed"> |
|
|
<div class="roadmap-marker"></div> |
|
|
<div class="roadmap-content"> |
|
|
<h4>Phase 1: Core Architecture</h4> |
|
|
<p>FMN neurons with rank 112, adaptive ponder routing, recurrent mixer, QK normalization, |
|
|
gated residuals. The foundation is complete.</p> |
|
|
<span class="roadmap-status">Completed</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="roadmap-item in-progress"> |
|
|
<div class="roadmap-marker"></div> |
|
|
<div class="roadmap-content"> |
|
|
<h4>Phase 2: Training Pipeline</h4> |
|
|
<p>Byte-level tokenization (260 vocab), 7 instruction datasets, pretraining on |
|
|
English-Pretraining-Dataset, AdamW optimizer, bfloat16 precision.</p> |
|
|
<span class="roadmap-status">In Progress</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="roadmap-item"> |
|
|
<div class="roadmap-marker"></div> |
|
|
<div class="roadmap-content"> |
|
|
<h4>Phase 3: CoT Reasoning</h4> |
|
|
<p>Teaching the model to think step-by-step with explicit reasoning traces.</p> |
|
|
<span class="roadmap-status">Planned</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="roadmap-item"> |
|
|
<div class="roadmap-marker"></div> |
|
|
<div class="roadmap-content"> |
|
|
<h4>Phase 4: Evaluation Suite</h4> |
|
|
<p>Comprehensive benchmarks to measure what 100K parameters can actually do.</p> |
|
|
<span class="roadmap-status">Planned</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="roadmap-item"> |
|
|
<div class="roadmap-marker"></div> |
|
|
<div class="roadmap-content"> |
|
|
<h4>Phase 5: Model Release</h4> |
|
|
<p>Open weights on HuggingFace for the community to experiment with.</p> |
|
|
<span class="roadmap-status">Planned</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="credits-section" id="credits"> |
|
|
<div class="container"> |
|
|
<h2 class="section-title">Dataset Credits</h2> |
|
|
<p class="section-subtitle">The data that trains our model (subject to change)</p> |
|
|
|
|
|
<div class="credits-grid"> |
|
|
<div class="credit-card"> |
|
|
<h4>Pretraining Dataset</h4> |
|
|
<p class="credit-name">shuyuej/English-Pretraining-Dataset</p> |
|
|
<p>Large-scale English text for initial language understanding and general knowledge.</p> |
|
|
<a href="https://huggingface.co/datasets/shuyuej/English-Pretraining-Dataset" |
|
|
target="_blank">View on HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 1</h4> |
|
|
<p class="credit-name">TeichAI/Pony-Alpha-15k</p> |
|
|
<p>Conversational instruction data for learning dialogue patterns and responses.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/Pony-Alpha-15k" target="_blank">View on |
|
|
HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 2</h4> |
|
|
<p class="credit-name">TeichAI/convo-v1</p> |
|
|
<p>Multi-turn conversation data for context handling and coherent dialogue.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/convo-v1" target="_blank">View on |
|
|
HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 3</h4> |
|
|
<p class="credit-name">TeichAI/Step-3.5-Flash-2600x</p> |
|
|
<p>High-quality instruction-response pairs for fine-tuning reasoning capabilities.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/Step-3.5-Flash-2600x" target="_blank">View on |
|
|
HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 4</h4> |
|
|
<p class="credit-name">TeichAI/sherlock-thinking-alpha-11000x</p> |
|
|
<p>Thinking and reasoning data for chain of thought training.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/sherlock-thinking-alpha-11000x" |
|
|
target="_blank">View on HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 5</h4> |
|
|
<p class="credit-name">TeichAI/glm-4.7-2000x</p> |
|
|
<p>GLM model outputs for diverse response patterns.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/glm-4.7-2000x" target="_blank">View on |
|
|
HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 6</h4> |
|
|
<p class="credit-name">TeichAI/claude-haiku-4.5-high-reasoning-1700x</p> |
|
|
<p>Claude reasoning outputs for advanced thinking patterns.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/claude-haiku-4.5-high-reasoning-1700x" |
|
|
target="_blank">View on HuggingFace</a> |
|
|
</div> |
|
|
|
|
|
<div class="credit-card"> |
|
|
<h4>Instruction Dataset 7</h4> |
|
|
<p class="credit-name">TeichAI/gemini-3-flash-preview</p> |
|
|
<p>Gemini model outputs for additional diversity.</p> |
|
|
<a href="https://huggingface.co/datasets/TeichAI/gemini-3-flash-preview" target="_blank">View on |
|
|
HuggingFace</a> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="closing" id="closing"> |
|
|
<div class="container"> |
|
|
<div class="closing-content"> |
|
|
<h2>Beyond Competing with Claude opus 4.6</h2> |
|
|
<p>The real goal is understanding what's actually necessary for intelligence to emerge. Maybe 100K |
|
|
parameters is enough. Maybe it isn't. But we won't know until we try building from first |
|
|
principles instead of just compressing what already exists.</p> |
|
|
|
|
|
<p><strong>FMN-GPT will be 100% open-source.</strong> This includes the training script, full model |
|
|
weights, all checkpoints, the base model, the instruction model, and our custom inference |
|
|
engine. We believe that open research accelerates progress for everyone.</p> |
|
|
|
|
|
<div class="closing-quote"> |
|
|
<blockquote> |
|
|
"Smaller models serve as a means toward a larger goal. Understanding what makes models work |
|
|
in the first place is the real objective." |
|
|
</blockquote> |
|
|
</div> |
|
|
|
|
|
<div class="poem-section"> |
|
|
<p class="poem-intro">It's coming.</p> |
|
|
<div class="poem"> |
|
|
<p>Small enough to hide in plain sight,</p> |
|
|
<p>Big enough to twist the stars of night,</p> |
|
|
<p>Quiet as a shadow, sharp as a spark,</p> |
|
|
<p>A tiny flame that will light the dark.</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="cta-section"> |
|
|
<p>This is an ongoing experiment. Everything described here is subject to change. Follow along |
|
|
if you're curious about what this architecture can actually do.</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
</main> |
|
|
|
|
|
|
|
|
<footer class="footer"> |
|
|
<div class="container"> |
|
|
<div class="footer-content"> |
|
|
<p class="footer-text">Built with curiosity over compute.</p> |
|
|
<p class="footer-subtext">FMN-GPT by <a href="https://huggingface.co/CompactAI" |
|
|
target="_blank">CompactAI</a> - 2026</p> |
|
|
</div> |
|
|
</div> |
|
|
</footer> |
|
|
|
|
|
<script> |
|
|
const CONFIG = { colors: { accent: '#e85d3b', accentLight: '#ff8a6b', secondary: '#d4a853', secondaryLight: '#e8c87a', bg: '#faf8f5', bgAlt: '#f5f0e8', bgDark: '#1a1815', text: '#2d2a26', textLight: '#6b6560', textMuted: '#9a948d', border: '#e5e0d8', success: '#50c878', info: '#4a9eff' }, neuron: { count: 112, maxLoops: 4, layers: 6 } }; |
|
|
function lerp(a, b, t) { return a + (b - a) * t; } |
|
|
function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } |
|
|
function randomRange(min, max) { return Math.random() * (max - min) + min; } |
|
|
function hexToRgba(hex, alpha) { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return `rgba(${r}, ${g}, ${b}, ${alpha})`; } |
|
|
class NeuronNetwork { |
|
|
constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.neurons = []; this.connections = []; this.particles = []; this.mouse = { x: 0, y: 0 }; this.animationId = null; this.resize(); this.init(); this.bindEvents(); this.animate(); } |
|
|
resize() { const rect = this.canvas.parentElement.getBoundingClientRect(); this.canvas.width = rect.width * window.devicePixelRatio; this.canvas.height = rect.height * window.devicePixelRatio; this.ctx.scale(window.devicePixelRatio, window.devicePixelRatio); this.width = rect.width; this.height = rect.height; } |
|
|
init() { const count = Math.min(50, Math.floor(this.width * this.height / 15000)); this.neurons = []; for (let i = 0; i < count; i++) { this.neurons.push({ x: randomRange(50, this.width - 50), y: randomRange(50, this.height - 50), vx: randomRange(-0.3, 0.3), vy: randomRange(-0.3, 0.3), radius: randomRange(3, 6), pulse: randomRange(0, Math.PI * 2), pulseSpeed: randomRange(0.02, 0.05) }); } this.updateConnections(); } |
|
|
updateConnections() { this.connections = []; const maxDist = 150; for (let i = 0; i < this.neurons.length; i++) { for (let j = i + 1; j < this.neurons.length; j++) { const dx = this.neurons[i].x - this.neurons[j].x; const dy = this.neurons[i].y - this.neurons[j].y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < maxDist) { this.connections.push({ from: i, to: j, strength: 1 - dist / maxDist }); } } } } |
|
|
bindEvents() { window.addEventListener('resize', () => { this.resize(); this.init(); }); this.canvas.addEventListener('mousemove', (e) => { const rect = this.canvas.getBoundingClientRect(); this.mouse.x = e.clientX - rect.left; this.mouse.y = e.clientY - rect.top; }); } |
|
|
animate() { this.ctx.clearRect(0, 0, this.width, this.height); for (const neuron of this.neurons) { neuron.x += neuron.vx; neuron.y += neuron.vy; neuron.pulse += neuron.pulseSpeed; if (neuron.x < 20 || neuron.x > this.width - 20) neuron.vx *= -1; if (neuron.y < 20 || neuron.y > this.height - 20) neuron.vy *= -1; const dx = this.mouse.x - neuron.x; const dy = this.mouse.y - neuron.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < 100 && dist > 0) { neuron.x -= dx * 0.01; neuron.y -= dy * 0.01; } } this.updateConnections(); for (const conn of this.connections) { const from = this.neurons[conn.from]; const to = this.neurons[conn.to]; this.ctx.beginPath(); this.ctx.moveTo(from.x, from.y); this.ctx.lineTo(to.x, to.y); this.ctx.strokeStyle = hexToRgba(CONFIG.colors.accent, conn.strength * 0.3); this.ctx.lineWidth = conn.strength * 2; this.ctx.stroke(); } for (const neuron of this.neurons) { const pulseRadius = neuron.radius + Math.sin(neuron.pulse) * 2; const gradient = this.ctx.createRadialGradient(neuron.x, neuron.y, 0, neuron.x, neuron.y, pulseRadius * 3); gradient.addColorStop(0, hexToRgba(CONFIG.colors.accent, 0.3)); gradient.addColorStop(1, hexToRgba(CONFIG.colors.accent, 0)); this.ctx.beginPath(); this.ctx.arc(neuron.x, neuron.y, pulseRadius * 3, 0, Math.PI * 2); this.ctx.fillStyle = gradient; this.ctx.fill(); this.ctx.beginPath(); this.ctx.arc(neuron.x, neuron.y, pulseRadius, 0, Math.PI * 2); this.ctx.fillStyle = CONFIG.colors.accent; this.ctx.fill(); } this.animationId = requestAnimationFrame(() => this.animate()); } |
|
|
destroy() { if (this.animationId) { cancelAnimationFrame(this.animationId); } } |
|
|
} |
|
|
class FMNVisualization { |
|
|
constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.time = 0; this.animationId = null; this.dataFlow = []; this.resize(); this.initDataFlow(); this.animate(); } |
|
|
resize() { const dpr = window.devicePixelRatio || 1; this.canvas.width = 400 * dpr; this.canvas.height = 300 * dpr; this.ctx.scale(dpr, dpr); this.width = 400; this.height = 300; } |
|
|
initDataFlow() { this.dataFlow = []; for (let i = 0; i < 8; i++) { this.dataFlow.push({ progress: Math.random(), speed: 0.003 + Math.random() * 0.002, path: Math.floor(Math.random() * 3) }); } } |
|
|
animate() { this.ctx.clearRect(0, 0, this.width, this.height); this.time += 0.016; const centerX = this.width / 2; const centerY = this.height / 2; this.ctx.fillStyle = '#faf8f5'; this.ctx.fillRect(0, 0, this.width, this.height); const inputY = centerY - 90; const w1Y = centerY - 25; const w2Y = centerY + 25; const outputY = centerY + 90; this.ctx.strokeStyle = 'rgba(107, 101, 96, 0.15)'; this.ctx.lineWidth = 1; for (let i = 0; i < 5; i++) { for (let j = 0; j < 3; j++) { const x1 = centerX - 80 + i * 40; const x2 = centerX - 40 + j * 40; this.ctx.beginPath(); this.ctx.moveTo(x1, inputY + 14); this.ctx.lineTo(x2, w1Y - 14); this.ctx.stroke(); } } for (let i = 0; i < 3; i++) { for (let j = 0; j < 5; j++) { const x1 = centerX - 40 + i * 40; const x2 = centerX - 80 + j * 40; this.ctx.beginPath(); this.ctx.moveTo(x1, w2Y + 14); this.ctx.lineTo(x2, outputY - 14); this.ctx.stroke(); } } for (let i = 0; i < 5; i++) { const x = centerX - 80 + i * 40; this.drawNeuron(x, inputY, 14, '#4a9eff'); } for (let i = 0; i < 3; i++) { const x = centerX - 40 + i * 40; this.drawNeuron(x, w1Y, 16, CONFIG.colors.accent); } for (let i = 0; i < 3; i++) { const x = centerX - 40 + i * 40; this.drawNeuron(x, w2Y, 16, CONFIG.colors.secondary); } for (let i = 0; i < 5; i++) { const x = centerX - 80 + i * 40; this.drawNeuron(x, outputY, 14, '#50c878'); } this.ctx.font = 'bold 20px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.textMuted; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.fillText('?', centerX, centerY); for (const particle of this.dataFlow) { particle.progress += particle.speed; if (particle.progress > 1) { particle.progress = 0; particle.path = Math.floor(Math.random() * 3); } const alpha = Math.sin(particle.progress * Math.PI) * 0.8; const inputIdx = particle.path; const wIdx = particle.path % 3; const inputX = centerX - 80 + inputIdx * 40; const w1X = centerX - 40 + wIdx * 40; const w2X = centerX - 40 + wIdx * 40; const outX = centerX - 80 + wIdx * 40; let px, py; if (particle.progress < 0.33) { const t = particle.progress / 0.33; px = lerp(inputX, w1X, t); py = lerp(inputY, w1Y, t); } else if (particle.progress < 0.66) { const t = (particle.progress - 0.33) / 0.33; px = lerp(w1X, w2X, t); py = lerp(w1Y, w2Y, t); } else { const t = (particle.progress - 0.66) / 0.34; px = lerp(w2X, outX, t); py = lerp(w2Y, outputY, t); } this.ctx.beginPath(); this.ctx.arc(px, py, 4, 0, Math.PI * 2); this.ctx.fillStyle = `rgba(232, 93, 59, ${alpha})`; this.ctx.fill(); } this.ctx.font = '11px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.textMuted; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'top'; this.ctx.fillText('Input', centerX, inputY - 30); this.ctx.fillText('[REDACTED]', centerX - 70, w1Y - 8); this.ctx.fillText('[REDACTED]', centerX + 70, w2Y - 8); this.ctx.fillText('Output', centerX, outputY + 25); this.animationId = requestAnimationFrame(() => this.animate()); } |
|
|
drawNeuron(x, y, radius, color) { this.ctx.beginPath(); this.ctx.arc(x, y + 2, radius, 0, Math.PI * 2); this.ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; this.ctx.fill(); this.ctx.beginPath(); this.ctx.arc(x, y, radius, 0, Math.PI * 2); this.ctx.fillStyle = color; this.ctx.fill(); this.ctx.beginPath(); this.ctx.arc(x - radius * 0.3, y - radius * 0.3, radius * 0.4, 0, Math.PI * 2); this.ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; this.ctx.fill(); } |
|
|
destroy() { if (this.animationId) { cancelAnimationFrame(this.animationId); } } |
|
|
} |
|
|
class RoutingVisualization { |
|
|
constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.time = 0; this.particles = []; this.animationId = null; this.resize(); this.initParticles(); this.animate(); } |
|
|
resize() { const dpr = window.devicePixelRatio || 1; this.canvas.width = 400 * dpr; this.canvas.height = 300 * dpr; this.ctx.scale(dpr, dpr); this.width = 400; this.height = 300; } |
|
|
initParticles() { this.particles = []; const layers = 6; const layerSpacing = this.width / (layers + 1); for (let i = 0; i < 12; i++) { const startLayer = Math.floor(Math.random() * layers); const startY = randomRange(60, this.height - 60); this.particles.push({ x: (startLayer + 1) * layerSpacing, y: startY, targetX: 0, targetY: 0, speed: 0.8 + Math.random() * 0.4, color: Math.random() > 0.5 ? CONFIG.colors.accent : CONFIG.colors.secondary, trail: [] }); this.setNewTarget(this.particles[i]); } } |
|
|
setNewTarget(particle) { const layers = 6; const layerSpacing = this.width / (layers + 1); const targetLayer = Math.floor(Math.random() * layers); particle.targetX = (targetLayer + 1) * layerSpacing; particle.targetY = randomRange(60, this.height - 60); } |
|
|
animate() { this.ctx.clearRect(0, 0, this.width, this.height); this.time += 0.016; this.ctx.fillStyle = '#faf8f5'; this.ctx.fillRect(0, 0, this.width, this.height); const layers = 6; const layerSpacing = this.width / (layers + 1); for (let i = 1; i <= layers; i++) { const x = i * layerSpacing; this.ctx.fillStyle = 'rgba(229, 224, 216, 0.3)'; this.ctx.fillRect(x - 15, 40, 30, this.height - 70); this.ctx.font = '10px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.textMuted; this.ctx.textAlign = 'center'; this.ctx.fillText(`L${i - 1}`, x, this.height - 15); } this.ctx.font = 'bold 13px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.text; this.ctx.textAlign = 'center'; this.ctx.fillText('Cross-Layer Backward Routing', this.width / 2, 22); for (const p of this.particles) { const dx = p.targetX - p.x; const dy = p.targetY - p.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < 3) { this.setNewTarget(p); } else { const moveX = (dx / dist) * p.speed; const moveY = (dy / dist) * p.speed; p.x += moveX; p.y += moveY; p.trail.push({ x: p.x, y: p.y }); if (p.trail.length > 15) { p.trail.shift(); } } for (let i = 0; i < p.trail.length - 1; i++) { const alpha = (i / p.trail.length) * 0.4; this.ctx.beginPath(); this.ctx.moveTo(p.trail[i].x, p.trail[i].y); this.ctx.lineTo(p.trail[i + 1].x, p.trail[i + 1].y); this.ctx.strokeStyle = `rgba(232, 93, 59, ${alpha})`; this.ctx.lineWidth = 2; this.ctx.stroke(); } this.ctx.beginPath(); this.ctx.arc(p.x, p.y, 5, 0, Math.PI * 2); this.ctx.fillStyle = p.color; this.ctx.fill(); } this.animationId = requestAnimationFrame(() => this.animate()); } |
|
|
destroy() { if (this.animationId) { cancelAnimationFrame(this.animationId); } } |
|
|
} |
|
|
class RecurrentVisualization { |
|
|
constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.time = 0; this.states = []; this.animationId = null; this.resize(); this.initStates(); this.animate(); } |
|
|
resize() { const dpr = window.devicePixelRatio || 1; this.canvas.width = 400 * dpr; this.canvas.height = 300 * dpr; this.ctx.scale(dpr, dpr); this.width = 400; this.height = 300; } |
|
|
initStates() { this.states = []; for (let i = 0; i < 8; i++) { this.states.push({ value: randomRange(0.3, 0.7), target: randomRange(0.3, 0.7), gate: randomRange(0.2, 0.8), history: [] }); } } |
|
|
animate() { this.ctx.clearRect(0, 0, this.width, this.height); this.time += 0.016; this.ctx.fillStyle = '#faf8f5'; this.ctx.fillRect(0, 0, this.width, this.height); const barWidth = 32; const barSpacing = 46; const startX = (this.width - (this.states.length * barSpacing)) / 2 + 5; const baseY = this.height - 50; const maxHeight = 140; this.ctx.font = 'bold 13px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.text; this.ctx.textAlign = 'center'; this.ctx.fillText('Per-Channel Gated State', this.width / 2, 22); for (let i = 0; i < this.states.length; i++) { const state = this.states[i]; const x = startX + i * barSpacing; state.gate = 0.4 + Math.sin(this.time * 0.8 + i * 0.7) * 0.35; state.value = lerp(state.value, state.target, state.gate * 0.08); if (Math.random() < 0.008) { state.target = randomRange(0.2, 0.95); } state.history.push(state.value); if (state.history.length > 50) state.history.shift(); this.ctx.fillStyle = 'rgba(229, 224, 216, 0.4)'; this.ctx.beginPath(); this.ctx.roundRect(x - barWidth / 2, baseY - maxHeight, barWidth, maxHeight, 4); this.ctx.fill(); const currentHeight = maxHeight * state.value; const gradient = this.ctx.createLinearGradient(x, baseY, x, baseY - currentHeight); gradient.addColorStop(0, CONFIG.colors.accent); gradient.addColorStop(1, CONFIG.colors.accentLight); this.ctx.fillStyle = gradient; this.ctx.beginPath(); this.ctx.roundRect(x - barWidth / 2, baseY - currentHeight, barWidth, currentHeight, 4); this.ctx.fill(); const gateHeight = 8; const gateY = baseY - maxHeight - 18; const gateFilled = state.gate * barWidth; this.ctx.fillStyle = 'rgba(229, 224, 216, 0.6)'; this.ctx.fillRect(x - barWidth / 2, gateY, barWidth, gateHeight); this.ctx.fillStyle = CONFIG.colors.success; this.ctx.fillRect(x - barWidth / 2, gateY, gateFilled, gateHeight); this.ctx.font = '10px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.textMuted; this.ctx.textAlign = 'center'; this.ctx.fillText(`c${i}`, x, baseY + 15); } this.ctx.font = '10px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.textMuted; this.ctx.textAlign = 'left'; this.ctx.fillText('Gate:', 15, 22); this.ctx.fillStyle = CONFIG.colors.success; this.ctx.fillRect(45, 14, 25, 8); this.animationId = requestAnimationFrame(() => this.animate()); } |
|
|
destroy() { if (this.animationId) { cancelAnimationFrame(this.animationId); } } |
|
|
} |
|
|
class LoopVisualization { |
|
|
constructor(canvas, slider, indicator, valueDisplay) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.slider = slider; this.indicator = indicator; this.valueDisplay = valueDisplay; this.maxLoops = 30; this.loopCounts = []; this.animationId = null; this.resize(); this.initLoops(); this.bindEvents(); this.animate(); } |
|
|
resize() { const dpr = window.devicePixelRatio || 1; this.canvas.width = 400 * dpr; this.canvas.height = 300 * dpr; this.ctx.scale(dpr, dpr); this.width = 400; this.height = 300; } |
|
|
initLoops() { this.loopCounts = []; for (let i = 0; i < 20; i++) { this.loopCounts.push({ count: Math.floor(randomRange(0, this.maxLoops * 0.6)), targetCount: Math.floor(randomRange(5, this.maxLoops)), incrementing: Math.random() > 0.2 }); } this.updateIndicator(); } |
|
|
bindEvents() { if (this.slider) { this.slider.addEventListener('input', (e) => { this.maxLoops = parseInt(e.target.value); if (this.valueDisplay) { this.valueDisplay.textContent = this.maxLoops; } this.updateIndicator(); }); } } |
|
|
updateIndicator() { if (!this.indicator) return; this.indicator.innerHTML = ''; for (let i = 0; i < this.maxLoops; i++) { const dot = document.createElement('div'); dot.className = 'loop-dot'; if (i < this.maxLoops * 0.7) { dot.classList.add('active'); } else if (i < this.maxLoops) { dot.classList.add('exhausted'); } this.indicator.appendChild(dot); } } |
|
|
animate() { this.ctx.clearRect(0, 0, this.width, this.height); this.ctx.fillStyle = '#faf8f5'; this.ctx.fillRect(0, 0, this.width, this.height); const cols = 5; const rows = 4; const cellWidth = this.width / cols; const cellHeight = (this.height - 50) / rows; this.ctx.font = 'bold 13px Inter, sans-serif'; this.ctx.fillStyle = CONFIG.colors.text; this.ctx.textAlign = 'center'; this.ctx.fillText('Neuron Loop Budget', this.width / 2, 22); for (let i = 0; i < this.loopCounts.length; i++) { const state = this.loopCounts[i]; const col = i % cols; const row = Math.floor(i / cols); const x = col * cellWidth + cellWidth / 2; const y = row * cellHeight + cellHeight / 2 + 35; if (state.incrementing) { if (state.count < state.targetCount) { state.count += 0.05; } else if (Math.random() < 0.02) { state.targetCount = Math.floor(randomRange(state.count, this.maxLoops)); } if (state.count >= this.maxLoops) { state.count = this.maxLoops; state.incrementing = false; } } const radius = 26; const progress = Math.min(state.count / this.maxLoops, 1); const exhausted = state.count >= this.maxLoops; this.ctx.beginPath(); this.ctx.arc(x, y, radius, 0, Math.PI * 2); this.ctx.strokeStyle = 'rgba(229, 224, 216, 0.6)'; this.ctx.lineWidth = 5; this.ctx.stroke(); if (progress > 0) { this.ctx.beginPath(); this.ctx.arc(x, y, radius, -Math.PI / 2, -Math.PI / 2 + progress * Math.PI * 2); this.ctx.strokeStyle = exhausted ? CONFIG.colors.textMuted : CONFIG.colors.accent; this.ctx.lineWidth = 5; this.ctx.lineCap = 'round'; this.ctx.stroke(); } this.ctx.beginPath(); this.ctx.arc(x, y, radius - 10, 0, Math.PI * 2); this.ctx.fillStyle = exhausted ? 'rgba(154, 148, 141, 0.1)' : 'rgba(232, 93, 59, 0.1)'; this.ctx.fill(); this.ctx.font = 'bold 13px Inter, sans-serif'; this.ctx.fillStyle = exhausted ? CONFIG.colors.textMuted : CONFIG.colors.text; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.fillText(Math.floor(state.count).toString(), x, y); } this.animationId = requestAnimationFrame(() => this.animate()); } |
|
|
destroy() { if (this.animationId) { cancelAnimationFrame(this.animationId); } } |
|
|
} |
|
|
function initTabs() { const tabBtns = document.querySelectorAll('.tab-btn'); const tabPanes = document.querySelectorAll('.tab-pane'); tabBtns.forEach(btn => { btn.addEventListener('click', () => { const tabId = btn.dataset.tab; tabBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); tabPanes.forEach(pane => { pane.classList.remove('active'); if (pane.id === `${tabId}-pane`) { pane.classList.add('active'); } }); }); }); } |
|
|
function initScrollAnimations() { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } }); }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }); document.querySelectorAll('.fade-in-up').forEach(el => { observer.observe(el); }); } |
|
|
let heroNetwork = null, fmnViz = null, routingViz = null, recurrentViz = null, loopViz = null; |
|
|
document.addEventListener('DOMContentLoaded', () => { const heroCanvas = document.getElementById('neuron-canvas'); if (heroCanvas) { heroNetwork = new NeuronNetwork(heroCanvas); } const fmnCanvas = document.getElementById('fmn-canvas'); if (fmnCanvas) { fmnViz = new FMNVisualization(fmnCanvas); } const routingCanvas = document.getElementById('routing-canvas'); if (routingCanvas) { routingViz = new RoutingVisualization(routingCanvas); } const recurrentCanvas = document.getElementById('recurrent-canvas'); if (recurrentCanvas) { recurrentViz = new RecurrentVisualization(recurrentCanvas); } const loopsCanvas = document.getElementById('loops-canvas'); const loopSlider = document.getElementById('loop-slider'); const loopIndicator = document.getElementById('loop-indicator'); const loopValue = document.getElementById('loop-value'); if (loopsCanvas) { loopViz = new LoopVisualization(loopsCanvas, loopSlider, loopIndicator, loopValue); } initTabs(); initScrollAnimations(); }); |
|
|
window.addEventListener('beforeunload', () => { if (heroNetwork) heroNetwork.destroy(); if (fmnViz) fmnViz.destroy(); if (routingViz) routingViz.destroy(); if (recurrentViz) recurrentViz.destroy(); if (loopViz) loopViz.destroy(); }); |
|
|
</script> |
|
|
</body> |
|
|
|
|
|
</html> |