diff --git a/package-lock.json b/package-lock.json index cc086d1..bb53b94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "framer-motion": "^12.38.0", "lucide-react": "^1.14.0", + "motion": "^12.0.6", "next": "16.2.5", "next-themes": "^0.4.6", "react": "19.2.4", @@ -1358,6 +1359,31 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/motion": { + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz", + "integrity": "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==", + "dependencies": { + "framer-motion": "^12.38.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/motion-dom": { "version": "12.38.0", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz", diff --git a/package.json b/package.json index 1fcb6dd..de02a36 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dependencies": { "framer-motion": "^12.38.0", "lucide-react": "^1.14.0", + "motion": "^12.0.6", "next": "16.2.5", "next-themes": "^0.4.6", "react": "19.2.4", diff --git a/src/app/[locale]/services/[slug]/service-detail-page.tsx b/src/app/[locale]/services/[slug]/service-detail-page.tsx index 42797c3..11b32c1 100644 --- a/src/app/[locale]/services/[slug]/service-detail-page.tsx +++ b/src/app/[locale]/services/[slug]/service-detail-page.tsx @@ -10,6 +10,9 @@ import { Cloud, Database, Gauge, + HandCoins, + MousePointerClick, + BarChart3, Headphones, Rocket, ShieldCheck, @@ -18,6 +21,7 @@ import { import { useI18n } from '../../../../i18n/provider'; import { serviceContent, type ServiceSlug } from './services.data'; import { useTheme } from 'next-themes'; +import { NetworkNexus } from '../../../components/network-nexus'; function HeroIcon({ name }: { name: 'shield' | 'wp' | 'speed' | 'support' }) { const className = @@ -82,12 +86,12 @@ export default function ServiceDetailPage({ slug }: { slug: ServiceSlug }) { const { locale } = useI18n(); const content = useMemo(() => serviceContent[slug][locale], [slug, locale]); const dir = locale === 'en' ? 'ltr' : 'rtl'; - const [openFaq, setOpenFaq] = useState(0); const { resolvedTheme } = useTheme(); const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); + const sectionMotion = { initial: { opacity: 0, y: 24 }, whileInView: { opacity: 1, y: 0 }, @@ -304,6 +308,9 @@ export default function ServiceDetailPage({ slug }: { slug: ServiceSlug }) { + {/* Network architecture (Core hub) */} + + {/* Plans */}
@@ -358,78 +365,74 @@ export default function ServiceDetailPage({ slug }: { slug: ServiceSlug }) {
- {/* FAQ + Why */} + {/* FAQ (new layout) */} -
-
-

{content.faqTitle}

-

{content.faqSubtitle}

+
+

+ {content.faqTitle} +

+

{content.faqSubtitle}

+
-
- {content.faqs.map((f, idx) => { - const isOpen = openFaq === idx; - return ( -
- - {isOpen ? ( -
- {f.a} -
- ) : null} +
+ {/* Timeline spine (desktop) */} +
+ +
+ {content.faqs.map((f, idx) => { + const Icon = [HandCoins, Gauge, ShieldCheck, MousePointerClick, BarChart3][idx % 5]; + const num = String(idx + 1).padStart(2, '0'); + const glow = ['#80c8f5', '#a78bfa', '#84e1bc', '#60a5fa', '#22d3ee'][idx % 5]; + + return ( +
+
+
+
+
+
+
+
{f.q}
+
{f.a}
+
- ); - })} -
-
-
-
-
-
-
+
+ {/* Dot on spine */} + + {/* Connector from dot to badge */} + -
-

{content.whyTitle}

-

{content.whyText}

-
    - {content.whyBullets.map((b) => ( -
  • - - - - {b} -
  • - ))} -
+
+
+
+ +
+
-
- -
-
-
+ + +
+ {num} +
+
+
+
+ ); + })}
diff --git a/src/app/components/network-nexus.tsx b/src/app/components/network-nexus.tsx new file mode 100644 index 0000000..2e23e8d --- /dev/null +++ b/src/app/components/network-nexus.tsx @@ -0,0 +1,295 @@ +import React, { useState } from 'react'; +import { motion, AnimatePresence } from 'motion/react'; +import { + Server, Cloud, Shield, HardDrive, Globe, Cpu, + Activity, Lock, Zap +} from 'lucide-react'; + +const SERVICES = [ + { + id: 'cloud', + title: 'هاست ابری اختصاصی', + desc: 'پایداری ۹۹.۹۹٪ با زیرساخت تمام ابری و هاردهای NVMe Enterprise', + icon: Cloud, + color: '#3b82f6', + x: 0, + y: -220, + stats: [ + { label: 'Uptime', value: '99.99%' }, + { label: 'Storage', value: 'NVMe SSD' } + ] + }, + { + id: 'dedicated', + title: 'سرور اختصاصی', + desc: 'بالاترین قدرت پردازشی با ��رورهای فیزیکی اختصاصی در بهترین دیتاسنترها', + icon: Server, + color: '#ef4444', + x: -300, + y: -100, + stats: [ + { label: 'CPU', value: 'Intel/AMD Dual' }, + { label: 'Network', value: '10 Gbps' } + ] + }, + { + id: 'vps', + title: 'سرور مجازی (VPS)', + desc: 'منابع کاملاً اختصاصی، کنترل کامل روت و تنوع سیستم‌عامل‌ها', + icon: HardDrive, + color: '#10b981', + x: 300, + y: -100, + stats: [ + { label: 'RAM', value: 'Up to 128GB' }, + { label: 'Root Access', value: 'Full' } + ] + }, + { + id: 'security', + title: 'امنیت و آنتی دیداس', + desc: 'محافظت هوشمند لایه ۷ در برابر بزرگترین حملات سایبری', + icon: Shield, + color: '#8b5cf6', + x: -220, + y: 160, + stats: [ + { label: 'DDoS Protection', value: 'Up to 2Tbps' }, + { label: 'WAF', value: 'Enabled' } + ] + }, + { + id: 'cdn', + title: 'شبکه توزیع محتوا (CDN)', + desc: 'بارگذاری در کسری از ثانیه با توزیع جهانی اطلاعات در سرورهای لبه', + icon: Globe, + color: '#f59e0b', + x: 220, + y: 160, + stats: [ + { label: 'Global PoPs', value: '150+' }, + { label: 'Latency', value: '< 20ms' } + ] + }, +]; + +export function NetworkNexus() { + const [activeService, setActiveService] = useState(null); + + return ( +
+ + {/* Background Grid Pattern */} +
+ +
+ + + زیرساخت ابری هوشمند و یکپارچه + +

+ معماری شبکـه و سرورهـا +

+

+ یک شبکه عظیم و به هم پیوسته از قدرتمندترین سرورهای جهان؛ پایداری بی‌نظیر، امنیت لایه‌ای و سرعت حداکثری برای کسب‌وکار شما. +

+
+ +
+ + {/* SVG Connections */} + + + + + + + + + {/* Central Glow Effect */} + + + {/* Static paths and animated data streams */} + {SERVICES.map((service) => { + // Cubic bezier curve path for a "cable" look + const pathD = `M 0 0 C ${service.x * 0.5} 0, ${service.x * 0.8} ${service.y * 0.8}, ${service.x} ${service.y}`; + const isActive = activeService === service.id; + const opacity = activeService ? (isActive ? 1 : 0.2) : 0.6; + + return ( + + {/* Background cable */} + + + {/* Glowing packet stream */} + + + ); + })} + + + {/* Central Hub (Core Data Center) */} +
+
+ + +
+ {[1,2,3].map(i => ( + + ))} +
+ CORE HUB +
+ + {/* Service Nodes */} + {SERVICES.map((service) => { + const isActive = activeService === service.id; + const isFaded = activeService && !isActive; + + return ( +
setActiveService(service.id)} + onMouseLeave={() => setActiveService(null)} + > +
+ {/* Icon Container */} +
+ {/* Hover gradient background inside the node */} +
+ +
+ + {/* Floating Info Card (Shows on Hover/Active) */} + + {isActive && ( + +

+ + {service.title} +

+

+ {service.desc} +

+ +
+ {service.stats.map((stat, idx) => ( +
+ {stat.label} + + {stat.value} + +
+ ))} +
+
+ )} +
+ + {/* Label (when not hovered) */} +
+ {service.title} +
+
+
+ ); + })} +
+ + {/* Decorative Server Rack Elements on the sides */} +
+ {[1,2,3,4,5].map(i => ( +
+
+
+
+ ))} +
+
+ {[1,2,3,4,5].map(i => ( +
+
+
+
+ ))} +
+ +
+ ); +} diff --git a/src/app/globals.css b/src/app/globals.css index c9232b4..eacb030 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -28,7 +28,7 @@ } } - @keyframes rb-fade-in { +@keyframes rb-fade-in { from { opacity: 0; } @@ -93,6 +93,110 @@ html.light .glass-rotating-border::after { filter: blur(16px); } +/* Animated gradient border (FAQ cards / hex badges) */ +@property --gb-angle { + syntax: ''; + inherits: false; + initial-value: 0deg; +} + +@keyframes gb-spin { + to { + --gb-angle: 360deg; + } +} + +.gradient-border-anim { + position: relative; +} + +.gradient-border-anim::before { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + padding: 1.5px; + pointer-events: none; + background: conic-gradient( + from var(--gb-angle), + rgba(255, 255, 255, 0) 0deg, + rgba(128, 200, 245, 0.55) 70deg, + rgba(167, 139, 250, 0.50) 145deg, + rgba(132, 225, 188, 0.50) 225deg, + rgba(34, 211, 238, 0.45) 305deg, + rgba(255, 255, 255, 0) 360deg + ); + -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + filter: drop-shadow(0 0 18px rgba(128, 200, 245, 0.10)); + animation: gb-spin 6.5s linear infinite; +} + +.gradient-border-anim::after { + content: ''; + position: absolute; + inset: -10px; + border-radius: inherit; + pointer-events: none; + background: conic-gradient( + from var(--gb-angle), + rgba(255, 255, 255, 0) 0deg, + rgba(128, 200, 245, 0.18) 90deg, + rgba(167, 139, 250, 0.14) 170deg, + rgba(132, 225, 188, 0.14) 250deg, + rgba(34, 211, 238, 0.12) 330deg, + rgba(255, 255, 255, 0) 360deg + ); + filter: blur(18px); + opacity: 0.65; + animation: gb-spin 6.5s linear infinite; +} + +html.light .gradient-border-anim::before { + filter: drop-shadow(0 0 14px rgba(2, 6, 23, 0.06)); +} + +.hex-clip { + clip-path: polygon(25% 6%, 75% 6%, 100% 50%, 75% 94%, 25% 94%, 0% 50%); +} + +.faq-title-bars { + display: inline-flex; + align-items: center; + gap: 14px; +} + +.faq-title-bars::before, +.faq-title-bars::after { + content: ''; + width: 44px; + height: 10px; + background: + linear-gradient(90deg, rgba(128,200,245,0) 0%, + rgba(128,200,245,0) 22%, + rgba(167,139,250,0.85) 22%, + rgba(167,139,250,0.85) 34%, + rgba(128,200,245,0) 34%, + rgba(128,200,245,0) 44%, + rgba(128,200,245,0.85) 44%, + rgba(128,200,245,0.85) 56%, + rgba(128,200,245,0) 56%, + rgba(128,200,245,0) 66%, + rgba(96,165,250,0.85) 66%, + rgba(96,165,250,0.85) 78%, + rgba(128,200,245,0) 78%, + rgba(128,200,245,0) 100%); + -webkit-mask: linear-gradient(135deg, #000 0 0); + mask: linear-gradient(135deg, #000 0 0); + transform: skewX(-18deg); + opacity: 0.9; +} + +.faq-title-bars::after { + transform: scaleX(-1) skewX(-18deg); +} + html.light .glass-rotating-border::before { background: conic-gradient( rgba(255, 255, 255, 0) 0deg 28deg,