Skip to content

Commit 1769937

Browse files
Antigravity Agentclaude
andcommitted
feat: Green theme (#00FF88) + X-COM style TechTree
- Updated landing page theme from teal to eco-green (#00FF88) - New color scheme: Primary #00FF88, Dark #00CC66, BG #0a1a0f - Created X-COM style Research Laboratory TechTree component - 5 research branches: CORE, INFERENCE, OPTIMIZATION, DEPLOYMENT, HARDWARE - Interactive nodes with status: DONE/IN_PROGRESS/LOCKED - Animated SVG connections between research nodes - Click-to-view details panel with prerequisites/unlocks - Progress tracking bars (overall + per-branch) - Replaced RoadmapSection with TechTree in App.tsx 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent acdb5c2 commit 1769937

16 files changed

Lines changed: 1544 additions & 46 deletions

website/messages/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@
348348
{ "date": "Q1 2027", "title": "ASIC Tape-out", "desc": "First native SU(3) chip (TSMC 180nm)" }
349349
]
350350
},
351+
"techTree": {
352+
"title": "TRINITY <span style=\"color: var(--accent)\">RESEARCH</span> LABORATORY",
353+
"sub": "X-COM Style Technology Development Tree",
354+
"hint": "Click on nodes to view research details"
355+
},
351356
"product": {
352357
"title": "Product <span class=\"grad\">Roadmap</span>",
353358
"phases": [

website/src/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const TheoremsSection = lazy(() => import('./components/sections/TheoremsSection
1111
const SolutionSection = lazy(() => import('./components/sections/SolutionSection'))
1212
const BenchmarksSection = lazy(() => import('./components/sections/BenchmarksSection'))
1313
const CalculatorSection = lazy(() => import('./components/sections/CalculatorSection'))
14-
const RoadmapSection = lazy(() => import('./components/sections/RoadmapSection'))
14+
const TechTree = lazy(() => import('./components/TechTree/TechTree'))
1515
const TeamSection = lazy(() => import('./components/sections/TeamSection'))
1616
const InvestSection = lazy(() => import('./components/sections/InvestSection'))
1717

@@ -46,8 +46,8 @@ export default function App() {
4646
{/* 5. CALCULATOR - ROI with GPU/mining options */}
4747
<CalculatorSection />
4848

49-
{/* 6. ROADMAP - Simplified execution plan */}
50-
<RoadmapSection />
49+
{/* 6. TECH TREE - X-COM style research laboratory */}
50+
<TechTree />
5151

5252
{/* 7. TEAM - Trust builder (3 members max) */}
5353
<TeamSection />

website/src/components/QuantumCanvas.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export default function QuantumCanvas({ mode, particleCount = 1500, interactive
102102
const scale = Math.min(w, h) / 800;
103103

104104
// Background grid
105-
ctx.strokeStyle = 'rgba(0, 229, 153, 0.05)';
105+
ctx.strokeStyle = 'rgba(0, 255, 136, 0.05)';
106106
ctx.lineWidth = 1;
107107
for (let x = 0; x < w; x += 50) {
108108
ctx.beginPath();
@@ -121,17 +121,17 @@ export default function QuantumCanvas({ mode, particleCount = 1500, interactive
121121
const coreRadius = 120 * scale;
122122

123123
// Outer rotating ring
124-
ctx.strokeStyle = 'rgba(0, 229, 153, 0.3)';
124+
ctx.strokeStyle = 'rgba(0, 255, 136, 0.3)';
125125
ctx.lineWidth = 2;
126126
ctx.beginPath();
127127
ctx.arc(cx, cy, coreRadius + 40, 0, TAU);
128128
ctx.stroke();
129129

130130
// Three main nodes: Physical, Protocol, Intelligence
131131
const nodes = [
132-
{ name: 'PHYSICAL', color: '#00E599', desc: 'Ternary Hardware' },
133-
{ name: 'PROTOCOL', color: '#00E599', desc: 'Quantum Network' },
134-
{ name: 'INTELLIGENCE', color: '#00b377', desc: 'AI/ML Layer' }
132+
{ name: 'PHYSICAL', color: '#00FF88', desc: 'Ternary Hardware' },
133+
{ name: 'PROTOCOL', color: '#00FF88', desc: 'Quantum Network' },
134+
{ name: 'INTELLIGENCE', color: '#00CC66', desc: 'AI/ML Layer' }
135135
];
136136

137137
for (let i = 0; i < 3; i++) {
@@ -214,14 +214,14 @@ export default function QuantumCanvas({ mode, particleCount = 1500, interactive
214214
const x = cx + (outerRadius + wobble) * Math.cos(angle);
215215
const y = cy + (outerRadius + wobble) * Math.sin(angle);
216216

217-
ctx.fillStyle = ['#0e9', '#0b7', '#ff0'][i % 3];
217+
ctx.fillStyle = ['#0f8', '#0c6', '#ff0'][i % 3];
218218
ctx.beginPath();
219219
ctx.arc(x, y, 6 * scale, 0, TAU);
220220
ctx.fill();
221221

222222
// Connection lines to center
223223
if (i % 2 === 0) {
224-
ctx.strokeStyle = 'rgba(0, 229, 153, 0.1)';
224+
ctx.strokeStyle = 'rgba(0, 255, 136, 0.1)';
225225
ctx.beginPath();
226226
ctx.moveTo(x, y);
227227
ctx.lineTo(cx, cy);
@@ -237,17 +237,17 @@ export default function QuantumCanvas({ mode, particleCount = 1500, interactive
237237

238238
ctx.fillStyle = 'rgba(0, 255, 255, 0.1)';
239239
ctx.fillRect(boxX, boxY, boxW, boxH);
240-
ctx.strokeStyle = '#0e9';
240+
ctx.strokeStyle = '#0f8';
241241
ctx.lineWidth = 1;
242242
ctx.strokeRect(boxX, boxY, boxW, boxH);
243243

244-
ctx.fillStyle = '#0e9';
244+
ctx.fillStyle = '#0f8';
245245
ctx.font = `bold ${10 * scale}px monospace`;
246246
ctx.textAlign = 'center';
247247
ctx.fillText('PROTOCOL STACK', boxX + boxW / 2, boxY + 14 * scale);
248248

249249
const layers = ['Application', 'Transport', 'Network', 'Link', 'Physical'];
250-
const layerColors = ['#0b7', '#ff0', '#0f0', '#0e9', '#00E599'];
250+
const layerColors = ['#0c6', '#ff0', '#0f0', '#0f8', '#00FF88'];
251251
layers.forEach((layer, i) => {
252252
const ly = boxY + 22 * scale + i * 16 * scale;
253253
ctx.fillStyle = layerColors[i] + '40';
@@ -280,10 +280,10 @@ export default function QuantumCanvas({ mode, particleCount = 1500, interactive
280280
const invY = h / 2 - 60 * scale; // Upper middle right
281281
ctx.fillStyle = 'rgba(0, 255, 255, 0.1)';
282282
ctx.fillRect(invX, invY, boxW, 70 * scale);
283-
ctx.strokeStyle = '#0e9';
283+
ctx.strokeStyle = '#0f8';
284284
ctx.strokeRect(invX, invY, boxW, 70 * scale);
285285

286-
ctx.fillStyle = '#0e9';
286+
ctx.fillStyle = '#0f8';
287287
ctx.font = `bold ${10 * scale}px monospace`;
288288
ctx.textAlign = 'center';
289289
ctx.fillText('SSOT INVARIANTS', invX + boxW / 2, invY + 14 * scale);

website/src/components/SU3MiningRealitySection.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ export default function SU3MiningRealitySection() {
119119
maxWidth: '1200px',
120120
margin: '0 auto',
121121
background: 'rgba(10, 10, 10, 0.9)',
122-
border: '1px solid rgba(0, 229, 153, 0.2)',
122+
border: '1px solid rgba(0, 255, 136, 0.2)',
123123
borderRadius: '16px',
124124
padding: '1.2rem',
125125
position: 'relative',
126-
boxShadow: '0 0 40px rgba(0, 229, 153, 0.05)',
126+
boxShadow: '0 0 40px rgba(0, 255, 136, 0.05)',
127127
backdropFilter: 'blur(20px)',
128128
minHeight: '320px',
129129
display: 'flex',
@@ -182,7 +182,7 @@ export default function SU3MiningRealitySection() {
182182
style={{
183183
position: 'absolute',
184184
inset: '-15px',
185-
background: 'radial-gradient(circle, rgba(0, 229, 153, 0.25) 0%, transparent 75%)',
185+
background: 'radial-gradient(circle, rgba(0, 255, 136, 0.25) 0%, transparent 75%)',
186186
zIndex: 0
187187
}}
188188
/>
@@ -194,19 +194,19 @@ export default function SU3MiningRealitySection() {
194194
width: '100%',
195195
height: '100%',
196196
borderRadius: '50%',
197-
border: '2px double rgba(0, 229, 153, 0.4)',
197+
border: '2px double rgba(0, 255, 136, 0.4)',
198198
display: 'flex',
199199
flexDirection: 'column',
200200
justifyContent: 'center',
201201
alignItems: 'center',
202202
background: 'rgba(0,0,0,0.95)',
203203
zIndex: 1,
204204
position: 'relative',
205-
boxShadow: '0 0 30px rgba(0, 229, 153, 0.15)'
205+
boxShadow: '0 0 30px rgba(0, 255, 136, 0.15)'
206206
}}
207207
>
208208
<div style={{ fontSize: '0.5rem', fontWeight: '800', color: 'rgba(255,255,255,0.4)', letterSpacing: '0.15em', marginBottom: '0.4rem' }}>{reality.coreLabel}</div>
209-
<div style={{ fontSize: '3rem', fontWeight: '900', color: '#00E599', lineHeight: 1, filter: 'drop-shadow(0 0 15px rgba(0, 229, 153, 0.5))' }}>SU(3)</div>
209+
<div style={{ fontSize: '3rem', fontWeight: '900', color: '#00FF88', lineHeight: 1, filter: 'drop-shadow(0 0 15px rgba(0, 255, 136, 0.5))' }}>SU(3)</div>
210210
<div style={{ fontSize: '0.45rem', color: 'var(--accent)', marginTop: '0.8rem', opacity: 0.7, letterSpacing: '0.05em' }}>{reality.phaseLocked}</div>
211211
</motion.div>
212212
</div>
@@ -246,33 +246,33 @@ export default function SU3MiningRealitySection() {
246246
borderRadius: '12px',
247247
padding: '0.6rem',
248248
textAlign: 'center',
249-
background: 'rgba(0, 229, 153, 0.03)',
249+
background: 'rgba(0, 255, 136, 0.03)',
250250
display: 'flex',
251251
flexDirection: 'column',
252252
justifyContent: 'center'
253253
}}>
254254
<div style={{ fontSize: '0.5rem', color: 'rgba(255,255,255,0.4)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '0.2rem' }}>
255255
{reality.efficiency}
256256
</div>
257-
<div style={{ fontSize: '1.4rem', fontWeight: '800', color: '#00E599', lineHeight: 1 }}>
257+
<div style={{ fontSize: '1.4rem', fontWeight: '800', color: '#00FF88', lineHeight: 1 }}>
258258
{stats.efficiency.toFixed(1)}x
259259
</div>
260-
<div style={{ fontSize: '0.45rem', color: '#00E599', fontWeight: '700', marginTop: '0.3rem' }}>
260+
<div style={{ fontSize: '0.45rem', color: '#00FF88', fontWeight: '700', marginTop: '0.3rem' }}>
261261
{reality.active}
262262
</div>
263263
</div>
264264

265265
{/* Coptic Terminal (Instruction Bridge) */}
266266
<div style={{
267267
background: 'rgba(0,0,0,0.7)',
268-
border: '1px solid rgba(0, 229, 153, 0.15)',
268+
border: '1px solid rgba(0, 255, 136, 0.15)',
269269
borderRadius: '8px',
270270
padding: '0.5rem',
271271
position: 'relative',
272272
overflow: 'hidden',
273273
fontFamily: '"JetBrains Mono", monospace'
274274
}}>
275-
<div style={{ marginBottom: '0.3rem', color: '#00E599', fontWeight: '800', fontSize: '0.4rem', textTransform: 'uppercase', opacity: 0.5, letterSpacing: '0.1em' }}>
275+
<div style={{ marginBottom: '0.3rem', color: '#00FF88', fontWeight: '800', fontSize: '0.4rem', textTransform: 'uppercase', opacity: 0.5, letterSpacing: '0.1em' }}>
276276
{reality.terminalTitle}
277277
</div>
278278
<div
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
"use client";
2+
import { motion } from 'framer-motion';
3+
import { useMemo } from 'react';
4+
import { getConnections, getNodeById, techBranches, type Connection } from './techTreeData';
5+
6+
interface TechConnectionsProps {
7+
nodeWidth: number;
8+
nodeHeight: number;
9+
gapX: number;
10+
gapY: number;
11+
offsetX: number;
12+
offsetY: number;
13+
}
14+
15+
export default function TechConnections({
16+
nodeWidth,
17+
nodeHeight,
18+
gapX,
19+
gapY,
20+
offsetX,
21+
offsetY
22+
}: TechConnectionsProps) {
23+
const connections = useMemo(() => getConnections(), []);
24+
25+
const getNodePosition = (nodeId: string) => {
26+
const node = getNodeById(nodeId);
27+
if (!node) return null;
28+
29+
const x = offsetX + node.x * (nodeWidth + gapX) + nodeWidth / 2;
30+
const y = offsetY + node.y * (nodeHeight + gapY) + nodeHeight / 2;
31+
32+
return { x, y };
33+
};
34+
35+
const getNodeColor = (nodeId: string) => {
36+
const node = getNodeById(nodeId);
37+
if (!node) return '#00FF88';
38+
const branch = techBranches.find(b => b.id === node.branch);
39+
return branch?.color || '#00FF88';
40+
};
41+
42+
const renderConnection = (conn: Connection, index: number) => {
43+
const from = getNodePosition(conn.from);
44+
const to = getNodePosition(conn.to);
45+
46+
if (!from || !to) return null;
47+
48+
const isActive = conn.status === 'active';
49+
const color = isActive ? getNodeColor(conn.from) : 'rgba(255, 255, 255, 0.15)';
50+
51+
// Calculate control points for curved lines
52+
const dx = to.x - from.x;
53+
const dy = to.y - from.y;
54+
55+
// Create smooth bezier curve
56+
const midX = from.x + dx / 2;
57+
const midY = from.y + dy / 2;
58+
59+
// Curve more for diagonal connections
60+
const curveOffset = Math.abs(dy) > 20 ? dx * 0.3 : 0;
61+
62+
const path = `M ${from.x} ${from.y} Q ${midX + curveOffset} ${from.y} ${midX} ${midY} Q ${midX + curveOffset} ${to.y} ${to.x} ${to.y}`;
63+
64+
return (
65+
<g key={`${conn.from}-${conn.to}-${index}`}>
66+
{/* Background glow for active connections */}
67+
{isActive && (
68+
<motion.path
69+
d={path}
70+
fill="none"
71+
stroke={color}
72+
strokeWidth="4"
73+
strokeOpacity="0.2"
74+
initial={{ pathLength: 0 }}
75+
animate={{ pathLength: 1 }}
76+
transition={{ duration: 1, delay: index * 0.1 }}
77+
/>
78+
)}
79+
80+
{/* Main line */}
81+
<motion.path
82+
d={path}
83+
fill="none"
84+
stroke={color}
85+
strokeWidth="2"
86+
strokeDasharray={isActive ? "none" : "5 5"}
87+
initial={{ pathLength: 0 }}
88+
animate={{ pathLength: 1 }}
89+
transition={{ duration: 0.8, delay: index * 0.1 }}
90+
/>
91+
92+
{/* Animated flow particles for active connections */}
93+
{isActive && (
94+
<motion.circle
95+
r="3"
96+
fill={color}
97+
filter="url(#glow)"
98+
initial={{ offsetDistance: '0%' }}
99+
animate={{ offsetDistance: '100%' }}
100+
transition={{
101+
duration: 2,
102+
repeat: Infinity,
103+
ease: 'linear',
104+
delay: index * 0.3
105+
}}
106+
style={{
107+
offsetPath: `path('${path}')`,
108+
}}
109+
/>
110+
)}
111+
112+
{/* Arrow at end */}
113+
<motion.circle
114+
cx={to.x}
115+
cy={to.y}
116+
r="4"
117+
fill={isActive ? color : 'rgba(255, 255, 255, 0.2)'}
118+
initial={{ scale: 0 }}
119+
animate={{ scale: 1 }}
120+
transition={{ duration: 0.3, delay: index * 0.1 + 0.5 }}
121+
/>
122+
</g>
123+
);
124+
};
125+
126+
return (
127+
<svg
128+
style={{
129+
position: 'absolute',
130+
top: 0,
131+
left: 0,
132+
width: '100%',
133+
height: '100%',
134+
pointerEvents: 'none',
135+
zIndex: 0
136+
}}
137+
>
138+
<defs>
139+
{/* Glow filter */}
140+
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
141+
<feGaussianBlur stdDeviation="2" result="coloredBlur" />
142+
<feMerge>
143+
<feMergeNode in="coloredBlur" />
144+
<feMergeNode in="SourceGraphic" />
145+
</feMerge>
146+
</filter>
147+
148+
{/* Gradient for active lines */}
149+
<linearGradient id="activeGradient" x1="0%" y1="0%" x2="100%" y2="0%">
150+
<stop offset="0%" stopColor="#00FF88" />
151+
<stop offset="100%" stopColor="#FFD700" />
152+
</linearGradient>
153+
</defs>
154+
155+
{connections.map((conn, i) => renderConnection(conn, i))}
156+
</svg>
157+
);
158+
}

0 commit comments

Comments
 (0)