Initial commit
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# React + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||||
|
|
||||||
|
## React Compiler
|
||||||
|
|
||||||
|
The React Compiler is not enabled on this template. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
||||||
|
|
||||||
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
|
29
eslint.config.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{js,jsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
reactHooks.configs['recommended-latest'],
|
||||||
|
reactRefresh.configs.vite,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
ecmaFeatures: { jsx: true },
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>mycelium-society</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.jsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
2940
package-lock.json
generated
Normal file
32
package.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "mycelium-society",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.23.22",
|
||||||
|
"react": "^19.1.1",
|
||||||
|
"react-dom": "^19.1.1",
|
||||||
|
"tailwind-merge": "^3.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.36.0",
|
||||||
|
"@types/react": "^19.1.13",
|
||||||
|
"@types/react-dom": "^19.1.9",
|
||||||
|
"@vitejs/plugin-react": "^5.0.3",
|
||||||
|
"eslint": "^9.36.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
|
"globals": "^16.4.0",
|
||||||
|
"vite": "^7.1.7"
|
||||||
|
}
|
||||||
|
}
|
1
public/vite.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
20
src/App.jsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import Hero from './components/Hero';
|
||||||
|
import Manifesto from './components/Manifesto';
|
||||||
|
import CorePillars from './components/CorePillars';
|
||||||
|
import Foundations from './components/Foundations';
|
||||||
|
import ForYou from './components/ForYou';
|
||||||
|
import CallToAction from './components/CallToAction';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
<Hero />
|
||||||
|
<Manifesto />
|
||||||
|
<Foundations />
|
||||||
|
<ForYou />
|
||||||
|
<CallToAction />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
BIN
src/assets/builder.png
Normal file
After Width: | Height: | Size: 725 KiB |
BIN
src/assets/collective copy.png
Normal file
After Width: | Height: | Size: 262 KiB |
BIN
src/assets/collective.png
Normal file
After Width: | Height: | Size: 262 KiB |
BIN
src/assets/community.png
Normal file
After Width: | Height: | Size: 712 KiB |
BIN
src/assets/creator.png
Normal file
After Width: | Height: | Size: 543 KiB |
BIN
src/assets/developer.png
Normal file
After Width: | Height: | Size: 545 KiB |
BIN
src/assets/joinus.png
Normal file
After Width: | Height: | Size: 199 KiB |
BIN
src/assets/legal.png
Normal file
After Width: | Height: | Size: 261 KiB |
BIN
src/assets/manifest.png
Normal file
After Width: | Height: | Size: 220 KiB |
BIN
src/assets/mushroom.png
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
src/assets/nomad.png
Normal file
After Width: | Height: | Size: 585 KiB |
BIN
src/assets/privacy_advocate.png
Normal file
After Width: | Height: | Size: 642 KiB |
1
src/assets/react.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/sovereign.png
Normal file
After Width: | Height: | Size: 278 KiB |
98
src/components/CallToAction.jsx
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { useState, useRef } from 'react';
|
||||||
|
import { motion, useInView } from 'framer-motion';
|
||||||
|
import joinusImg from '../assets/joinus.png';
|
||||||
|
import SocietyTerminal from './SocietyTerminal';
|
||||||
|
|
||||||
|
const CallToAction = () => {
|
||||||
|
const [showTerminal, setShowTerminal] = useState(false);
|
||||||
|
const ref = useRef(null);
|
||||||
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
|
|
||||||
|
const fadeInUp = {
|
||||||
|
hidden: { opacity: 0, y: 50 },
|
||||||
|
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const bounceIn = {
|
||||||
|
hidden: { scale: 0, opacity: 0 },
|
||||||
|
visible: { scale: 1, opacity: 1, transition: { type: "spring", bounce: 0.4, duration: 0.8 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const staggerContainer = {
|
||||||
|
visible: { transition: { staggerChildren: 0.3 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section ref={ref} className="section-padding bg-dark-gradient">
|
||||||
|
<motion.div
|
||||||
|
className="container-width text-center"
|
||||||
|
initial="hidden"
|
||||||
|
animate={isInView ? "visible" : "hidden"}
|
||||||
|
variants={staggerContainer}
|
||||||
|
>
|
||||||
|
{/* Mascot */}
|
||||||
|
<motion.div
|
||||||
|
className="mb-8"
|
||||||
|
variants={bounceIn}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={joinusImg}
|
||||||
|
alt="Mycelium Society Mascot"
|
||||||
|
className="w-48 h-48 mx-auto rounded-full bg-gradient-to-br from-bright-cyan/20 to-cyan/20 p-4"
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Heading */}
|
||||||
|
<motion.h2
|
||||||
|
className="text-4xl md:text-5xl font-bold text-white mb-8"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
Join as a Founding Member
|
||||||
|
</motion.h2>
|
||||||
|
|
||||||
|
{/* Body Text */}
|
||||||
|
<motion.p
|
||||||
|
className="text-lg md:text-xl text-gray-300 leading-relaxed max-w-3xl mx-auto mb-12"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
This is early days. Every founding member shapes what Mycelium Society becomes. We're shaping the future of digital sovereignty, together. Your participation matters. Your needs drive development. Your voice decides what we build next.
|
||||||
|
</motion.p>
|
||||||
|
|
||||||
|
{/* CTA Button */}
|
||||||
|
<motion.div variants={fadeInUp}>
|
||||||
|
<motion.button
|
||||||
|
className="btn-primary animate-pulse-glow text-lg px-8 py-4"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
onClick={() => setShowTerminal(true)}
|
||||||
|
animate={{
|
||||||
|
boxShadow: [
|
||||||
|
"0 0 5px #00d9ff",
|
||||||
|
"0 0 20px #00d9ff, 0 0 30px #00d9ff",
|
||||||
|
"0 0 5px #00d9ff"
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
boxShadow: {
|
||||||
|
duration: 2,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
> Enter the Network
|
||||||
|
</motion.button>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{showTerminal && (
|
||||||
|
<SocietyTerminal
|
||||||
|
showTerminal={showTerminal}
|
||||||
|
setShowTerminal={setShowTerminal}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CallToAction;
|
69
src/components/CorePillars.jsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { useInView } from 'framer-motion';
|
||||||
|
import { useRef } from 'react';
|
||||||
|
|
||||||
|
const CorePillars = () => {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
|
|
||||||
|
const slideInLeft = {
|
||||||
|
hidden: { opacity: 0, x: -50 },
|
||||||
|
visible: { opacity: 1, x: 0, transition: { duration: 0.6 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const staggerContainer = {
|
||||||
|
visible: { transition: { staggerChildren: 0.3 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const pillars = [
|
||||||
|
{
|
||||||
|
title: "Sovereign Infrastructure",
|
||||||
|
content: "We've already built the foundation: a decentralized cloud, peer-to-peer networking protocols, and a legally recognized digital free zone. Your infrastructure runs on systems you control, based on networks that can't be shut down."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Collective Direction",
|
||||||
|
content: "Members use on-chain unmediated services to replace rent. Every layer matters. Every voice shapes our development roadmap. The tools you need become the tools we build."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Legal Framework",
|
||||||
|
content: "This town isn't in a suitcase jurisdiction! We're a legally recognized legal framework. This isn't legal grey area. It's compliant, legitimate, and protected. Every service we build protects your sovereignty and helps individuals and firms handle compliance, manage taxation, all through integrated systems designed for digital sovereignty."
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section ref={ref} className="section-padding bg-dark-gradient">
|
||||||
|
<motion.div
|
||||||
|
className="container-width"
|
||||||
|
initial="hidden"
|
||||||
|
animate={isInView ? "visible" : "hidden"}
|
||||||
|
variants={staggerContainer}
|
||||||
|
>
|
||||||
|
<motion.h2
|
||||||
|
className="text-4xl md:text-5xl font-bold text-white mb-16 text-center"
|
||||||
|
variants={slideInLeft}
|
||||||
|
>
|
||||||
|
Core Pillars
|
||||||
|
</motion.h2>
|
||||||
|
|
||||||
|
<div className="space-y-12">
|
||||||
|
{pillars.map((pillar, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
className="border-l-2 border-bright-cyan pl-6 py-4"
|
||||||
|
variants={slideInLeft}
|
||||||
|
>
|
||||||
|
<h3 className="text-2xl md:text-3xl font-bold text-white mb-4">
|
||||||
|
{pillar.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-lg text-gray-300 leading-relaxed">
|
||||||
|
{pillar.content}
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CorePillars;
|
53
src/components/ForYou.jsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { useInView } from 'framer-motion';
|
||||||
|
import { useRef } from 'react';
|
||||||
|
import ScrollingCards from './ScrollingCards';
|
||||||
|
|
||||||
|
const ForYou = () => {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
|
|
||||||
|
const fadeInUp = {
|
||||||
|
hidden: { opacity: 0, y: 50 },
|
||||||
|
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const staggerContainer = {
|
||||||
|
visible: { transition: { staggerChildren: 0.3 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section ref={ref} className="section-padding bg-dark-gradient">
|
||||||
|
<motion.div
|
||||||
|
className="w-full"
|
||||||
|
initial="hidden"
|
||||||
|
animate={isInView ? "visible" : "hidden"}
|
||||||
|
variants={staggerContainer}
|
||||||
|
>
|
||||||
|
{/* Section Header */}
|
||||||
|
<div className="container-width text-center mb-16">
|
||||||
|
<motion.h2
|
||||||
|
className="text-4xl md:text-5xl font-bold text-white mb-8"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
For You
|
||||||
|
</motion.h2>
|
||||||
|
|
||||||
|
<motion.p
|
||||||
|
className="text-lg md:text-xl text-gray-300 leading-relaxed max-w-4xl mx-auto"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
Mycelium Society is for those building the sovereign digital world. Whether you're launching decentralized networks, protecting user privacy, or creating new forms of online communities, our infrastructure gives you full control, no intermediaries, no limits.
|
||||||
|
</motion.p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Scrolling Cards */}
|
||||||
|
<motion.div variants={fadeInUp}>
|
||||||
|
<ScrollingCards />
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ForYou;
|
131
src/components/Foundations.jsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
|
||||||
|
import legal from '../assets/legal.png';
|
||||||
|
import collective from '../assets/collective.png';
|
||||||
|
import sovereign from '../assets/sovereign.png';
|
||||||
|
|
||||||
|
const Foundations = () => {
|
||||||
|
|
||||||
|
|
||||||
|
const [activeImage, setActiveImage] = useState(legal);
|
||||||
|
const [hoveredIndex, setHoveredIndex] = useState(0); // Start with first item highlighted
|
||||||
|
|
||||||
|
const foundations = [
|
||||||
|
{
|
||||||
|
title: 'Legal Framework',
|
||||||
|
line1: 'Operate as a sovereign legal entity within our digital free zone. Form businesses, manage compliance, and handle taxation, all within a transparent, compliant system designed for digital sovereignty.',
|
||||||
|
image: legal,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Collective Direction',
|
||||||
|
line1: 'Members guide the roadmap. Every voice counts, every vote matters.',
|
||||||
|
line2: 'Together, we decide which tools replace corporate dependencies.',
|
||||||
|
image: collective,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Sovereign Infrastructure',
|
||||||
|
line1: 'A decentralized cloud, peer-to-peer networking protocols, and a legally recognized digital free zone. Your systems, your control, hosted on networks that cannot be shut down.',
|
||||||
|
image: sovereign,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="bg-gradient-to-b from-gray-900 to-black py-20 text-white">
|
||||||
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-16 text-center">
|
||||||
|
<h2 className="text-5xl font-bold text-center">
|
||||||
|
The <span className="text-cyan-400">Foundations</span> of the
|
||||||
|
</h2>
|
||||||
|
<h2 className="text-5xl font-bold text-center">Mycelium Society</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Two Column Container - Using Inline Styles for Absolute Control */}
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row', gap: '6rem', alignItems: 'center', justifyContent: 'center' }} className="flex-col lg:flex-row">
|
||||||
|
{/* Left Column - Image */}
|
||||||
|
<div style={{ width: '280px', flexShrink: 0 }} className="w-full lg:w-auto mb-12 lg:mb-0">
|
||||||
|
<div className="lg:sticky lg:top-24">
|
||||||
|
<AnimatePresence mode="wait">
|
||||||
|
<motion.img
|
||||||
|
key={activeImage}
|
||||||
|
src={activeImage}
|
||||||
|
alt="Foundation illustration"
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
exit={{ opacity: 0, scale: 0.9 }}
|
||||||
|
transition={{ duration: 0.4, ease: [0.4, 0, 0.2, 1] }}
|
||||||
|
style={{ width: '100%', height: 'auto', display: 'block' }}
|
||||||
|
/>
|
||||||
|
</AnimatePresence>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Column - Text Content */}
|
||||||
|
<div style={{ flex: 1, minWidth: 0, maxWidth: '60ch' }} className="w-full">
|
||||||
|
<div className="space-y-8">
|
||||||
|
{foundations.map((foundation, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
onMouseEnter={() => {
|
||||||
|
setActiveImage(foundation.image);
|
||||||
|
setHoveredIndex(index);
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setActiveImage(mushroom);
|
||||||
|
setHoveredIndex(null);
|
||||||
|
}}
|
||||||
|
className="relative group cursor-pointer"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: index * 0.1 }}
|
||||||
|
>
|
||||||
|
<div className={`
|
||||||
|
p-6 pb-8 rounded-lg transition-all duration-300 text-center
|
||||||
|
${hoveredIndex === index
|
||||||
|
? 'bg-gray-800/50 backdrop-blur-sm'
|
||||||
|
: 'bg-transparent'
|
||||||
|
}
|
||||||
|
`}>
|
||||||
|
<motion.div
|
||||||
|
className="absolute left-0 top-0 bottom-0 w-1 bg-cyan-400"
|
||||||
|
initial={{ scaleY: 0 }}
|
||||||
|
animate={{ scaleY: hoveredIndex === index ? 1 : 0 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<h3 className={`
|
||||||
|
text-2xl lg:text-3xl font-bold mb-2 transition-colors duration-300
|
||||||
|
${hoveredIndex === index ? 'text-cyan-400' : 'text-white'}
|
||||||
|
`}>
|
||||||
|
{foundation.title}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p className={`
|
||||||
|
text-base lg:text-lg leading-relaxed transition-all duration-300
|
||||||
|
${hoveredIndex === index ? 'text-gray-100' : 'text-gray-400'}
|
||||||
|
`}>
|
||||||
|
{foundation.line1}
|
||||||
|
</p>
|
||||||
|
<p className={`
|
||||||
|
text-base lg:text-lg leading-relaxed transition-all duration-300 mt-2 mb-12
|
||||||
|
${hoveredIndex === index ? 'text-gray-100' : 'text-gray-400'}
|
||||||
|
`}>
|
||||||
|
{foundation.line2}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{index < foundations.length - 1 && (
|
||||||
|
<div className="mt-6 h-px bg-gradient-to-r from-gray-700 via-gray-600 to-transparent" />
|
||||||
|
)}
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Foundations;
|
107
src/components/Hero.jsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import mushroomImg from '../assets/mushroom.png';
|
||||||
|
import SocietyTerminal from './SocietyTerminal';
|
||||||
|
|
||||||
|
const Hero = () => {
|
||||||
|
const [showTerminal, setShowTerminal] = useState(false);
|
||||||
|
|
||||||
|
const fadeInUp = {
|
||||||
|
hidden: { opacity: 0, y: 50 },
|
||||||
|
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const bounceIn = {
|
||||||
|
hidden: { scale: 0, opacity: 0 },
|
||||||
|
visible: { scale: 1, opacity: 1, transition: { type: "spring", bounce: 0.4, duration: 0.8 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const staggerContainer = {
|
||||||
|
visible: { transition: { staggerChildren: 0.2 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section className="min-h-screen flex items-center justify-center bg-dark-gradient relative overflow-hidden">
|
||||||
|
<motion.div
|
||||||
|
className="text-center z-10"
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
variants={staggerContainer}
|
||||||
|
>
|
||||||
|
{/* Mascot */}
|
||||||
|
<motion.div
|
||||||
|
className="mb-8"
|
||||||
|
variants={bounceIn}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={mushroomImg}
|
||||||
|
alt="Mycelium Society Mascot"
|
||||||
|
className="mx-auto max-w-xs"
|
||||||
|
style={{ width: 'auto', height: 'auto', maxHeight: '300px' }}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Main Title */}
|
||||||
|
<motion.h1
|
||||||
|
className="text-4xl md:text-6xl lg:text-7xl font-bold mb-8 leading-tight"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
<span className="text-white">Welcome to</span>
|
||||||
|
<br />
|
||||||
|
<span className="text-bright-cyan">Mycelium Society</span>
|
||||||
|
</motion.h1>
|
||||||
|
|
||||||
|
{/* Tagline */}
|
||||||
|
<motion.p
|
||||||
|
className="text-lg md:text-xl text-gray-300 mb-12 max-w-3xl mx-auto"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
A community inspired by network state concepts, combining people,
|
||||||
|
<br className="hidden sm:block" />
|
||||||
|
technology, and governance for global collaboration.
|
||||||
|
</motion.p>
|
||||||
|
|
||||||
|
{/* Buttons */}
|
||||||
|
<motion.div
|
||||||
|
className="flex flex-col sm:flex-row gap-4 justify-center items-center"
|
||||||
|
variants={fadeInUp}
|
||||||
|
>
|
||||||
|
<motion.button
|
||||||
|
className="btn-primary animate-pulse-glow"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
onClick={() => setShowTerminal(true)}
|
||||||
|
>
|
||||||
|
> ENTER THE NETWORK
|
||||||
|
</motion.button>
|
||||||
|
<a href="https://docs.ourworld.tf/mycelium_society_docs/docs/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<motion.button
|
||||||
|
className="btn-primary"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
> LEARN MORE
|
||||||
|
</motion.button>
|
||||||
|
</a>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Background Effects */}
|
||||||
|
<div className="absolute inset-0 overflow-hidden">
|
||||||
|
<div className="absolute -top-40 -right-40 w-80 h-80 bg-bright-cyan/5 rounded-full blur-3xl"></div>
|
||||||
|
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-cyan/5 rounded-full blur-3xl"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{showTerminal && (
|
||||||
|
<SocietyTerminal
|
||||||
|
showTerminal={showTerminal}
|
||||||
|
setShowTerminal={setShowTerminal}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Hero;
|
52
src/components/Manifesto.jsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import manifest from '../assets/manifest.png';
|
||||||
|
|
||||||
|
const Manifesto = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="bg-gradient-to-b from-gray-900 to-black py-20 text-white">
|
||||||
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-16 text-center">
|
||||||
|
<h2 className="text-5xl font-bold text-center">
|
||||||
|
Our <span className="text-cyan-400">Manifesto</span>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Two Column Container - Using Inline Styles for Absolute Control */}
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row', gap: '6rem', alignItems: 'flex-start', justifyContent: 'center' }} className="flex-col lg:flex-row">
|
||||||
|
{/* Left Column - Image */}
|
||||||
|
<div style={{ width: '280px', flexShrink: 0 }} className="w-full lg:w-auto mb-12 lg:mb-0">
|
||||||
|
<div className="lg:sticky lg:top-24">
|
||||||
|
<img
|
||||||
|
src={manifest}
|
||||||
|
alt="Mycelium Society Mascot"
|
||||||
|
style={{ width: '100%', height: 'auto', display: 'block' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Column - Text Content */}
|
||||||
|
<div style={{ flex: 1, minWidth: 0, maxWidth: '60ch' }} className="w-full">
|
||||||
|
<div className="space-y-8">
|
||||||
|
<p className="text-lg md:text-xl leading-relaxed text-gray-300 text-center">
|
||||||
|
Mycelium Society's mission is to eventually provide every tool individuals, organizations, and network states need to strategically opt-out of centralized digital systems and thrive independently with sovereign legal standing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div className="pt-4 text-center">
|
||||||
|
<p className="text-lg md:text-xl font-bold">
|
||||||
|
Own your digital sovereignty.
|
||||||
|
</p>
|
||||||
|
<p className="text-lg md:text-xl font-bold text-cyan-400">
|
||||||
|
Legally. Transparently. Together.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Manifesto;
|
121
src/components/ScrollingCards.jsx
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import builderImg from '../assets/builder.png';
|
||||||
|
import privacyAdvocateImg from '../assets/privacy_advocate.png';
|
||||||
|
import nomadImg from '../assets/nomad.png';
|
||||||
|
import creatorImg from '../assets/creator.png';
|
||||||
|
import developerImg from '../assets/developer.png';
|
||||||
|
import communityImg from '../assets/community.png';
|
||||||
|
import mushroomImg from '../assets/mushroom.png';
|
||||||
|
|
||||||
|
const ScrollingCards = () => {
|
||||||
|
const cards = [
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "For Privacy Seekers",
|
||||||
|
text: "Use digital tools that respect your data and autonomy by design, not as an afterthought.",
|
||||||
|
image: privacyAdvocateImg
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "For Digital Nomads",
|
||||||
|
text: "Manage your finances and business operations with a sovereign infrastructure that's always with you.",
|
||||||
|
image: nomadImg
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "For Creators",
|
||||||
|
text: "Own your content and distribution channels without platform intermediaries.",
|
||||||
|
image: creatorImg
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "For Developers",
|
||||||
|
text: "Access full-stack decentralized infrastructure to build your sovereign digital foundation, from secure UIs to robust legal frameworks.",
|
||||||
|
image: developerImg
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "For Organizations",
|
||||||
|
text: "Deploy private open source collaboration stacks, keeping your sensitive information within your own infrastructure.",
|
||||||
|
image: communityImg
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "For Network States",
|
||||||
|
text: "Access full-stack decentralized infrastructure to build your sovereign digital foundation.",
|
||||||
|
image: builderImg
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Duplicate cards for seamless infinite scroll
|
||||||
|
const duplicatedCards = [...cards, ...cards];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ overflow: 'hidden', padding: '2rem 0' }}>
|
||||||
|
<motion.div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
gap: '1.5rem',
|
||||||
|
width: `${(cards.length * 2) * 300}px`
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
x: [0, -(cards.length * 300)]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
x: {
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatType: "loop",
|
||||||
|
duration: 35,
|
||||||
|
ease: "linear",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{duplicatedCards.map((card, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
flexShrink: 0,
|
||||||
|
width: '280px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Top section with mascot */}
|
||||||
|
<div style={{
|
||||||
|
height: '280px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
borderRadius: '16px',
|
||||||
|
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
||||||
|
}}>
|
||||||
|
<img
|
||||||
|
src={card.image}
|
||||||
|
alt={card.title}
|
||||||
|
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom section with text */}
|
||||||
|
<div style={{
|
||||||
|
padding: '1rem 0',
|
||||||
|
textAlign: 'center'
|
||||||
|
}}>
|
||||||
|
<h3 style={{
|
||||||
|
color: 'white',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: '1.125rem',
|
||||||
|
marginBottom: '0.5rem',
|
||||||
|
fontFamily: "'Roboto Mono', monospace"
|
||||||
|
}}>
|
||||||
|
{card.title}
|
||||||
|
</h3>
|
||||||
|
<p style={{
|
||||||
|
color: '#9ca3af',
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: '1.4',
|
||||||
|
fontFamily: "'Roboto Mono', monospace"
|
||||||
|
}}>
|
||||||
|
{card.text}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ScrollingCards;
|
58
src/components/SocietyTerminal.jsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
function SocietyTerminal({ showTerminal, setShowTerminal }) {
|
||||||
|
const [terminalText, setTerminalText] = useState('');
|
||||||
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
|
|
||||||
|
const redirectMessages = [
|
||||||
|
'> connecting to member portal...',
|
||||||
|
'> synchronizing with mycelium network...',
|
||||||
|
'> welcome, initiate...'
|
||||||
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let typingTimer;
|
||||||
|
|
||||||
|
if (showTerminal) {
|
||||||
|
if (currentStep < redirectMessages.length) {
|
||||||
|
if (terminalText !== redirectMessages[currentStep]) {
|
||||||
|
typingTimer = setTimeout(() => {
|
||||||
|
setTerminalText(redirectMessages[currentStep].substring(0, terminalText.length + 1));
|
||||||
|
}, 50);
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
setCurrentStep(currentStep + 1);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = 'https://docs.ourworld.tf/mycelium_society_docs/docs/';
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => clearTimeout(typingTimer);
|
||||||
|
}, [showTerminal, currentStep, terminalText]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="terminal-overlay">
|
||||||
|
<div className="terminal">
|
||||||
|
<div className="terminal-header">
|
||||||
|
<div className="terminal-title">MYCELIUM SOCIETY PORTAL</div>
|
||||||
|
<button className="terminal-close" onClick={() => setShowTerminal(false)}>
|
||||||
|
abort
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-body h-96">
|
||||||
|
<div id="terminal-content">
|
||||||
|
{terminalText}
|
||||||
|
<span className="terminal-cursor"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SocietyTerminal;
|
47
src/components/ui/button.jsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { Slot } from "@radix-ui/react-slot"
|
||||||
|
import { cva } from "class-variance-authority";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const buttonVariants = cva(
|
||||||
|
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||||
|
destructive:
|
||||||
|
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||||
|
outline:
|
||||||
|
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||||
|
secondary:
|
||||||
|
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||||
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||||
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: "h-10 px-4 py-2",
|
||||||
|
sm: "h-9 rounded-md px-3",
|
||||||
|
lg: "h-11 rounded-md px-8",
|
||||||
|
icon: "h-10 w-10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
size: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "button"
|
||||||
|
return (
|
||||||
|
(<Comp
|
||||||
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
|
ref={ref}
|
||||||
|
{...props} />)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
Button.displayName = "Button"
|
||||||
|
|
||||||
|
export { Button, buttonVariants }
|
326
src/index.css
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
/* Custom CSS for Mycelium Society */
|
||||||
|
|
||||||
|
/* Import Roboto Mono and Avenir fonts */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300;400;500;700&display=swap');
|
||||||
|
/* Avenir is a system font on macOS, but we'll use a web-safe fallback stack */
|
||||||
|
|
||||||
|
/* Reset and base styles */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Avenir', 'Avenir Next', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
background: #000000;
|
||||||
|
color: white;
|
||||||
|
min-height: 100vh;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep all headings as Roboto Mono */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep buttons as Roboto Mono */
|
||||||
|
button {
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility classes */
|
||||||
|
.min-h-screen { min-height: 100vh; }
|
||||||
|
.flex { display: flex; }
|
||||||
|
.items-center { align-items: center; }
|
||||||
|
.justify-center { justify-content: center; }
|
||||||
|
.text-center { text-align: center; }
|
||||||
|
.relative { position: relative; }
|
||||||
|
.absolute { position: absolute; }
|
||||||
|
.overflow-hidden { overflow: hidden; }
|
||||||
|
.z-10 { z-index: 10; }
|
||||||
|
.mx-auto { margin-left: auto; margin-right: auto; }
|
||||||
|
.mb-4 { margin-bottom: 1rem; }
|
||||||
|
.mb-8 { margin-bottom: 2rem; }
|
||||||
|
.mb-12 { margin-bottom: 3rem; }
|
||||||
|
.mb-16 { margin-bottom: 4rem; }
|
||||||
|
.py-8 { padding-top: 2rem; padding-bottom: 2rem; }
|
||||||
|
.py-20 { padding-top: 5rem; padding-bottom: 5rem; }
|
||||||
|
.py-32 { padding-top: 8rem; padding-bottom: 8rem; }
|
||||||
|
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
|
||||||
|
.px-8 { padding-left: 2rem; padding-right: 2rem; }
|
||||||
|
.p-4 { padding: 1rem; }
|
||||||
|
.pl-6 { padding-left: 1.5rem; }
|
||||||
|
.w-48 { width: 12rem; }
|
||||||
|
.h-48 { height: 12rem; }
|
||||||
|
.w-72 { width: 18rem; }
|
||||||
|
.h-96 { height: 24rem; }
|
||||||
|
.h-72 { height: 18rem; }
|
||||||
|
.h-24 { height: 6rem; }
|
||||||
|
.max-w-4xl { max-width: 56rem; }
|
||||||
|
.max-w-3xl { max-width: 48rem; }
|
||||||
|
.rounded-full { border-radius: 9999px; }
|
||||||
|
.rounded-2xl { border-radius: 1rem; }
|
||||||
|
.shadow-lg { box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); }
|
||||||
|
.gap-4 { gap: 1rem; }
|
||||||
|
.gap-6 { gap: 1.5rem; }
|
||||||
|
.space-y-12 > * + * { margin-top: 3rem; }
|
||||||
|
.leading-tight { line-height: 1.25; }
|
||||||
|
.leading-relaxed { line-height: 1.625; }
|
||||||
|
.uppercase { text-transform: uppercase; }
|
||||||
|
.font-bold { font-weight: 700; }
|
||||||
|
.border-2 { border-width: 2px; }
|
||||||
|
.border-l-2 { border-left-width: 2px; }
|
||||||
|
.flex-shrink-0 { flex-shrink: 0; }
|
||||||
|
.flex-col { flex-direction: column; }
|
||||||
|
|
||||||
|
/* Background classes */
|
||||||
|
.bg-dark-gradient { background: #000000; }
|
||||||
|
.bg-gray-900 { background-color: #111827; }
|
||||||
|
.bg-amber-100 { background-color: #fef3c7; }
|
||||||
|
.bg-blue-100 { background-color: #dbeafe; }
|
||||||
|
.bg-pink-100 { background-color: #fce7f3; }
|
||||||
|
.bg-yellow-100 { background-color: #fef3c7; }
|
||||||
|
.bg-green-100 { background-color: #dcfce7; }
|
||||||
|
.bg-orange-100 { background-color: #fed7aa; }
|
||||||
|
.bg-purple-100 { background-color: #e9d5ff; }
|
||||||
|
|
||||||
|
/* Text colors */
|
||||||
|
.text-white { color: #ffffff; }
|
||||||
|
.text-gray-300 { color: #d1d5db; }
|
||||||
|
.text-gray-400 { color: #9ca3af; }
|
||||||
|
.text-bright-cyan { color: #00d9ff; }
|
||||||
|
.text-red-accent { color: #ff3366; }
|
||||||
|
|
||||||
|
/* Border colors */
|
||||||
|
.border-bright-cyan { border-color: #00d9ff; }
|
||||||
|
|
||||||
|
/* Text sizes */
|
||||||
|
.text-sm { font-size: 0.875rem; }
|
||||||
|
.text-lg { font-size: 1.125rem; }
|
||||||
|
.text-xl { font-size: 1.25rem; }
|
||||||
|
.text-2xl { font-size: 1.5rem; }
|
||||||
|
.text-3xl { font-size: 1.875rem; }
|
||||||
|
.text-4xl { font-size: 2.25rem; }
|
||||||
|
.text-5xl { font-size: 3rem; }
|
||||||
|
.text-6xl { font-size: 3.75rem; }
|
||||||
|
.text-7xl { font-size: 4.5rem; }
|
||||||
|
|
||||||
|
/* Button styles */
|
||||||
|
.btn-primary {
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid #00d9ff;
|
||||||
|
color: #00d9ff;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
padding: 0.625rem 1.5rem;
|
||||||
|
border-radius: 2px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
box-shadow: 0 0 20px #00d9ff, 0 0 30px #00d9ff;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container widths */
|
||||||
|
.container-width {
|
||||||
|
max-width: 56rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-padding {
|
||||||
|
padding-top: 5rem;
|
||||||
|
padding-bottom: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text gradient */
|
||||||
|
.text-gradient {
|
||||||
|
background: linear-gradient(to right, #00d9ff, #00ffff);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes pulse-glow {
|
||||||
|
0% { box-shadow: 0 0 5px #00d9ff; }
|
||||||
|
100% { box-shadow: 0 0 20px #00d9ff, 0 0 30px #00d9ff; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-pulse-glow {
|
||||||
|
animation: pulse-glow 2s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrolling animation */
|
||||||
|
@keyframes scroll {
|
||||||
|
0% { transform: translateX(0); }
|
||||||
|
100% { transform: translateX(-100%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-scroll {
|
||||||
|
animation: scroll 30s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #00d9ff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #00ffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive design */
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:flex-row { flex-direction: row; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:text-2xl { font-size: 1.5rem; }
|
||||||
|
.md\:text-3xl { font-size: 1.875rem; }
|
||||||
|
.md\:text-5xl { font-size: 3rem; }
|
||||||
|
.md\:text-6xl { font-size: 3.75rem; }
|
||||||
|
.md\:text-xl { font-size: 1.25rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:text-7xl { font-size: 4.5rem; }
|
||||||
|
.lg\:px-8 { padding-left: 2rem; padding-right: 2rem; }
|
||||||
|
.lg\:py-32 { padding-top: 8rem; padding-bottom: 8rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Line clamp utility */
|
||||||
|
.line-clamp-2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Additional spacing utilities */
|
||||||
|
.tracking-widest { letter-spacing: 0.1em; }
|
||||||
|
|
||||||
|
/* Terminal styles */
|
||||||
|
.terminal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
z-index: 50;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal {
|
||||||
|
width: 90%;
|
||||||
|
max-width: 800px;
|
||||||
|
height: 600px;
|
||||||
|
background: #0a0a0a;
|
||||||
|
border: 1px solid #00d9ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 30px rgba(0, 217, 255, 0.3);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
background: #1a1a1a;
|
||||||
|
border-bottom: 1px solid #00d9ff;
|
||||||
|
border-top-left-radius: 8px;
|
||||||
|
border-top-right-radius: 8px;
|
||||||
|
color: #00d9ff;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #ff3366;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-body {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 1.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
color: #00ff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal-content {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-cursor {
|
||||||
|
display: inline-block;
|
||||||
|
width: 10px;
|
||||||
|
height: 1.2em;
|
||||||
|
background: #00ff00;
|
||||||
|
animation: blink 1s step-end infinite;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
50% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-green-400 {
|
||||||
|
color: #4ade80;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-red-400 {
|
||||||
|
color: #f87171;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-cyan-400 {
|
||||||
|
color: #22d3ee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-mono {
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:outline-none:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:ring-0:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
6
src/lib/utils.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { clsx } from "clsx"
|
||||||
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
|
export function cn(...inputs) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
10
src/main.jsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { StrictMode } from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import './index.css'
|
||||||
|
import App from './App.jsx'
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>,
|
||||||
|
)
|
12
vite.config.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import path from "path"
|
||||||
|
import react from "@vitejs/plugin-react"
|
||||||
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|