Rework ecosystem section: CoFi prominence, Psilo-Cyber ICS, footer cleanup
- Replace Defect.fi with CoFi card, remove NoFi card from Economic Ecosystems - Highlight CoFi in finance progression line - Remove Mycopunk from Culture & Infrastructure grid - Add Institutional Neuroplasticity subsection (Psilo-Cyber ICS) - Clean up network map: remove Defect.fi/Mycopunk nodes, add CoFi node - Footer: remove link bar, change tagline to "Made by the mycopunks" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3bbd40a73b
commit
0a89dc0c2b
|
|
@ -8,7 +8,6 @@ import { UndernetSection } from "@/components/undernet-section"
|
|||
import { AnastomosisSection } from "@/components/anastomosis-section"
|
||||
import { NoFiSection } from "@/components/nofi-section"
|
||||
import { EmergenceSection } from "@/components/emergence-section"
|
||||
import { NetworkMapSection } from "@/components/network-map-section"
|
||||
import { Footer } from "@/components/footer"
|
||||
|
||||
export default function Home() {
|
||||
|
|
@ -25,7 +24,6 @@ export default function Home() {
|
|||
<AnastomosisSection />
|
||||
<NoFiSection />
|
||||
<EmergenceSection />
|
||||
<NetworkMapSection />
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
id: TASK-9
|
||||
title: 'Add NoFi section, fix undernet readability, allied orgs'
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-02-26 03:23'
|
||||
labels:
|
||||
- mycostack-website
|
||||
- content
|
||||
- visual
|
||||
- performance
|
||||
dependencies: []
|
||||
priority: high
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
**NoFi Section (nofi.lol):**
|
||||
Post-finance statement — TradFi→DeFi→ReFi→NoFi progression. The point was never to make money, it was to make change. Building systems where financial scaffolding can be composted.
|
||||
|
||||
**Undernet Readability Fix:**
|
||||
Eliminated the jarring brightening effect. Background stays dark (L≤0.20) with light text through Undernet, Anastomosis, and NoFi sections. Only brightens gradually at Emergence (L=0.55) and Network Map (L=0.88).
|
||||
|
||||
**Faster Section Reveals:**
|
||||
- Threshold: 0.15→0.05 (triggers earlier)
|
||||
- rootMargin: -50px→-20px (triggers sooner)
|
||||
- translateY: 40px→24px (subtler slide)
|
||||
- Duration: 0.9s→0.6s (snappier)
|
||||
|
||||
**Allied Organizations:**
|
||||
Network map and footer now include Giveth, Token Engineering Commons, Enspiral, and Grassroots Economics as "building alongside" allies with connections.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [ ] #1 NoFi section with post-finance content and nofi.lol link
|
||||
- [ ] #2 Undernet section stays dark and readable throughout scroll
|
||||
- [ ] #3 Section reveals trigger faster and animate quicker
|
||||
- [ ] #4 Allied organizations appear in network map with connections
|
||||
- [ ] #5 Footer includes NoFi and building alongside section
|
||||
- [ ] #6 Build passes with no errors
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
All changes implemented. Committed a8f0bb4, pushed to dev and merged to main on Gitea. 8 files changed, 301 insertions, 35 deletions.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
|
@ -30,8 +30,8 @@ export function AnastomosisSection() {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-16">
|
||||
<div className="section-reveal space-y-6 text-center">
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export function CompostSection() {
|
|||
const sectionRef = useSectionReveal()
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-5xl mx-auto space-y-16">
|
||||
<div className="section-reveal space-y-4 text-center">
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export function EmergenceSection() {
|
|||
const sectionRef = useSectionReveal()
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-5xl mx-auto space-y-16">
|
||||
<div className="section-reveal space-y-6 text-center">
|
||||
|
|
|
|||
|
|
@ -1,45 +1,13 @@
|
|||
"use client"
|
||||
|
||||
const LINKS = [
|
||||
{ name: "Commons Stack", url: "https://commonsstack.org" },
|
||||
{ name: "P2P Foundation", url: "https://wiki.p2pfoundation.net/" },
|
||||
{ name: "MycoFi", url: "https://mycofi.earth" },
|
||||
{ name: "NoFi", url: "https://nofi.lol" },
|
||||
{ name: "Defect.fi", url: "https://defect.fi" },
|
||||
{ name: "Mycopunk", url: "https://mycopunk.xyz" },
|
||||
{ name: "rFunds", url: "https://rfunds.online" },
|
||||
{ name: "rStack", url: "https://rstack.org" },
|
||||
{ name: "rSpace", url: "https://yourspace.online" },
|
||||
{ name: "Undernet", url: "https://undernet.earth" },
|
||||
{ name: "Psilo-Cyber", url: "https://psilo-cyber.net" },
|
||||
{ name: "Compost Capitalism", url: "https://compostcapitalism.xyz" },
|
||||
{ name: "Post-Appitalism", url: "https://post-appitalist.app" },
|
||||
{ name: "Trippin Balls", url: "https://trippinballs.lol" },
|
||||
]
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className="relative z-10 py-20 px-6 border-t border-current/10">
|
||||
<div className="max-w-4xl mx-auto space-y-10">
|
||||
{/* Network links */}
|
||||
<div className="flex flex-wrap justify-center gap-x-6 gap-y-2">
|
||||
{LINKS.map((link) => (
|
||||
<a
|
||||
key={link.url}
|
||||
href={link.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-mono text-xs opacity-40 hover:opacity-70 transition-opacity"
|
||||
>
|
||||
{link.name}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tagline */}
|
||||
<div className="text-center space-y-3">
|
||||
<p className="font-serif text-lg opacity-65">
|
||||
Built with compost and code.
|
||||
Made by the mycopunks.
|
||||
</p>
|
||||
<p className="font-mono text-xs opacity-45">
|
||||
MycoStack — technology-augmented commons growing from beneath
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ export function GoodsMatrixSection() {
|
|||
const sectionRef = useSectionReveal()
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-16">
|
||||
<div className="section-reveal space-y-4 text-center">
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ export function LegacySection() {
|
|||
const sectionRef = useSectionReveal()
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-16">
|
||||
{/* Header */}
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ export function MyceliumSection() {
|
|||
const sectionRef = useSectionReveal()
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-20">
|
||||
<div className="section-reveal space-y-4 text-center">
|
||||
|
|
|
|||
|
|
@ -179,8 +179,8 @@ export function NetworkMapSection() {
|
|||
}
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-5xl mx-auto space-y-16">
|
||||
<div className="section-reveal space-y-4 text-center">
|
||||
|
|
|
|||
|
|
@ -1,15 +1,179 @@
|
|||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { useSectionReveal } from "@/hooks/use-section-reveal"
|
||||
import { ExternalLink } from "lucide-react"
|
||||
|
||||
interface NetworkNode {
|
||||
name: string
|
||||
domain: string
|
||||
description: string
|
||||
x: number
|
||||
y: number
|
||||
primary?: boolean
|
||||
}
|
||||
|
||||
const NODES: NetworkNode[] = [
|
||||
{
|
||||
name: "MycoStack",
|
||||
domain: "mycostack.xyz",
|
||||
description: "Technology-augmented commons",
|
||||
x: 50,
|
||||
y: 45,
|
||||
primary: true,
|
||||
},
|
||||
{
|
||||
name: "Commons Stack",
|
||||
domain: "commonsstack.org",
|
||||
description: "Fund and govern the commons — primary root",
|
||||
x: 50,
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
name: "P2P Foundation",
|
||||
domain: "wiki.p2pfoundation.net",
|
||||
description: "25,000 pages of commons knowledge",
|
||||
x: 50,
|
||||
y: 95,
|
||||
},
|
||||
{
|
||||
name: "MycoFi",
|
||||
domain: "mycofi.earth",
|
||||
description: "Mycoeconomics & regenerative currencies",
|
||||
x: 20,
|
||||
y: 18,
|
||||
},
|
||||
{
|
||||
name: "CoFi",
|
||||
domain: "cofi.earth",
|
||||
description: "Community finance — coordinating shared resources",
|
||||
x: 80,
|
||||
y: 18,
|
||||
},
|
||||
{
|
||||
name: "NoFi",
|
||||
domain: "nofi.lol",
|
||||
description: "Post-finance — beyond the need for money",
|
||||
x: 92,
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
name: "rFunds",
|
||||
domain: "rfunds.online",
|
||||
description: "Threshold-Based Flow Funding research",
|
||||
x: 15,
|
||||
y: 30,
|
||||
},
|
||||
{
|
||||
name: "rStack",
|
||||
domain: "rstack.org",
|
||||
description: "Open source community coordination infrastructure",
|
||||
x: 78,
|
||||
y: 55,
|
||||
},
|
||||
{
|
||||
name: "Compost Capitalism",
|
||||
domain: "compostcapitalism.xyz",
|
||||
description: "Decomposing extractive systems",
|
||||
x: 12,
|
||||
y: 55,
|
||||
},
|
||||
{
|
||||
name: "The Undernet",
|
||||
domain: "undernet.earth",
|
||||
description: "Community-owned infrastructure",
|
||||
x: 88,
|
||||
y: 35,
|
||||
},
|
||||
{
|
||||
name: "Post-Appitalism",
|
||||
domain: "post-appitalist.app",
|
||||
description: "Tools beyond extractive platforms",
|
||||
x: 15,
|
||||
y: 78,
|
||||
},
|
||||
{
|
||||
name: "rSpace",
|
||||
domain: "yourspace.online",
|
||||
description: "Community-owned digital spaces",
|
||||
x: 65,
|
||||
y: 78,
|
||||
},
|
||||
{
|
||||
name: "Psilo-Cyber",
|
||||
domain: "psilo-cyber.net",
|
||||
description: "Institutional neuroplasticity & adaptive systems",
|
||||
x: 88,
|
||||
y: 70,
|
||||
},
|
||||
{
|
||||
name: "Trippin Balls",
|
||||
domain: "trippinballs.lol",
|
||||
description: "Expand your perspective",
|
||||
x: 38,
|
||||
y: 92,
|
||||
},
|
||||
]
|
||||
|
||||
const CONNECTIONS: [string, string][] = [
|
||||
["mycostack.xyz", "commonsstack.org"],
|
||||
["mycostack.xyz", "wiki.p2pfoundation.net"],
|
||||
["mycostack.xyz", "mycofi.earth"],
|
||||
["mycostack.xyz", "undernet.earth"],
|
||||
["mycostack.xyz", "compostcapitalism.xyz"],
|
||||
["mycostack.xyz", "yourspace.online"],
|
||||
["mycostack.xyz", "rstack.org"],
|
||||
["mycostack.xyz", "cofi.earth"],
|
||||
["commonsstack.org", "wiki.p2pfoundation.net"],
|
||||
["commonsstack.org", "mycofi.earth"],
|
||||
["commonsstack.org", "rfunds.online"],
|
||||
["commonsstack.org", "cofi.earth"],
|
||||
["rfunds.online", "mycofi.earth"],
|
||||
["cofi.earth", "mycofi.earth"],
|
||||
["cofi.earth", "nofi.lol"],
|
||||
["nofi.lol", "mycofi.earth"],
|
||||
["rstack.org", "yourspace.online"],
|
||||
["rstack.org", "undernet.earth"],
|
||||
["wiki.p2pfoundation.net", "post-appitalist.app"],
|
||||
["undernet.earth", "psilo-cyber.net"],
|
||||
["compostcapitalism.xyz", "post-appitalist.app"],
|
||||
["post-appitalist.app", "yourspace.online"],
|
||||
["yourspace.online", "trippinballs.lol"],
|
||||
["psilo-cyber.net", "rstack.org"],
|
||||
]
|
||||
|
||||
function getNode(domain: string) {
|
||||
return NODES.find((n) => n.domain === domain)
|
||||
}
|
||||
|
||||
export function NoFiSection() {
|
||||
const sectionRef = useSectionReveal()
|
||||
const [hovered, setHovered] = useState<string | null>(null)
|
||||
|
||||
const isConnected = (domain: string) => {
|
||||
if (!hovered) return false
|
||||
return CONNECTIONS.some(
|
||||
([a, b]) =>
|
||||
(a === hovered && b === domain) || (b === hovered && a === domain)
|
||||
)
|
||||
}
|
||||
|
||||
const getLineOpacity = (a: string, b: string) => {
|
||||
if (!hovered) return 0.15
|
||||
if (
|
||||
(a === hovered || b === hovered) &&
|
||||
(isConnected(a) || isConnected(b) || a === hovered || b === hovered)
|
||||
)
|
||||
return 0.5
|
||||
return 0.06
|
||||
}
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay" style={{ background: "oklch(0.14 0.02 140 / 0.9)" }}>
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-16">
|
||||
<div className="max-w-5xl mx-auto space-y-14">
|
||||
{/* Ecosystem header */}
|
||||
<div className="section-reveal space-y-6 text-center">
|
||||
<h2 className="font-serif text-4xl sm:text-5xl md:text-6xl font-bold">
|
||||
The Ecosystem
|
||||
|
|
@ -72,7 +236,7 @@ export function NoFiSection() {
|
|||
<h3 className="font-serif text-xl font-semibold opacity-70 text-center">
|
||||
Economic Ecosystems
|
||||
</h3>
|
||||
<div className="grid gap-6 sm:grid-cols-3 max-w-3xl mx-auto">
|
||||
<div className="grid gap-6 sm:grid-cols-2 max-w-3xl mx-auto">
|
||||
<div className="glass-card p-5 space-y-3">
|
||||
<h4 className="font-serif text-lg font-semibold">
|
||||
<a
|
||||
|
|
@ -94,44 +258,27 @@ export function NoFiSection() {
|
|||
<div className="glass-card p-5 space-y-3">
|
||||
<h4 className="font-serif text-lg font-semibold">
|
||||
<a
|
||||
href="https://nofi.lol"
|
||||
href="https://cofi.earth"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="domain-link"
|
||||
>
|
||||
NoFi
|
||||
CoFi
|
||||
</a>
|
||||
</h4>
|
||||
<p className="text-sm leading-relaxed opacity-80">
|
||||
Post-finance. What if coordination becomes so dense that the
|
||||
financial scaffolding can be composted? Not anti-money —
|
||||
beyond the need for it.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="glass-card p-5 space-y-3">
|
||||
<h4 className="font-serif text-lg font-semibold">
|
||||
<a
|
||||
href="https://defect.fi"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="domain-link"
|
||||
>
|
||||
Defect.fi
|
||||
</a>
|
||||
</h4>
|
||||
<p className="text-sm leading-relaxed opacity-80">
|
||||
Defecting from extractive finance. The conscious choice to
|
||||
withdraw from systems that concentrate wealth and build
|
||||
alternatives that distribute it.
|
||||
Community finance — the practical layer where communities
|
||||
coordinate shared resources. The bridge between ReFi’s
|
||||
ideals and MycoFi’s living systems. Cooperative finance
|
||||
for the commons.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="glass-card p-3 space-y-1 font-mono text-xs text-center max-w-sm mx-auto">
|
||||
<div className="opacity-50">TradFi → DeFi → ReFi → CoFi → MycoFi →</div>
|
||||
<div style={{ color: "var(--scroll-accent)" }}>NoFi</div>
|
||||
<div className="opacity-50">Transcend the need for it.</div>
|
||||
<div className="opacity-50">TradFi → DeFi → ReFi →</div>
|
||||
<div style={{ color: "var(--scroll-accent)" }}>CoFi</div>
|
||||
<div className="opacity-50">→ MycoFi → NoFi</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -140,7 +287,7 @@ export function NoFiSection() {
|
|||
<h3 className="font-serif text-xl font-semibold opacity-70 text-center">
|
||||
Culture & Infrastructure
|
||||
</h3>
|
||||
<div className="grid gap-6 sm:grid-cols-3 max-w-3xl mx-auto">
|
||||
<div className="grid gap-6 sm:grid-cols-2 max-w-3xl mx-auto">
|
||||
<div className="glass-card p-5 space-y-3">
|
||||
<h4 className="font-serif text-lg font-semibold">
|
||||
<a
|
||||
|
|
@ -159,24 +306,6 @@ export function NoFiSection() {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div className="glass-card p-5 space-y-3">
|
||||
<h4 className="font-serif text-lg font-semibold">
|
||||
<a
|
||||
href="https://mycopunk.xyz"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="domain-link"
|
||||
>
|
||||
Mycopunk
|
||||
</a>
|
||||
</h4>
|
||||
<p className="text-sm leading-relaxed opacity-80">
|
||||
Building from beneath the surface. A cultural and philosophical
|
||||
movement that draws on fungi as a model for decentralized,
|
||||
resilient, regenerative systems.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="glass-card p-5 space-y-3">
|
||||
<h4 className="font-serif text-lg font-semibold">
|
||||
<a
|
||||
|
|
@ -197,12 +326,155 @@ export function NoFiSection() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Institutional Neuroplasticity */}
|
||||
<div className="section-reveal space-y-4" style={{ transitionDelay: "0.3s" }}>
|
||||
<h3 className="font-serif text-xl font-semibold opacity-70 text-center">
|
||||
<a
|
||||
href="https://psilo-cyber.net/ics"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="domain-link"
|
||||
>
|
||||
Institutional Neuroplasticity
|
||||
</a>
|
||||
</h3>
|
||||
<div className="glass-card p-6 space-y-5 max-w-3xl mx-auto">
|
||||
<p className="text-sm leading-relaxed opacity-85">
|
||||
The MycoStack doesn’t just build new institutions — it
|
||||
makes institutions capable of continuous adaptation. Structures
|
||||
that rewire themselves in response to changing conditions.
|
||||
Governance that evolves through use. Protocols that strengthen the
|
||||
pathways that work and prune those that don’t.
|
||||
</p>
|
||||
<div className="border-t border-current/10 pt-4 space-y-2">
|
||||
<h4 className="font-serif text-base font-semibold opacity-90">
|
||||
Dynamic Adaptivity
|
||||
</h4>
|
||||
<p className="text-sm leading-relaxed opacity-80">
|
||||
Rigid institutions fail because they can’t adapt. The
|
||||
MycoStack enables dynamic adaptivity — institutions that
|
||||
sense, respond, and reorganize like living systems. Not static
|
||||
bureaucracies but adaptive organisms.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<blockquote className="section-reveal max-w-2xl mx-auto text-center">
|
||||
<p className="font-serif text-xl sm:text-2xl italic leading-relaxed opacity-80">
|
||||
“None of us are as resilient as all of us. The ecosystem
|
||||
is the unit of survival.”
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
{/* Network Map */}
|
||||
<div className="mycelial-divider" />
|
||||
|
||||
<div className="section-reveal space-y-4 text-center">
|
||||
<h2 className="font-serif text-4xl sm:text-5xl md:text-6xl font-bold">
|
||||
The Network of Networks
|
||||
</h2>
|
||||
<p className="text-lg sm:text-xl opacity-85 max-w-2xl mx-auto">
|
||||
Every node strengthens the whole. Every connection multiplies
|
||||
possibility.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Desktop: SVG network map */}
|
||||
<div className="section-reveal hidden md:block">
|
||||
<div className="relative" style={{ paddingBottom: "60%" }}>
|
||||
<svg
|
||||
viewBox="0 0 1000 600"
|
||||
className="absolute inset-0 w-full h-full"
|
||||
fill="none"
|
||||
>
|
||||
{/* Connection lines */}
|
||||
{CONNECTIONS.map(([a, b]) => {
|
||||
const nodeA = getNode(a)
|
||||
const nodeB = getNode(b)
|
||||
if (!nodeA || !nodeB) return null
|
||||
return (
|
||||
<line
|
||||
key={`${a}-${b}`}
|
||||
x1={nodeA.x * 10}
|
||||
y1={nodeA.y * 6}
|
||||
x2={nodeB.x * 10}
|
||||
y2={nodeB.y * 6}
|
||||
stroke="var(--scroll-accent)"
|
||||
strokeWidth="1"
|
||||
opacity={getLineOpacity(a, b)}
|
||||
style={{ transition: "opacity 0.3s ease" }}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</svg>
|
||||
|
||||
{/* Node cards */}
|
||||
{NODES.map((node) => {
|
||||
const isActive = hovered === node.domain
|
||||
const connected = isConnected(node.domain)
|
||||
const dimmed = hovered && !isActive && !connected
|
||||
|
||||
return (
|
||||
<a
|
||||
key={node.domain}
|
||||
href={`https://${node.domain}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="network-node absolute -translate-x-1/2 -translate-y-1/2"
|
||||
style={{
|
||||
left: `${node.x}%`,
|
||||
top: `${node.y}%`,
|
||||
opacity: dimmed ? 0.3 : 1,
|
||||
transition: "opacity 0.3s ease, transform 0.3s ease, filter 0.3s ease",
|
||||
}}
|
||||
onMouseEnter={() => setHovered(node.domain)}
|
||||
onMouseLeave={() => setHovered(null)}
|
||||
>
|
||||
<div
|
||||
className={`glass-card px-4 py-3 text-center space-y-1 ${
|
||||
node.primary ? "ring-1 ring-current/20" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="font-serif text-sm font-semibold whitespace-nowrap">
|
||||
{node.name}
|
||||
</div>
|
||||
<div className="font-mono text-xs opacity-50 whitespace-nowrap flex items-center gap-1 justify-center">
|
||||
{node.domain}
|
||||
<ExternalLink className="w-2.5 h-2.5" />
|
||||
</div>
|
||||
{isActive && (
|
||||
<div className="text-xs opacity-60 max-w-[160px]">
|
||||
{node.description}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile: Simple card list */}
|
||||
<div className="section-reveal md:hidden grid gap-3 grid-cols-1 sm:grid-cols-2">
|
||||
{NODES.map((node, i) => (
|
||||
<a
|
||||
key={node.domain}
|
||||
href={`https://${node.domain}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="glass-card p-4 space-y-1 hover:opacity-80 transition-opacity"
|
||||
style={{ transitionDelay: `${i * 0.05}s` }}
|
||||
>
|
||||
<div className="font-serif text-base font-semibold flex items-center gap-2">
|
||||
{node.name}
|
||||
<ExternalLink className="w-3 h-3 opacity-40" />
|
||||
</div>
|
||||
<div className="font-mono text-xs opacity-40">{node.domain}</div>
|
||||
<div className="text-xs opacity-60">{node.description}</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ export function UndernetSection() {
|
|||
const sectionRef = useSectionReveal()
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="relative py-32 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-20" />
|
||||
<section ref={sectionRef} className="relative py-20 px-6 noise-overlay">
|
||||
<div className="mycelial-divider mb-12" />
|
||||
|
||||
<div className="max-w-5xl mx-auto space-y-16">
|
||||
<div className="section-reveal space-y-4 text-center">
|
||||
|
|
|
|||
Loading…
Reference in New Issue