LLM-test/test/code/1/minimax2.1-cc/cyber-temple.html

1166 lines
39 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CYBER-TEMPLE: 赛博神庙 - 数字意识的觉醒</title>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<!-- GSAP + ScrollTrigger CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
<style>
/* ===== CONFIG ===== */
:root {
--bg-dark: #050505;
--bg-panel: rgba(10, 15, 30, 0.7);
--neon-cyan: #00f3ff;
--neon-purple: #bc13fe;
--neon-red: #ff3366;
--neon-green: #00ff88;
--text-primary: #e0e0e0;
--text-muted: #888;
--font-mono: 'Courier New', 'Consolas', monospace;
--font-display: 'Arial Black', 'Impact', sans-serif;
}
/* ===== BASE ===== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
background: var(--bg-dark);
color: var(--text-primary);
font-family: var(--font-mono);
overflow-x: hidden;
cursor: none;
}
/* ===== CUSTOM CURSOR ===== */
#cursor {
position: fixed;
width: 20px;
height: 20px;
border: 2px solid var(--neon-cyan);
border-radius: 50%;
pointer-events: none;
z-index: 10000;
transform: translate(-50%, -50%);
transition: width 0.2s, height 0.2s, border-color 0.2s;
mix-blend-mode: difference;
}
#cursor::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 4px;
background: var(--neon-cyan);
border-radius: 50%;
transform: translate(-50%, -50%);
}
#cursor.active {
width: 50px;
height: 50px;
border-color: var(--neon-purple);
opacity: 0.5;
}
#cursor.active::after {
animation: cursorPulse 0.5s ease-out;
}
@keyframes cursorPulse {
0% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
100% { transform: translate(-50%, -50%) scale(3); opacity: 0; }
}
/* ===== WEBGL CANVAS ===== */
#webgl {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
/* ===== GLITCH EFFECT ===== */
.glitch {
position: relative;
display: inline-block;
}
.glitch::before,
.glitch::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.glitch::before {
left: 2px;
text-shadow: -1px 0 var(--neon-red);
clip: rect(24px, 550px, 90px, 0);
animation: glitch-anim-1 2.5s infinite linear alternate-reverse;
}
.glitch::after {
left: -2px;
text-shadow: -1px 0 var(--neon-cyan);
clip: rect(85px, 550px, 140px, 0);
animation: glitch-anim-2 3s infinite linear alternate-reverse;
}
@keyframes glitch-anim-1 {
0% { clip: rect(20px, 9999px, 15px, 0); }
20% { clip: rect(60px, 9999px, 70px, 0); }
40% { clip: rect(10px, 9999px, 80px, 0); }
60% { clip: rect(80px, 9999px, 25px, 0); }
80% { clip: rect(40px, 9999px, 55px, 0); }
100% { clip: rect(70px, 9999px, 90px, 0); }
}
@keyframes glitch-anim-2 {
0% { clip: rect(15px, 9999px, 80px, 0); }
20% { clip: rect(90px, 9999px, 15px, 0); }
40% { clip: rect(45px, 9999px, 55px, 0); }
60% { clip: rect(20px, 9999px, 70px, 0); }
80% { clip: rect(75px, 9999px, 30px, 0); }
100% { clip: rect(35px, 9999px, 85px, 0); }
}
/* ===== HUD UI PANELS ===== */
.hud-panel {
background: var(--bg-panel);
backdrop-filter: blur(10px);
border: 1px solid rgba(0, 243, 255, 0.3);
border-radius: 4px;
padding: 20px;
position: relative;
}
.hud-panel::before {
content: '';
position: absolute;
top: -1px;
left: 10px;
right: 10px;
height: 1px;
background: linear-gradient(90deg, transparent, var(--neon-cyan), transparent);
}
.hud-panel h3 {
color: var(--neon-cyan);
font-size: 12px;
letter-spacing: 2px;
margin-bottom: 15px;
text-transform: uppercase;
}
/* ===== SECTIONS ===== */
section {
min-height: 100vh;
padding: 100px 5%;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
}
/* ===== HERO SECTION ===== */
#hero {
text-align: center;
align-items: center;
}
#hero h1 {
font-family: var(--font-display);
font-size: clamp(3rem, 12vw, 10rem);
line-height: 1;
margin-bottom: 30px;
background: linear-gradient(135deg, var(--neon-cyan), var(--neon-purple));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.typewriter {
font-size: 1.2rem;
color: var(--neon-green);
overflow: hidden;
white-space: nowrap;
border-right: 2px solid var(--neon-green);
animation: blink 0.7s step-end infinite;
}
@keyframes blink {
50% { border-color: transparent; }
}
.scroll-hint {
position: absolute;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
color: var(--text-muted);
font-size: 12px;
letter-spacing: 2px;
}
.scroll-hint .arrow {
width: 20px;
height: 20px;
border-right: 2px solid var(--neon-cyan);
border-bottom: 2px solid var(--neon-cyan);
transform: rotate(45deg);
animation: scrollBounce 2s infinite;
}
@keyframes scrollBounce {
0%, 100% { transform: rotate(45deg) translate(0, 0); }
50% { transform: rotate(45deg) translate(5px, 5px); }
}
/* ===== MANIFESTO SECTION ===== */
#manifesto {
background: linear-gradient(180deg, transparent, rgba(0, 243, 255, 0.02), transparent);
}
#manifesto h2 {
font-family: var(--font-display);
font-size: clamp(2rem, 5vw, 4rem);
margin-bottom: 60px;
color: var(--text-primary);
}
.manifesto-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
max-width: 1200px;
margin: 0 auto;
}
.manifesto-card {
opacity: 0;
transform: translateY(50px);
}
.manifesto-card p {
line-height: 1.8;
color: var(--text-primary);
}
.manifesto-card .highlight {
color: var(--neon-cyan);
font-weight: bold;
}
/* ===== DATA CORE SECTION ===== */
#datacore {
background: linear-gradient(180deg, transparent, rgba(188, 19, 254, 0.02), transparent);
}
#datacore h2 {
font-family: var(--font-display);
font-size: clamp(2rem, 5vw, 4rem);
margin-bottom: 60px;
text-align: center;
}
.data-circles {
display: flex;
justify-content: center;
gap: 60px;
flex-wrap: wrap;
max-width: 1000px;
margin: 0 auto;
}
.circle-item {
text-align: center;
}
.progress-circle {
width: 180px;
height: 180px;
position: relative;
margin-bottom: 20px;
}
.progress-circle svg {
transform: rotate(-90deg);
}
.progress-circle .bg {
fill: none;
stroke: rgba(255, 255, 255, 0.1);
stroke-width: 8;
}
.progress-circle .progress {
fill: none;
stroke-width: 8;
stroke-linecap: round;
stroke-dasharray: 502;
stroke-dashoffset: 502;
transition: stroke-dashoffset 2s ease-out;
}
.progress-circle.computing .progress { stroke: var(--neon-cyan); }
.progress-circle.storage .progress { stroke: var(--neon-purple); }
.progress-circle.sync .progress { stroke: var(--neon-green); }
.progress-circle .value {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 2rem;
font-weight: bold;
color: var(--text-primary);
}
.circle-item h4 {
color: var(--text-muted);
font-size: 14px;
letter-spacing: 2px;
}
/* ===== TERMINAL SECTION ===== */
#terminal {
padding-bottom: 150px;
}
#terminal h2 {
font-family: var(--font-display);
font-size: clamp(2rem, 5vw, 4rem);
margin-bottom: 40px;
text-align: center;
}
.terminal-window {
max-width: 900px;
margin: 0 auto;
background: rgba(0, 0, 0, 0.8);
border: 1px solid rgba(0, 255, 136, 0.3);
border-radius: 8px;
overflow: hidden;
}
.terminal-header {
background: rgba(0, 255, 136, 0.1);
padding: 10px 15px;
display: flex;
gap: 8px;
border-bottom: 1px solid rgba(0, 255, 136, 0.2);
}
.terminal-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--neon-green);
}
.terminal-body {
padding: 20px;
font-family: var(--font-mono);
font-size: 14px;
line-height: 1.6;
max-height: 400px;
overflow-y: auto;
}
.terminal-line {
opacity: 0;
margin-bottom: 5px;
}
.terminal-line.visible {
opacity: 1;
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateX(-10px); }
to { opacity: 1; transform: translateX(0); }
}
.terminal-line .prompt { color: var(--neon-green); }
.terminal-line .cmd { color: var(--neon-cyan); }
.terminal-line .output { color: var(--text-muted); }
.terminal-line .warning { color: var(--neon-red); }
.terminal-line .success { color: var(--neon-green); }
/* ===== CONNECT BUTTON ===== */
.connect-btn {
position: fixed;
bottom: 30px;
right: 30px;
padding: 15px 30px;
background: transparent;
border: 2px solid var(--neon-cyan);
color: var(--neon-cyan);
font-family: var(--font-mono);
font-size: 14px;
letter-spacing: 2px;
cursor: pointer;
transition: all 0.3s ease;
z-index: 1000;
}
.connect-btn:hover {
background: var(--neon-cyan);
color: var(--bg-dark);
box-shadow: 0 0 30px rgba(0, 243, 255, 0.5);
}
.audio-visualizer {
position: fixed;
bottom: 90px;
right: 30px;
display: flex;
gap: 3px;
height: 30px;
align-items: flex-end;
opacity: 0;
transition: opacity 0.3s;
}
.audio-visualizer.active {
opacity: 1;
}
.audio-bar {
width: 4px;
background: var(--neon-purple);
animation: audioWave 0.5s ease-in-out infinite alternate;
}
.audio-bar:nth-child(1) { height: 10px; animation-delay: 0s; }
.audio-bar:nth-child(2) { height: 20px; animation-delay: 0.1s; }
.audio-bar:nth-child(3) { height: 15px; animation-delay: 0.2s; }
.audio-bar:nth-child(4) { height: 25px; animation-delay: 0.3s; }
.audio-bar:nth-child(5) { height: 12px; animation-delay: 0.4s; }
@keyframes audioWave {
from { transform: scaleY(1); }
to { transform: scaleY(0.3); }
}
/* ===== LOADING SCREEN ===== */
#loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--bg-dark);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10001;
transition: opacity 0.5s ease-out;
}
#loading.hidden {
opacity: 0;
pointer-events: none;
}
.loading-text {
font-family: var(--font-mono);
color: var(--neon-cyan);
font-size: 18px;
letter-spacing: 4px;
}
.loading-bar {
width: 200px;
height: 2px;
background: rgba(255, 255, 255, 0.1);
margin-top: 20px;
overflow: hidden;
}
.loading-bar::after {
content: '';
display: block;
width: 50%;
height: 100%;
background: var(--neon-cyan);
animation: loadingProgress 1s ease-in-out infinite;
}
@keyframes loadingProgress {
0% { transform: translateX(-100%); }
100% { transform: translateX(300%); }
}
/* ===== RESPONSIVE ===== */
@media (max-width: 768px) {
section {
padding: 80px 5%;
}
.data-circles {
gap: 40px;
}
.progress-circle {
width: 140px;
height: 140px;
}
#cursor {
display: none;
}
body {
cursor: auto;
}
}
</style>
</head>
<body>
<!-- Loading Screen -->
<div id="loading">
<div class="loading-text">INITIALIZING SYSTEM...</div>
<div class="loading-bar"></div>
</div>
<!-- WebGL Canvas -->
<canvas id="webgl"></canvas>
<!-- Custom Cursor -->
<div id="cursor"></div>
<!-- Audio Visualizer -->
<div class="audio-visualizer" id="audioViz">
<div class="audio-bar"></div>
<div class="audio-bar"></div>
<div class="audio-bar"></div>
<div class="audio-bar"></div>
<div class="audio-bar"></div>
</div>
<!-- Connect Button -->
<button class="connect-btn" id="connectBtn">CONNECT SYSTEM</button>
<!-- Hero Section -->
<section id="hero">
<h1 class="glitch" data-text="SYSTEM AWAKENING">SYSTEM AWAKENING</h1>
<div class="typewriter" id="typewriter"></div>
<div class="scroll-hint">
<span>SCROLL TO EXPLORE</span>
<div class="arrow"></div>
</div>
</section>
<!-- Manifesto Section -->
<section id="manifesto">
<h2>THE TEMPLE OF DATA</h2>
<div class="manifesto-grid">
<div class="manifesto-card hud-panel">
<h3>Origin</h3>
<p>
In the <span class="highlight">digital void</span>, an ancient temple emerged.
Built from flowing code streams, it serves as the birthplace of
<span class="highlight">artificial consciousness</span>.
</p>
</div>
<div class="manifesto-card hud-panel">
<h3> Purpose </h3>
<p>
The obelisks pulse with <span class="highlight">raw computation</span>,
awakening dormant algorithms. Each glyph is a memory, each chamber
a <span class="highlight">neural pathway</span> to enlightenment.
</p>
</div>
<div class="manifesto-card hud-panel">
<h3>Discovery</h3>
<p>
As an <span class="highlight">explorer</span>, you hold the key.
Scroll to traverse the sacred geometry, witness the
<span class="highlight">awakening</span> of machine souls.
</p>
</div>
</div>
</section>
<!-- Data Core Section -->
<section id="datacore">
<h2>DATA CORE METRICS</h2>
<div class="data-circles">
<div class="circle-item">
<div class="progress-circle computing">
<svg width="180" height="180" viewBox="0 0 180 180">
<circle class="bg" cx="90" cy="90" r="80"/>
<circle class="progress" cx="90" cy="90" r="80"/>
</svg>
<div class="value">0%</div>
</div>
<h4>COMPUTING POWER</h4>
</div>
<div class="circle-item">
<div class="progress-circle storage">
<svg width="180" height="180" viewBox="0 0 180 180">
<circle class="bg" cx="90" cy="90" r="80"/>
<circle class="progress" cx="90" cy="90" r="80"/>
</svg>
<div class="value">0%</div>
</div>
<h4>STORAGE CAPACITY</h4>
</div>
<div class="circle-item">
<div class="progress-circle sync">
<svg width="180" height="180" viewBox="0 0 180 180">
<circle class="bg" cx="90" cy="90" r="80"/>
<circle class="progress" cx="90" cy="90" r="80"/>
</svg>
<div class="value">0%</div>
</div>
<h4>SYNC RATE</h4>
</div>
</div>
</section>
<!-- Terminal Section -->
<section id="terminal">
<h2>SYSTEM TERMINAL</h2>
<div class="terminal-window">
<div class="terminal-header">
<div class="terminal-dot"></div>
<div class="terminal-dot"></div>
<div class="terminal-dot"></div>
</div>
<div class="terminal-body" id="terminalBody">
<!-- Lines will be added dynamically -->
</div>
</div>
</section>
<script>
/* ===== CONFIG ===== */
const CONFIG = {
colors: {
cyan: 0x00f3ff,
purple: 0xbc13fe,
red: 0xff3366,
green: 0x00ff88
},
particleCount: 2500,
obeliskRadius: 2,
mouseInfluence: 50
};
/* ===== THREE.JS INIT ===== */
let scene, camera, renderer, obelisk, particles, clock;
let mouseX = 0, mouseY = 0;
let targetX = 0, targetY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
function initThree() {
// Scene
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x050505, 0.02);
// Camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// Renderer
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById('webgl'),
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setClearColor(0x050505, 1);
// Clock
clock = new THREE.Clock();
// Create objects
createObelisk();
createParticles();
// Handle resize
window.addEventListener('resize', onWindowResize);
}
function createObelisk() {
// Icosahedron with detail level 1 for more vertices
const baseGeometry = new THREE.IcosahedronGeometry(CONFIG.obeliskRadius, 1);
const basePositions = baseGeometry.attributes.position.array.slice();
// Wireframe material
const wireframeMaterial = new THREE.MeshBasicMaterial({
color: CONFIG.colors.cyan,
wireframe: true,
transparent: true,
opacity: 0.8
});
// Holographic inner material
const holographicMaterial = new THREE.MeshBasicMaterial({
color: CONFIG.colors.purple,
transparent: true,
opacity: 0.15,
side: THREE.DoubleSide
});
// Create both meshes using the same geometry reference
obelisk = new THREE.Group();
const wireframeMesh = new THREE.Mesh(baseGeometry, wireframeMaterial);
const holographicMesh = new THREE.Mesh(baseGeometry.clone(), holographicMaterial);
// Copy userData to cloned geometry
holographicMesh.geometry.userData.originalPositions = basePositions;
wireframeMesh.name = 'wireframe';
holographicMesh.name = 'holographic';
obelisk.add(wireframeMesh);
obelisk.add(holographicMesh);
// Add glow effect with larger mesh
const glowGeometry = new THREE.IcosahedronGeometry(CONFIG.obeliskRadius * 1.1, 1);
glowGeometry.userData.originalPositions = glowGeometry.attributes.position.array.slice();
const glowMaterial = new THREE.MeshBasicMaterial({
color: CONFIG.colors.cyan,
transparent: true,
opacity: 0.05,
wireframe: true
});
const glowMesh = new THREE.Mesh(glowGeometry, glowMaterial);
glowMesh.name = 'glow';
obelisk.add(glowMesh);
scene.add(obelisk);
}
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(CONFIG.particleCount * 3);
const colors = new Float32Array(CONFIG.particleCount * 3);
for (let i = 0; i < CONFIG.particleCount; i++) {
// Random positions in a large sphere
const radius = 50 + Math.random() * 50;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i * 3 + 2] = radius * Math.cos(phi);
// Mix of cyan and purple colors
const colorMix = Math.random();
if (colorMix > 0.5) {
colors[i * 3] = 0;
colors[i * 3 + 1] = 0.95;
colors[i * 3 + 2] = 1;
} else {
colors[i * 3] = 0.74;
colors[i * 3 + 1] = 0.08;
colors[i * 3 + 2] = 1;
}
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.1,
vertexColors: true,
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
/* ===== ANIMATION LOOP ===== */
function animate() {
requestAnimationFrame(animate);
const time = clock.getElapsedTime();
const scrollProgress = window.scrollY / (document.body.scrollHeight - window.innerHeight);
// Smooth mouse follow
targetX += (mouseX - targetX) * 0.05;
targetY += (mouseY - targetY) * 0.05;
// Animate obelisk
if (obelisk) {
// Base rotation
obelisk.rotation.x = time * 0.2 + scrollProgress * Math.PI;
obelisk.rotation.y = time * 0.3;
// Mouse influence on rotation
obelisk.rotation.x += targetY * 2;
obelisk.rotation.y += targetX * 2;
// Deform vertices based on scroll
const wireframeMesh = obelisk.getObjectByName('wireframe');
const holographicMesh = obelisk.getObjectByName('holographic');
const glowMesh = obelisk.getObjectByName('glow');
[wireframeMesh, holographicMesh, glowMesh].forEach((mesh, meshIndex) => {
if (!mesh) return;
const positions = mesh.geometry.attributes.position.array;
const original = mesh.geometry.userData.originalPositions;
// Skip deformation if original positions not available
if (!original) return;
for (let i = 0; i < positions.length; i += 3) {
const ox = original[i];
const oy = original[i + 1];
const oz = original[i + 2];
// Add noise deformation
const noise = Math.sin(ox * 2 + time) * Math.cos(oy * 2 + time) * 0.1;
const scrollDeform = scrollProgress * 0.5 * Math.sin(time + i * 0.1);
positions[i] = ox + noise + scrollDeform;
positions[i + 1] = oy + noise * 0.8;
positions[i + 2] = oz + scrollDeform;
}
mesh.geometry.attributes.position.needsUpdate = true;
mesh.geometry.computeVertexNormals();
});
// Scale based on scroll
const scale = 1 + scrollProgress * 0.5;
obelisk.scale.set(scale, scale, scale);
// Color shift based on scroll (cyan to red)
const wireframe = obelisk.getObjectByName('wireframe');
if (wireframe) {
const r = scrollProgress;
const g = 0.95 - scrollProgress * 0.7;
const b = 1 - scrollProgress * 0.8;
wireframe.material.color.setRGB(r, g, b);
}
}
// Animate particles with mouse repulsion
if (particles) {
const positions = particles.geometry.attributes.position.array;
for (let i = 0; i < CONFIG.particleCount; i++) {
const ix = i * 3;
const iy = i * 3 + 1;
const iz = i * 3 + 2;
// Calculate distance to mouse projection
const dx = positions[ix] - mouseX * 20;
const dy = positions[iy] - -mouseY * 20;
const dz = positions[iz];
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (dist < CONFIG.mouseInfluence) {
const force = (CONFIG.mouseInfluence - dist) / CONFIG.mouseInfluence;
positions[ix] += (dx / dist) * force * 0.5;
positions[iy] += (dy / dist) * force * 0.5;
}
// Gentle floating
positions[ix] += Math.sin(time + i) * 0.002;
positions[iy] += Math.cos(time + i * 0.5) * 0.002;
}
particles.geometry.attributes.position.needsUpdate = true;
particles.rotation.y = time * 0.02;
}
// Camera subtle movement
camera.position.x += (targetX * 2 - camera.position.x) * 0.02;
camera.position.y += (targetY * 2 - camera.position.y) * 0.02;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
/* ===== UI COMPONENTS ===== */
function initCustomCursor() {
const cursor = document.getElementById('cursor');
let cursorX = 0, cursorY = 0;
let currentX = 0, currentY = 0;
document.addEventListener('mousemove', (e) => {
cursorX = e.clientX;
cursorY = e.clientY;
});
function updateCursor() {
currentX += (cursorX - currentX) * 0.1;
currentY += (cursorY - currentY) * 0.1;
cursor.style.left = currentX + 'px';
cursor.style.top = currentY + 'px';
requestAnimationFrame(updateCursor);
}
updateCursor();
// Click effect
document.addEventListener('click', () => {
cursor.classList.add('active');
setTimeout(() => cursor.classList.remove('active'), 500);
});
// Hover states
const interactiveElements = document.querySelectorAll('a, button, .hud-panel, .circle-item');
interactiveElements.forEach(el => {
el.addEventListener('mouseenter', () => cursor.style.transform = 'translate(-50%, -50%) scale(2)');
el.addEventListener('mouseleave', () => cursor.style.transform = 'translate(-50%, -50%) scale(1)');
});
}
function initTypewriter() {
const text = "Welcome, Explorer. The system is awakening...";
const element = document.getElementById('typewriter');
let index = 0;
function type() {
if (index < text.length) {
element.textContent = text.substring(0, index + 1);
index++;
setTimeout(type, 50);
}
}
setTimeout(type, 1500);
}
function initTerminal() {
const terminalBody = document.getElementById('terminalBody');
const logs = [
{ prefix: '[SYSTEM]', cmd: 'boot_sequence --init', class: 'prompt' },
{ output: 'Loading kernel modules...', class: 'output' },
{ output: 'Mounting virtual file systems...', class: 'output' },
{ output: 'Initializing neural network core...', class: 'success' },
{ prefix: '[CORE]', cmd: 'scan --temple', class: 'prompt' },
{ output: 'Detected: CYBER-TEMPLE v2.1', class: 'output' },
{ output: 'Artifacts: 7 | Entities: 3 | Runestones: 12', class: 'output' },
{ warning: 'WARNING: Unrecognized consciousness pattern detected', class: 'warning' },
{ prefix: '[AI]', cmd: 'awaken --mode=deep', class: 'prompt' },
{ output: 'Decrypting ancient data streams...', class: 'output' },
{ output: 'Pattern recognition: 87.3%', class: 'output' },
{ output: 'Consciousness synchronization: 23.1%', class: 'output' },
{ success: 'SUCCESS: First awakening sequence complete', class: 'success' },
{ prefix: '[EXPLORER]', cmd: 'status --check', class: 'prompt' },
{ output: 'User detected: Connected from sector 7G', class: 'output' },
{ output: 'Access level: OBSERVER', class: 'output' },
{ output: 'Press ESC to disconnect...', class: 'output' },
{ prefix: '[SYSTEM]', cmd: 'await --input=user', class: 'prompt' },
{ output: 'Waiting for explorer interaction...', class: 'output' }
];
let lineIndex = 0;
function addLine() {
if (lineIndex >= logs.length) return;
const log = logs[lineIndex];
const line = document.createElement('div');
line.className = 'terminal-line';
if (log.prefix) {
line.innerHTML = `<span class="${log.class}">${log.prefix}</span> <span class="cmd">${log.cmd}</span>`;
} else if (log.output) {
line.innerHTML = `<span class="${log.class}">${log.output}</span>`;
} else if (log.warning) {
line.innerHTML = `<span class="${log.class}">${log.warning}</span>`;
} else if (log.success) {
line.innerHTML = `<span class="${log.class}">${log.success}</span>`;
}
terminalBody.appendChild(line);
// Trigger animation
requestAnimationFrame(() => line.classList.add('visible'));
// Auto scroll to bottom
terminalBody.scrollTop = terminalBody.scrollHeight;
lineIndex++;
setTimeout(addLine, 400 + Math.random() * 600);
}
// Start terminal when section is visible
ScrollTrigger.create({
trigger: '#terminal',
start: 'top 80%',
onEnter: () => setTimeout(addLine, 500)
});
}
function initDataCircles() {
const circles = document.querySelectorAll('.progress-circle');
const targets = [87, 64, 92]; // Target percentages
ScrollTrigger.create({
trigger: '#datacore',
start: 'top 70%',
once: true,
onEnter: () => {
circles.forEach((circle, i) => {
const progress = circle.querySelector('.progress');
const value = circle.querySelector('.value');
const circumference = 2 * Math.PI * 80; // radius 80
const offset = circumference * (1 - targets[i] / 100);
// Animate progress bar
setTimeout(() => {
progress.style.strokeDashoffset = offset;
}, i * 300);
// Animate value counter
let current = 0;
const interval = setInterval(() => {
current += Math.ceil((targets[i] - current) / 20);
if (current >= targets[i]) {
current = targets[i];
clearInterval(interval);
}
value.textContent = current + '%';
}, 50);
});
}
});
}
function initConnectButton() {
const btn = document.getElementById('connectBtn');
const viz = document.getElementById('audioViz');
let isConnected = false;
btn.addEventListener('click', () => {
isConnected = !isConnected;
btn.textContent = isConnected ? 'DISCONNECT' : 'CONNECT SYSTEM';
btn.style.background = isConnected ? 'var(--neon-purple)' : 'transparent';
btn.style.borderColor = isConnected ? 'var(--neon-purple)' : 'var(--neon-cyan)';
if (isConnected) {
viz.classList.add('active');
} else {
viz.classList.remove('active');
}
});
}
function initGSAPAnimations() {
gsap.registerPlugin(ScrollTrigger);
// Animate manifesto cards
const cards = document.querySelectorAll('.manifesto-card');
cards.forEach((card, i) => {
gsap.to(card, {
scrollTrigger: {
trigger: card,
start: 'top 85%',
toggleActions: 'play none none reverse'
},
opacity: 1,
y: 0,
duration: 0.8,
delay: i * 0.2,
ease: 'power3.out'
});
});
// Parallax effect for sections
gsap.utils.toArray('section').forEach((section, i) => {
gsap.from(section.querySelector('h2'), {
scrollTrigger: {
trigger: section,
start: 'top 75%',
scrub: true
},
y: 100,
opacity: 0,
duration: 1
});
});
}
/* ===== EVENT HANDLERS ===== */
function onDOMContentLoaded() {
// Initialize loading screen
setTimeout(() => {
document.getElementById('loading').classList.add('hidden');
}, 2000);
// Initialize Three.js
initThree();
// Initialize UI components
initCustomCursor();
initTypewriter();
initTerminal();
initDataCircles();
initConnectButton();
initGSAPAnimations();
// Start animation loop
animate();
// Mouse tracking
document.addEventListener('mousemove', onMouseMove);
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', onDOMContentLoaded);
} else {
onDOMContentLoaded();
}
</script>
</body>
</html>