You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

936 lines
56 KiB

<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Microgrid | Smart Energy System</title>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com" rel="preconnect"/>
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;700;900&family=Montserrat:wght@400;500;700;800;900&family=Inter:wght@400;500;700;800;900&family=JetBrains+Mono:wght@500&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-tilt/1.7.2/vanilla-tilt.min.js"></script>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
colors: {
"primary": "#13eca4",
"primary-dark": "#0da670", // Added for contrast on light mode
"background-light": "#f8fcfa",
"background-dark": "#10221c",
"pearlescent": "#f0f7f5",
"silver-accent": "#e2e8f0",
"accent": "#ff6b00"
},
fontFamily: {
"display": ["Montserrat", "sans-serif"],
"sans": ["Montserrat", "sans-serif"],
"mono": ["JetBrains Mono", "Montserrat"],
"inter": ["Inter", "Montserrat"],
},
backgroundImage: {
'liquid-gradient': 'linear-gradient(135deg, #f8fcfa 0%, #e8f5f1 50%, #dcfce7 100%)',
'glass-gradient': 'linear-gradient(180deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.4) 100%)',
'aurora': 'linear-gradient(135deg, rgba(19,236,164,0.15) 0%, rgba(13,166,112,0.08) 50%, rgba(248,252,250,0) 100%)',
},
boxShadow: {
'glow': '0 0 20px rgba(19, 236, 164, 0.4)',
'bento': '0 20px 40px -15px rgba(0,0,0,0.05), 0 0 0 1px rgba(255,255,255,0.6)',
'bento-hover': '0 30px 60px -20px rgba(19,236,164,0.25), 0 0 0 1px rgba(19,236,164,0.5)',
'glass': '0 8px 32px 0 rgba(13, 166, 112, 0.1)',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0', transform: 'translateY(10px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
dash: {
'0%': { strokeDashoffset: '1000' },
'100%': { strokeDashoffset: '0' },
}
},
animation: {
'fade-in': 'fadeIn 0.5s ease-out forwards',
'dash-flow': 'dash 3s linear infinite',
}
},
},
}
</script>
</head>
<body class="bg-liquid-gradient text-background-dark font-sans antialiased overflow-x-hidden selection:bg-primary selection:text-white min-h-screen">
<!-- Three.js Canvas Container -->
<div id="canvas-container" class="fixed inset-0 z-0 pointer-events-none opacity-80"></div>
<div class="fixed inset-0 bg-gradient-to-t from-background-light via-background-light/40 to-transparent z-0 pointer-events-none"></div>
<main class="relative z-10 mx-auto ">
<!-- === Hero Section === -->
<section id="mod-hero" class="min-h-screen flex flex-col justify-center text-center">
<span class="text-primary font-mono text-sm tracking-[0.3em] uppercase mb-6 " data-aos="fade-down">
Smart Energy System
</span>
<h1 class="text-4xl md:text-[2.66rem] leading-tight tracking-tighter text-background-dark mb-8 drop-shadow-sm" data-aos="zoom-in">
INTEGRATED INDEPENDENT
<span class="text-primary">INTELLIGENT.</span>
</h1>
<p class="text-[1rem] text-background-dark/70 font-medium max-w-4xl mx-auto leading-relaxed md:text-center" data-aos="fade-up">
The Next Generation of Microgrid Solutions Empowering industrial parks and zero-carbon communities with seamless, green, and autonomous energy.
</p>
</section>
<!-- === 系统拓扑图模块 === -->
<section id="mod-topology" class="min-h-screen flex flex-col justify-center items-center text-center py-24 relative z-10 overflow-hidden">
<!-- 明亮网格背景 -->
<div class="absolute inset-0 z-0 opacity-[0.4] pointer-events-none hex-bg"></div>
<div class="absolute inset-0 z-0 opacity-[0.5] pointer-events-none" style="background-image: linear-gradient(rgba(19,236,164,0.2) 1px, transparent 1px), linear-gradient(90deg, rgba(19,236,164,0.2) 1px, transparent 1px); background-size: 60px 60px; transform: perspective(800px) rotateX(60deg) scale(2.5) translateY(-50px); transform-origin: top center;"></div>
<style>
.hex-bg { background-image: url("data:image/svg+xml,%3Csvg width='24' height='40' viewBox='0 0 24 40' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 10L12 3l12 7v14l-12 7-12-7V10z' stroke='rgba(13,166,112,0.1)' fill='none' fill-rule='evenodd'/%3E%3C/svg%3E"); }
.cyber-clip { clip-path: polygon(0 15px, 15px 0, 100% 0, 100% calc(100% - 15px), calc(100% - 15px) 100%, 0 100%); }
.cyber-hub { clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%); }
.tilt-card { transform-style: preserve-3d; will-change: transform; transform: perspective(1000px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale3d(1, 1, 1); transition: transform 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94), border-color 0.4s ease; }
.tilt-card.reset { transition: transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94), border-color 0.4s ease; }
.svg-circuit-line { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.flow-packet { stroke-dasharray: 15, 150; animation: dashFlow 3s linear infinite; }
@keyframes dashFlow { 0% { stroke-dashoffset: 165; } 100% { stroke-dashoffset: 0; } }
.layer-stats { opacity: 1; transition: opacity 0.3s ease, transform 0.3s ease; transform: translateY(0); }
.layer-text { opacity: 0; pointer-events: none; transition: opacity 0.3s ease, transform 0.3s ease; transform: translateY(10px); }
.tilt-card:hover .layer-stats { opacity: 0; transform: translateY(-10px); pointer-events: none; }
.tilt-card:hover .layer-text { opacity: 1; pointer-events: auto; transform: translateY(0); }
</style>
<div class="relative z-30 mb-20" data-aos="fade-down">
<h2 class="text-4xl md:text-[2.66rem] mb-4 uppercase tracking-[0.2em] text-background-dark flex items-center justify-center gap-4">
CORE ARCHITECTURE OF MICROGRID SYSTEM
</h2>
<div class="flex items-center justify-center gap-4 text-primary font-mono text-xs tracking-[0.4em] ">
<span class="w-8 h-[2px] bg-gradient-to-r from-transparent to-primary-dark"></span>
INTELLIGENT MICROGRID NETWORK
<span class="w-8 h-[2px] bg-gradient-to-l from-transparent to-primary-dark"></span>
</div>
</div>
<div class="relative w-full max-w-[1400px] mx-auto z-30 flex items-center justify-center px-10 lg:px-20 min-h-[500px]">
<div class="hidden lg:block absolute inset-0 z-0 pointer-events-none">
<svg class="w-full h-full drop-shadow-[0_0_8px_rgba(19,236,164,0.4)]" preserveAspectRatio="xMidYMid meet" viewBox="0 0 1400 500">
<path d="M 380 130 L 450 130 Q 480 130 480 160 L 480 250 L 550 250" class="svg-circuit-line stroke-primary/30" />
<path d="M 380 130 L 450 130 Q 480 130 480 160 L 480 250 L 550 250" class="svg-circuit-line stroke-primary-dark flow-packet" />
<path d="M 380 370 L 450 370 Q 480 370 480 340 L 480 250 L 550 250" class="svg-circuit-line stroke-accent/30" />
<path d="M 380 370 L 450 370 Q 480 370 480 340 L 480 250 L 550 250" class="svg-circuit-line stroke-accent flow-packet" style="animation-duration: 2.5s; animation-direction: reverse;" />
<path d="M 850 250 L 1020 250" class="svg-circuit-line stroke-primary/30" />
<path d="M 850 250 L 1020 250" class="svg-circuit-line stroke-primary-dark flow-packet" style="stroke-dasharray: 20, 100; animation-duration: 1.5s;" />
</svg>
</div>
<div class="grid grid-cols-1 lg:grid-cols-[minmax(300px,1.2fr)_auto_minmax(300px,1.2fr)] gap-8 lg:gap-16 w-full relative z-10 items-center">
<div class="flex flex-col gap-8 relative z-10">
<!-- Card 1 -->
<div class="tilt-card relative bg-white/70 backdrop-blur-xl border border-white p-8 cyber-clip cursor-pointer hover:border-primary/50 shadow-glass text-left w-full lg:w-[290px] ml-auto group">
<div class="flex items-start justify-between mb-6 relative z-10">
<div class="flex items-center gap-4">
<div class="w-12 h-12 bg-primary/10 rounded flex items-center justify-center border border-primary/30 text-primary group-hover:bg-primary group-hover:text-white transition-colors duration-300 shadow-sm">
<span class="material-symbols-outlined text-2xl">&#xec0f;</span>
</div>
<div>
<h3 class="text-xl text-background-dark tracking-wide">Power Gen</h3>
<div class="text-[10px] text-primary font-mono mt-1 ">NODE: GEN_01</div>
</div>
</div>
</div>
<div class="relative h-[80px] w-full">
<div class="layer-stats absolute inset-0 w-full grid grid-cols-2 gap-3 font-mono text-xs">
<div class="bg-primary/5 border border-primary/20 p-3 text-primary flex flex-col justify-center rounded-sm">
<span class="text-background-dark/50 text-[10px] mb-1 ">VOLTAGE OUT</span>
<span class="text-base ">400V DC</span>
</div>
<div class="bg-primary/5 border border-primary/20 p-3 text-primary flex flex-col justify-center rounded-sm">
<span class="text-background-dark/50 text-[10px] mb-1 ">STATUS</span>
<span class="text-base animate-pulse">STABLE</span>
</div>
</div>
<div class="layer-text absolute inset-0 w-full overflow-hidden">
<p class="decrypt-text text-[13px] text-background-dark/70 font-medium leading-relaxed" data-target="Harnessing renewable and conventional energy for consistent supply.">>_ Awaiting command...</p>
</div>
</div>
<div class="absolute bottom-0 right-0 w-6 h-6 border-b-2 border-r-2 border-primary/40 group-hover:border-primary-dark transition-colors m-1"></div>
</div>
<!-- Card 2 -->
<div class="tilt-card relative bg-white/70 backdrop-blur-xl border border-white p-8 cyber-clip cursor-pointer hover:border-accent/50 shadow-glass text-left w-full lg:w-[290px] ml-auto group">
<div class="flex items-start justify-between mb-6 relative z-10">
<div class="flex items-center gap-4">
<div class="w-12 h-12 bg-accent/10 rounded flex items-center justify-center border border-accent/30 text-accent group-hover:bg-accent group-hover:text-white transition-colors duration-300 shadow-sm">
<span class="material-symbols-outlined text-2xl">&#xe1a3;</span>
</div>
<div>
<h3 class="text-xl text-background-dark tracking-wide">Energy Storage</h3>
<div class="text-[10px] text-accent font-mono mt-1 ">NODE: BATT_X</div>
</div>
</div>
</div>
<div class="relative h-[80px] w-full">
<div class="layer-stats absolute inset-0 w-full grid grid-cols-2 gap-3 font-mono text-xs">
<div class="bg-accent/5 border border-accent/20 p-3 text-accent flex flex-col justify-center rounded-sm">
<span class="text-background-dark/50 text-[10px] mb-1 ">CAPACITY</span>
<span class="text-base ">500 kWh</span>
</div>
<div class="bg-accent/5 border border-accent/20 p-3 text-accent flex flex-col justify-center rounded-sm">
<span class="text-background-dark/50 text-[10px] mb-1 ">MODE</span>
<span class="text-base animate-pulse">CHARGE</span>
</div>
</div>
<div class="layer-text absolute inset-0 w-full overflow-hidden">
<p class="decrypt-text text-[13px] text-background-dark/70 font-medium leading-relaxed" data-target="Storing surplus electricity to stabilize the grid day and night.">>_ Interfacing...</p>
</div>
</div>
<div class="absolute bottom-0 right-0 w-6 h-6 border-b-2 border-r-2 border-accent/40 group-hover:border-accent transition-colors m-1"></div>
</div>
</div>
<!-- Central Hub -->
<div class="flex justify-center items-center relative z-20 mx-4 py-8 lg:py-0">
<div class="relative flex flex-col items-center justify-center p-12 bg-white/80 backdrop-blur-2xl border-2 border-white cyber-hub hover:border-primary/50 transition-all duration-500 w-[300px] h-[360px] shadow-glass group">
<div class="relative w-32 h-32 flex items-center justify-center mb-8">
<div class="absolute inset-0 rounded-full border border-dashed border-primary-dark/40 animate-[spin_10s_linear_infinite]"></div>
<div class="absolute inset-2 rounded-full border-t-4 border-primary/80 animate-[spin_3s_linear_infinite]"></div>
<div class="absolute inset-6 rounded-full bg-white border border-primary/30 flex items-center justify-center overflow-hidden z-10 group-hover:shadow-[0_0_20px_rgba(19,236,164,0.6)] transition-shadow duration-500">
<span class="material-symbols-outlined text-primary text-4xl">&#xe322;</span>
</div>
</div>
<div class="bg-primary/10 border border-primary/30 px-3 py-1 rounded-full text-primary font-mono text-[10px] mb-4 flex gap-2 items-center tracking-widest ">
<span class="w-2 h-2 bg-primary rounded-full animate-ping"></span> CONVERTER
</div>
<h3 class="text-2xl text-background-dark tracking-wide mb-2 z-10 group-hover:text-primary transition-colors">Power Conversion</h3>
<p class="text-[12px] text-background-dark/60 font-mono tracking-widest text-center mt-2 ">AC/DC ⇌ DC/AC<br>EFF: <span class="text-primary">99.1%</span></p>
</div>
</div>
<!-- Card 3 -->
<div class="flex flex-col justify-center relative z-10">
<div class="tilt-card relative bg-white/70 backdrop-blur-xl border border-white p-8 cyber-clip cursor-pointer hover:border-primary-dark/50 shadow-glass text-left w-full lg:w-[290px] group">
<div class="flex items-start justify-between mb-6 relative z-10">
<div class="flex items-center gap-4">
<div class="w-12 h-12 bg-primary-dark/10 rounded flex items-center justify-center border border-primary-dark/30 text-primary group-hover:bg-primary-dark group-hover:text-white transition-colors duration-300 shadow-sm">
<span class="material-symbols-outlined text-2xl">&#xe7ee;</span>
</div>
<div>
<h3 class="text-xl text-background-dark tracking-wide">Demand Mgt</h3>
<div class="text-[10px] text-background-dark/50 font-mono mt-1 ">NODE: LOAD_END</div>
</div>
</div>
</div>
<div class="relative h-[80px] w-full">
<div class="layer-stats absolute inset-0 w-full grid grid-cols-2 gap-3 font-mono text-xs">
<div class="bg-gray-100 border border-gray-200 p-3 text-background-dark flex flex-col justify-center rounded-sm">
<span class="text-background-dark/50 text-[10px] mb-1 ">REAL POWER</span>
<span class="text-base ">120 kW</span>
</div>
<div class="bg-gray-100 border border-gray-200 p-3 text-background-dark flex flex-col justify-center rounded-sm">
<span class="text-background-dark/50 text-[10px] mb-1 ">POWER FACTOR</span>
<span class="text-base ">0.98</span>
</div>
</div>
<div class="layer-text absolute inset-0 w-full overflow-hidden">
<p class="decrypt-text text-[13px] text-background-dark/70 font-medium leading-relaxed" data-target="Distributing power smartly to meet diverse load requirements.">>_ Connecting...</p>
</div>
</div>
<div class="absolute bottom-0 right-0 w-6 h-6 border-b-2 border-r-2 border-primary-dark/40 group-hover:border-primary-dark transition-colors m-1"></div>
</div>
</div>
</div>
</div>
</section>
<!-- Features Sections (Glassmorphism & Bright Theme) -->
<section id="mod-security" class="min-h-screen flex items-center">
<div class="max-w-xl bg-white/80 backdrop-blur-xl p-10 border-l-4 border-accent rounded-r-3xl shadow-glass">
<span class="material-symbols-outlined text-5xl text-accent mb-6">&#xe32a;</span>
<h2 class="text-4xl mb-4 text-background-dark">Safe &<br>Reliable</h2>
<p class="text-lg text-background-dark/70 leading-relaxed font-medium">Sustains island operation without disconnection, backed by multi-power redundancy to guarantee zero downtime for critical loads.</p>
</div>
</section>
<section id="mod-efficiency" class="min-h-screen flex items-center justify-end text-right">
<div class="max-w-xl bg-white/80 backdrop-blur-xl p-10 border-r-4 border-primary rounded-l-3xl shadow-glass">
<span class="material-symbols-outlined text-5xl text-primary mb-6">&#xf0cf;</span>
<h2 class="text-4xl mb-4 text-background-dark">Smart &<br>Efficient</h2>
<p class="text-lg text-background-dark/70 leading-relaxed font-medium">Intelligent optimization and dispatch enable peak shaving and valley filling, effectively reducing electricity costs and energy consumption.</p>
</div>
</section>
<section id="mod-netzero" class="min-h-screen flex items-center">
<div class="max-w-xl bg-white/80 backdrop-blur-xl p-10 border-l-4 border-primary-dark rounded-r-3xl shadow-glass">
<span class="material-symbols-outlined text-5xl text-primary mb-6">&#xea35;</span>
<h2 class="text-4xl mb-4 text-background-dark">Green &<br>Low-Carbon</h2>
<p class="text-lg text-background-dark/70 leading-relaxed font-medium">Efficiently absorbs renewable energy and reduces carbon emissions, facilitating the realization of dual-carbon goals.</p>
</div>
</section>
<section id="mod-autonomous" class="min-h-screen flex items-center justify-end text-right">
<div class="max-w-xl bg-white/80 backdrop-blur-xl p-10 border-r-4 border-accent rounded-l-3xl shadow-glass">
<span class="material-symbols-outlined text-5xl text-accent mb-6">&#xe97a;</span>
<h2 class="text-4xl mb-4 text-background-dark">Autonomous &<br>Controllable</h2>
<p class="text-lg text-background-dark/70 leading-relaxed font-medium">Operates independently of the external grid, significantly enhancing energy autonomy and risk resilience.</p>
</div>
</section>
<!-- === Scenarios === -->
<section id="mod-scenarios" class="min-h-[80vh] flex flex-col justify-center items-center text-center pb-20 relative z-10" style="perspective: 2000px;">
<h2 class="text-4xl md:text-[2.66rem] mb-12 uppercase tracking-widest text-background-dark mt-10 relative z-30">Applicable Scenarios</h2>
<div class="flex flex-wrap justify-center gap-4 font-mono text-sm max-w-4xl relative z-30 " id="scenario-buttons">
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">Industrial Parks</button>
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">Data Centers</button>
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">Commercial Complexes</button>
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">Hospitals & Schools</button>
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">Remote Regions</button>
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">Islands</button>
<button class="scenario-btn active-scenario px-6 py-2 bg-primary/10 border border-primary text-primary shadow-[0_4px_15px_rgba(19,236,164,0.3)] transition-all duration-300 rounded-full">Zero-Carbon Communities</button>
<button class="scenario-btn px-6 py-2 border border-primary/20 bg-white/80 hover:border-primary-dark hover:text-primary transition-all duration-300 rounded-full shadow-sm text-background-dark/70">New Energy Stations</button>
</div>
<div id="card-wrapper" class="relative mt-12 w-full max-w-5xl h-[450px] z-20" style="transform-style: preserve-3d;">
<div id="scenario-card" class="absolute inset-0 w-full h-full rounded-3xl overflow-hidden border-4 border-white shadow-2xl bg-white opacity-0" style="transform: translateZ(-500px) rotateX(20deg); pointer-events: none;">
<div class="absolute inset-0 z-0 overflow-hidden">
<img id="card-img" src="" class="w-full h-full object-cover opacity-90" alt="Scenario Image" />
</div>
<!-- Light theme inner gradient -->
<div class="absolute inset-0 bg-gradient-to-t from-white via-white/80 to-transparent z-10"></div>
<div class="absolute bottom-12 left-12 z-20 text-left">
<h3 id="card-title" class="text-4xl font-display text-background-dark mb-4 tracking-tighter"></h3>
<p id="card-desc" class="text-lg text-background-dark/80 max-w-2xl leading-relaxed font-medium"></p>
</div>
</div>
</div>
</section>
<!-- === Contact === -->
<section id="mod-contact" class="w-full py-24 relative z-10 overflow-hidden bg-white/50 border-t border-white shadow-[0_-10px_40px_rgba(13,166,112,0.05)]">
<div class="max-w-7xl mx-auto px-6">
<div class="flex items-center gap-4 mb-12" data-aos="fade-right">
<div class="h-[2px] w-12 bg-primary-dark"></div>
<span class="text-primary font-mono text-xs uppercase tracking-[0.4em] ">Get in Touch</span>
</div>
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-12">
<div data-aos="fade-up" data-aos-delay="100">
<h2 class="text-background-dark/50 text-sm font-mono uppercase tracking-widest mb-2 ">Microgrid Project Leader</h2>
<div class="flex items-baseline gap-6">
<span class="text-5xl tracking-tighter text-background-dark">Yan</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 w-full lg:max-w-2xl" data-aos="fade-left" data-aos-delay="200">
<a href="mailto:sheyanxin@nenghui.com" class="group relative p-6 bg-white border border-primary/20 rounded-2xl overflow-hidden transition-all duration-500 hover:border-primary hover:shadow-lg">
<div class="absolute inset-0 bg-gradient-to-r from-primary/5 to-transparent translate-x-[-100%] group-hover:translate-x-[0%] transition-transform duration-500"></div>
<div class="relative flex items-center gap-4">
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center text-primary">
<span class="material-symbols-outlined">&#xe158;</span>
</div>
<div>
<div class="text-background-dark/50 text-[10px] uppercase tracking-widest ">Send Email</div>
<div class="text-background-dark group-hover:text-primary transition-colors">sheyanxin@nenghui.com</div>
</div>
</div>
</a>
<a href="tel:8619120593729" class="group relative p-6 bg-white border border-primary/20 rounded-2xl overflow-hidden transition-all duration-500 hover:border-primary hover:shadow-lg">
<div class="absolute inset-0 bg-gradient-to-r from-primary/5 to-transparent translate-x-[-100%] group-hover:translate-x-[0%] transition-transform duration-500"></div>
<div class="relative flex items-center gap-4">
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center text-primary">
<span class="material-symbols-outlined">&#xe0b0;</span>
</div>
<div>
<div class="text-background-dark/50 text-[10px] uppercase tracking-widest ">Call Directly</div>
<div class="text-background-dark group-hover:text-primary transition-colors">+86 191 2059 3729</div>
</div>
</div>
</a>
</div>
</div>
</div>
</section>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
<!-- JavaScript Logic & Animations -->
<script>
AOS.init({ once: true });
gsap.registerPlugin(ScrollTrigger);
// --- 卡片倾斜与打字机特效 (保持不变) ---
document.addEventListener("DOMContentLoaded", () => {
const cards = document.querySelectorAll('.tilt-card');
cards.forEach(card => {
card.addEventListener('mousemove', e => {
card.classList.remove('reset');
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * -4;
const rotateY = ((x - centerX) / centerX) * 4;
card.style.setProperty('--rx', `${rotateX}deg`);
card.style.setProperty('--ry', `${rotateY}deg`);
});
card.addEventListener('mouseleave', () => {
card.classList.add('reset');
card.style.setProperty('--rx', `0deg`);
card.style.setProperty('--ry', `0deg`);
const decryptEl = card.querySelector('.decrypt-text');
if(decryptEl) {
decryptEl.dataset.isAnimating = "false";
decryptEl.innerHTML = `>_ Awaiting command...`;
}
});
card.addEventListener('mouseenter', () => {
const decryptEl = card.querySelector('.decrypt-text');
if(!decryptEl || decryptEl.dataset.isAnimating === "true") return;
decryptEl.dataset.isAnimating = "true";
const targetText = decryptEl.getAttribute('data-target');
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%&*';
let iteration = 0;
function decryptFrame() {
if(decryptEl.dataset.isAnimating === "false") return;
decryptEl.innerHTML = targetText.split("").map((letter, index) => {
if(index < iteration) return letter;
return chars[Math.floor(Math.random() * chars.length)];
}).join("") + `<span class="animate-pulse text-primary ml-1">_</span>`;
if(iteration < targetText.length) {
iteration += 1;
setTimeout(() => requestAnimationFrame(decryptFrame), 15);
} else {
decryptEl.dataset.isAnimating = "false";
decryptEl.innerHTML = targetText + `<span class="animate-pulse text-primary ml-1">_</span>`;
}
}
requestAnimationFrame(decryptFrame);
});
});
});
// --- Three.js 亮色主题粒子引擎 ---
const scene = new THREE.Scene();
// 增加雾化效果,让远处的粒子融入背景
scene.fog = new THREE.FogExp2(0xf8fcfa, 0.0015);
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 500;
function updateCameraFOV() {
camera.fov = window.innerWidth < 768 ? 75 : 55;
camera.updateProjectionMatrix();
}
updateCameraFOV();
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('canvas-container').appendChild(renderer.domElement);
const particleCount = window.innerWidth < 768 ? 9000 : 12000;
const geometry = new THREE.BufferGeometry();
const currentPositions = new Float32Array(particleCount * 3);
const renderPositions = new Float32Array(particleCount * 3);
const startPos = new Float32Array(particleCount * 3);
const targetPos = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// --- 核心改动:适合亮色背景的粒子颜色 ---
const colorPrimary = new THREE.Color('#09ab75'); // 深翠绿,保证在白底上清晰
const colorAccent = new THREE.Color('#64e8bc'); // 亮绿色用于点缀
const colorGray = new THREE.Color('#94a3b8'); // 蓝灰色替代原有的银白色
for (let i = 0; i < particleCount; i++) {
const mix = Math.random();
const color = colorPrimary.clone().lerp(colorAccent, mix * 0.5);
colors.set([color.r, color.g, color.b], i * 3);
}
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
// 形状生成器 (保持原有计算逻辑)
const shapesGen = {
text: () => {
const canvas = document.createElement('canvas');
canvas.width = 1200; canvas.height = 300;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#000'; ctx.fillRect(0, 0, 1200, 300);
ctx.font = 'bold 200px "Arial", sans-serif';
ctx.fillStyle = '#fff'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
ctx.fillText( window.innerWidth < 768 ? 'NH' :'NENGHUI', 600, 150);
const data = ctx.getImageData(0, 0, 1200, 300).data;
let points = [];
for (let y = 0; y < 300; y += 3) {
for (let x = 0; x < 1200; x += 3) {
if (data[(y * 1200 + x) * 4] > 128) {
points.push({ x: x - 600, y: -(y - 150), z: (Math.random() - 0.5) * 20 });
}
}
}
const arr = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const p = points[i % points.length];
arr.set([p.x, p.y, p.z], i * 3);
}
return arr;
},
nestedPolyhedron: () => {
const arr = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const r = i % 2 === 0 ? 100 : 50;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(Math.random() * 2 - 1);
let x = r * Math.sin(phi) * Math.cos(theta);
let y = r * Math.sin(phi) * Math.sin(theta);
let z = r * Math.cos(phi);
if (Math.abs(x) > r * 0.7) x = Math.sign(x) * r * 0.7;
arr.set([x, y, z], i * 3);
}
return arr;
},
symbioticLeaf: () => {
const arr = new Float32Array(particleCount * 3);
const leafParticles = Math.floor(particleCount * 0.85);
const carbonParticles = particleCount - leafParticles;
for (let i = 0; i < leafParticles; i++) {
const t = Math.random();
const y = t * 400 - 150;
const widthFactor = Math.sin(t * Math.PI) * (1.2 - 0.2 * t);
const maxWidth = 160;
let x, z;
const isVein = Math.random() < 0.4;
if (isVein) {
if (Math.random() < 0.3) {
x = (Math.random() - 0.5) * 4;
z = (Math.random() - 0.5) * 4;
} else {
const side = Math.random() > 0.5 ? 1 : -1;
const veinT = Math.floor(t * 10) / 10;
x = side * (t - veinT) * 300 + (side * veinT * 20);
x = THREE.MathUtils.clamp(x, -maxWidth * widthFactor, maxWidth * widthFactor);
z = (Math.random() - 0.5) * 10;
}
} else {
const rawX = (Math.random() - 0.5) * 2 * maxWidth * widthFactor;
x = Math.round(rawX / 15) * 15;
z = (Math.random() - 0.5) * 20;
}
const bend = Math.sin(t * Math.PI) * 30;
arr.set([x + bend, y, z], i * 3);
}
for (let i = 0; i < carbonParticles; i++) {
const idx = (leafParticles + i) * 3;
arr.set([
(Math.random() - 0.5) * 300,
-250 - Math.random() * 150,
(Math.random() - 0.5) * 60
], idx);
}
return arr;
},
concentricSphere: () => {
const arr = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const r = i % 3 === 0 ? 140 : (i % 3 === 1 ? 90 : 40);
const phi = Math.acos(-1 + Math.random() * 2);
const theta = Math.random() * Math.PI * 2;
arr.set([r * Math.sin(phi) * Math.cos(theta), r * Math.sin(phi) * Math.sin(theta), r * Math.cos(phi)], i * 3);
}
return arr;
},
barGraph: () => {
const arr = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const gridX = Math.floor(Math.random() * 8) - 4;
const gridZ = Math.floor(Math.random() * 8) - 4;
const height = (Math.sin(gridX) + Math.cos(gridZ) + 2) * 40 + 20;
arr.set([gridX * 40 + (Math.random() - 0.5) * 20, Math.random() * height - 100, gridZ * 40 + (Math.random() - 0.5) * 20], i * 3);
}
return arr;
},
shield: () => {
const arr = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
let x = (Math.random() - 0.5) * 200;
let y, z;
let topEdge = 100 + 15 * Math.cos(x * Math.PI / 100);
let bottomEdge = -120 + 220 * Math.pow(Math.abs(x) / 100, 2);
let t = Math.random();
if (Math.random() > 0.6) {
t = Math.random() > 0.5 ? Math.random() * 0.1 : 0.9 + Math.random() * 0.1;
}
y = bottomEdge + t * (topEdge - bottomEdge);
let maxZ = 30 * (1 - Math.pow(Math.abs(x) / 100, 2));
if (Math.abs(x) < 8 || Math.abs(y - 10) < 8) maxZ += 10;
z = (Math.random() - 0.5) * maxZ;
arr.set([x, y, z], i * 3);
}
return arr;
},
torusKnot: () => {
const arr = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const t = Math.random() * Math.PI * 2;
const p = 2; const q = 3;
const r = 50 * (2 + Math.cos(q * t));
const x = r * Math.cos(p * t);
const y = r * Math.sin(p * t);
const z = 50 * Math.sin(q * t);
const noise = 15;
arr.set([x + (Math.random() - 0.5) * noise, y + (Math.random() - 0.5) * noise, z + (Math.random() - 0.5) * noise], i * 3);
}
return arr;
},
networkNode: () => {
const arr = new Float32Array(particleCount * 3);
const nodes = [
{x: 0, y: 0, z: 0, r: 35},
{x: 120, y: 70, z: 40, r: 15},
{x: -110, y: -80, z: 20, r: 20},
{x: 90, y: -100, z: -40, r: 15},
{x: -100, y: 90, z: -30, r: 18},
{x: 0, y: 130, z: 10, r: 12},
{x: 0, y: -130, z: 0, r: 12}
];
for (let i = 0; i < particleCount; i++) {
const pType = Math.random();
if (pType < 0.5) {
const node = nodes[Math.floor(Math.random() * nodes.length)];
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
const r = node.r * (0.5 + 0.5 * Math.random());
arr.set([
node.x + r * Math.sin(phi) * Math.cos(theta),
node.y + r * Math.sin(phi) * Math.sin(theta),
node.z + r * Math.cos(phi)
], i * 3);
} else {
const targetNode = nodes[1 + Math.floor(Math.random() * (nodes.length - 1))];
const t = Math.random();
const noise = 3;
arr.set([
t * targetNode.x + (Math.random() - 0.5) * noise,
t * targetNode.y + (Math.random() - 0.5) * noise,
t * targetNode.z + (Math.random() - 0.5) * noise
], i * 3);
}
}
return arr;
}
};
const precalculatedShapes = {
text: shapesGen.text(),
nestedPolyhedron: shapesGen.nestedPolyhedron(),
symbioticLeaf: shapesGen.symbioticLeaf(),
concentricSphere: shapesGen.concentricSphere(),
barGraph: shapesGen.barGraph(),
shield: shapesGen.shield(),
torusKnot: shapesGen.torusKnot(),
networkNode: shapesGen.networkNode()
};
currentPositions.set(precalculatedShapes.text);
renderPositions.set(precalculatedShapes.text);
geometry.setAttribute('position', new THREE.BufferAttribute(renderPositions, 3));
// --- 核心改动:必须使用 NormalBlending 才能在白底上显示颜色 ---
const material = new THREE.PointsMaterial({
size: window.innerWidth < 768 ? 3.5 : 4.0,
vertexColors: true,
transparent: true,
opacity: 0.8,
blending: THREE.NormalBlending, // AdditiveBlending 会在白底上完全消失!
sizeAttenuation: true,
depthWrite: false
});
const particles = new THREE.Points(geometry, material);
scene.add(particles);
let time = 0;
let morphData = { progress: 0 };
let currentShapeKey = 'text';
let morphTween = null;
const rotationSpeed = { x: 0, y: 0 };
const waveConfig = { amplitude: 20 };
function morphTo(shapeKey) {
if (currentShapeKey === shapeKey) return;
currentShapeKey = shapeKey;
if (morphTween) morphTween.kill();
const colorAttribute = geometry.attributes.color;
const targetColors = new Float32Array(particleCount * 3);
const leafParticles = Math.floor(particleCount * 0.85);
for (let i = 0; i < particleCount; i++) {
let color;
if (shapeKey === 'symbioticLeaf') {
if (i < leafParticles) {
color = colorPrimary.clone().lerp(colorAccent, Math.random() * 0.2);
} else {
color = colorGray.clone();
}
} else {
color = colorPrimary.clone().lerp(colorAccent, Math.random() * 0.4);
}
targetColors.set([color.r, color.g, color.b], i * 3);
}
gsap.to(colorAttribute.array, {
endArray: targetColors,
duration: 1.5,
ease: "power2.inOut",
onUpdate: () => colorAttribute.needsUpdate = true
});
for (let i = 0; i < currentPositions.length; i++) {
startPos[i] = currentPositions[i];
}
targetPos.set(precalculatedShapes[shapeKey]);
morphData.progress = 0;
morphTween = gsap.to(morphData, {
progress: 1,
duration: 2.0,
ease: "power3.inOut",
onUpdate: () => {
for (let i = 0; i < particleCount * 3; i++) {
currentPositions[i] = startPos[i] + (targetPos[i] - startPos[i]) * morphData.progress;
}
}
});
if (shapeKey === 'text') {
gsap.to(rotationSpeed, { x: 0, y: 0, duration: 1.5 });
const targetX = Math.round(particles.rotation.x / (Math.PI * 2)) * (Math.PI * 2);
const targetY = Math.round(particles.rotation.y / (Math.PI * 2)) * (Math.PI * 2);
gsap.to(particles.rotation, { x: targetX, y: targetY, duration: 2.0 });
} else if (shapeKey === 'shield') {
gsap.to(rotationSpeed, { x: 0, y: 0.002, duration: 1.5 });
const targetX = Math.round(particles.rotation.x / (Math.PI * 2)) * (Math.PI * 2);
gsap.to(particles.rotation, { x: targetX, duration: 2.0 });
} else if (shapeKey === 'symbioticLeaf') {
gsap.to(rotationSpeed, { x: 0.0005, y: 0.001, duration: 1.5 });
} else if (shapeKey === 'barGraph') {
gsap.to(rotationSpeed, { x: 0, y: 0.002, duration: 1.5 });
const targetX = Math.round(particles.rotation.x / (Math.PI * 2)) * (Math.PI * 2);
gsap.to(particles.rotation, { x: targetX + 0.4, duration: 2.0 });
} else {
gsap.to(rotationSpeed, { x: 0.001, y: 0.002, duration: 2.0 });
}
gsap.to(waveConfig, {
duration: 2.0,
amplitude: (shapeKey === 'text') ? 20 : 0
});
}
function animate() {
requestAnimationFrame(animate);
time += 0.02;
const positions = geometry.attributes.position.array;
const colorsArray = geometry.attributes.color.array;
const leafParticles = Math.floor(particleCount * 0.85);
for (let i = 0; i < particleCount; i++) {
let idx = i * 3;
let baseX = currentPositions[idx];
let baseY = currentPositions[idx + 1];
let baseZ = currentPositions[idx + 2];
if (currentShapeKey === 'symbioticLeaf' ) {
if (i < leafParticles) {
if (i % 7 === 0 ) {
if (Math.abs(baseX) < 100) {
const angle = time * 3 + (baseY * 0.02);
const r = 10 * Math.sin(time * 0.5);
positions[idx] = baseX + r * Math.cos(angle);
positions[idx + 1] = baseY;
positions[idx + 2] = baseZ + r * Math.sin(angle);
}
} else {
positions[idx] = baseX + Math.sin(time + baseY * 0.1) * 2;
positions[idx + 1] = baseY;
positions[idx + 2] = baseZ;
}
}
} else if (waveConfig.amplitude > 0.01) {
const phase = baseX * 0.006 + time;
const waveY = Math.sin(phase) * (waveConfig.amplitude * 0.4);
const waveZ = Math.cos(phase * 0.8) * waveConfig.amplitude;
positions[idx] = baseX;
positions[idx + 1] = baseY + waveY;
positions[idx + 2] = baseZ + waveZ;
} else {
positions[idx] = baseX;
positions[idx + 1] = baseY;
positions[idx + 2] = baseZ;
}
if (currentShapeKey === 'symbioticLeaf') {
if (i >= leafParticles) {
let y = baseY + (time * 50) % 200;
let opacity = 1.0;
if (y > -150) {
opacity = THREE.MathUtils.lerp(1.0, 0.0, (y + 150) / 100);
}
if (y > -50) opacity = 0;
positions[idx + 1] = y;
colorsArray[idx] = colorGray.r * opacity;
colorsArray[idx + 1] = colorGray.g * opacity;
colorsArray[idx + 2] = colorGray.b * opacity;
}
}
}
geometry.attributes.position.needsUpdate = true;
if (currentShapeKey === 'symbioticLeaf') {
geometry.attributes.color.needsUpdate = true;
}
particles.rotation.x += rotationSpeed.x;
particles.rotation.y += rotationSpeed.y;
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
updateCameraFOV();
});
const shapeList = ['text', 'shield', 'concentricSphere', 'symbioticLeaf', 'torusKnot', 'networkNode', 'barGraph', 'nestedPolyhedron'];
const sections = ['#mod-hero', '#mod-security', '#mod-efficiency', '#mod-netzero', '#mod-autonomous', '#mod-topology', '#mod-scenarios', '#mod-contact'];
sections.forEach((id, idx) => {
ScrollTrigger.create({
trigger: id,
start: "top 55%",
end: "bottom 45%",
onEnter: () => morphTo(shapeList[idx]),
onEnterBack: () => morphTo(shapeList[idx])
});
});
</script>
<script>
// --- 场景卡片 3D 动画 ---
const scenarioData = {
"Industrial Parks": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-Industrial-parks.jpg", desc: "Optimize energy consumption and reduce operational costs for smart industrial zones with intelligent management." },
"Data Centers": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-data-center.jpg", desc: "Ensuring continuous mission-critical power supply for data centers with robust and resilient microgrids." },
"Commercial Complexes": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-Commercial-complexes.jpg", desc: "Optimize operational costs for commercial hubs through intelligent energy distribution and Peak Shaving." },
"Hospitals & Schools": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-Hospitals-schools.jpg", desc: "Ensuring uninterrupted power supply for critical medical services and secure educational campus environments." },
"Remote Regions": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-Remote-regions.jpg", desc: "Overcoming geographical barriers with advanced microgrid technology to illuminate the world's remotest corners." },
"Islands": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-Islands.jpg", desc: "Achieve reliable energy independence for remote islands through sustainable solar and storage systems." },
"Zero-Carbon Communities": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-Zero-carbon-communities.jpg", desc: "Building a sustainable future for modern living through intelligent and eco-friendly microgrid systems." },
"New Energy Stations": { img: "https://nenghui.com/wp-content/uploads/2026/03/icrogrid-New-energy-stations.jpg", desc: "Enhancing grid stability and renewable integration through advanced storage-based microgrid management systems." }
};
const scenarioButtons = document.querySelectorAll('.scenario-btn');
const scenarioCard = document.getElementById('scenario-card');
const cardImg = document.getElementById('card-img');
const cardTitle = document.getElementById('card-title');
const cardDesc = document.getElementById('card-desc');
let currentActiveBtn = document.querySelector('.active-scenario');
function updateCardContent(scenarioName) {
if(!scenarioData[scenarioName]) return;
const data = scenarioData[scenarioName];
const tl = gsap.timeline();
tl.to(scenarioCard, { rotationY: 90, opacity: 0, duration: 0.4, ease: "power2.in" })
.call(() => {
cardImg.src = data.img;
cardTitle.innerText = scenarioName;
cardDesc.innerText = data.desc;
})
.fromTo(scenarioCard,
{ rotationY: -90 },
{ rotationY: 0, opacity: 1, duration: 0.6, ease: "back.out(1.7)" }
);
}
scenarioButtons.forEach(btn => {
btn.addEventListener('click', () => {
if (btn === currentActiveBtn) return;
scenarioButtons.forEach(b => {
b.classList.remove('active-scenario', 'bg-primary/10', 'border-primary', 'text-primary', 'shadow-[0_4px_15px_rgba(19,236,164,0.3)]');
b.classList.add('border-primary/20', 'bg-white/80', 'text-background-dark/70');
});
btn.classList.add('active-scenario', 'bg-primary/10', 'border-primary', 'text-primary', 'shadow-[0_4px_15px_rgba(19,236,164,0.3)]');
currentActiveBtn = btn;
updateCardContent(btn.innerText.trim());
});
});
if (currentActiveBtn) {
const data = scenarioData[currentActiveBtn.innerText.trim()];
if (data) {
cardImg.src = data.img;
cardTitle.innerText = currentActiveBtn.innerText.trim();
cardDesc.innerText = data.desc;
}
}
ScrollTrigger.create({
trigger: '#mod-scenarios',
start: "top 60%",
end: "bottom top",
onEnter: () => {
gsap.fromTo(scenarioCard,
{ z: -1000, rotationX: 45, rotationY: -30, opacity: 0, scale: 0.5 },
{ z: 0, rotationX: 0, rotationY: 0, opacity: 1, scale: 1, duration: 1.5, ease: "expo.out" }
);
},
onLeaveBack: () => {
gsap.to(scenarioCard, {
z: -800, rotationX: 20, opacity: 0, scale: 0.7, duration: 0.8, ease: "power2.in"
});
},
onLeave: () => {
gsap.to(scenarioCard, {
y: -200, z: 200, rotationX: -20, opacity: 0, duration: 0.8, ease: "power2.in"
});
},
onEnterBack: () => {
gsap.to(scenarioCard, {
y: 0, z: 0, rotationX: 0, opacity: 1, scale: 1, duration: 1, ease: "back.out(1.2)"
});
}
});
</script>
</body>
</html>