Navbar restructure, footer redesign, cobe globe, approach section - Navbar: نبض صنعت (->/pulse), رسانه و رویداد dropdown (videocast/sessions/events), generalized NavDropdown; logo -> Frame 2095585206 (2).png - Footer: 3-col RTL layout (brand+socials / nav / contact+badges+newsletter), white logo, gold copyright bar - RadarTechSection: replace tech-frontier with «رویکرد ما» approach cards - MapEventsSection: swap static map for animated cobe WebGL globe (blue theme) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
This commit is contained in:
parent
121082abc9
commit
9043f62b27
|
|
@ -12,6 +12,7 @@
|
||||||
"@tanstack/react-query": "^5.100.14",
|
"@tanstack/react-query": "^5.100.14",
|
||||||
"apexcharts": "^5.13.0",
|
"apexcharts": "^5.13.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"cobe": "^2.0.1",
|
||||||
"dotted-map": "^3.1.0",
|
"dotted-map": "^3.1.0",
|
||||||
"framer-motion": "^12.40.0",
|
"framer-motion": "^12.40.0",
|
||||||
"gsap": "^3.15.0",
|
"gsap": "^3.15.0",
|
||||||
|
|
@ -1712,6 +1713,12 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cobe": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cobe/-/cobe-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-aaa6vcIlaC8C1SF50LDH0Anybo/EAXnrxqe+bwvr4+YUtZydqjeBjTTD7ziCCkbRrRGSns3I3F6cZsf3W+L+ag==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/convert-source-map": {
|
"node_modules/convert-source-map": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||||
|
|
@ -3318,6 +3325,17 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-sync-external-store": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vazir-font": {
|
"node_modules/vazir-font": {
|
||||||
"version": "30.1.0",
|
"version": "30.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/vazir-font/-/vazir-font-30.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/vazir-font/-/vazir-font-30.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
"@tanstack/react-query": "^5.100.14",
|
"@tanstack/react-query": "^5.100.14",
|
||||||
"apexcharts": "^5.13.0",
|
"apexcharts": "^5.13.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"cobe": "^2.0.1",
|
||||||
"dotted-map": "^3.1.0",
|
"dotted-map": "^3.1.0",
|
||||||
"framer-motion": "^12.40.0",
|
"framer-motion": "^12.40.0",
|
||||||
"gsap": "^3.15.0",
|
"gsap": "^3.15.0",
|
||||||
|
|
|
||||||
|
|
@ -1,68 +1,92 @@
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { Send, Share2, AtSign, MessageCircle, MapPin, Phone, Mail } from 'lucide-react'
|
||||||
|
|
||||||
function SocialIcon({ label, name, href }: { label: string; name: string; href: string }) {
|
const NAVY = '#071d49'
|
||||||
|
const GOLD = '#c9a227'
|
||||||
|
|
||||||
|
/* round social buttons (gold filled, like the screenshot) */
|
||||||
|
const SOCIALS = [
|
||||||
|
{ Icon: Send, name: 'تلگرام', href: '#' },
|
||||||
|
{ Icon: Share2, name: 'لینکدین', href: '#' },
|
||||||
|
{ Icon: AtSign, name: 'توییتر', href: '#' },
|
||||||
|
{ Icon: MessageCircle, name: 'آپارات', href: '#' },
|
||||||
|
]
|
||||||
|
|
||||||
|
function SocialIcon({ Icon, name, href }: { Icon: typeof Send; name: string; href: string }) {
|
||||||
const [hovered, setHovered] = useState(false)
|
const [hovered, setHovered] = useState(false)
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href={href} target="_blank" rel="noopener noreferrer" aria-label={name} title={name}
|
href={href} target="_blank" rel="noopener noreferrer" aria-label={name} title={name}
|
||||||
onMouseEnter={() => setHovered(true)}
|
onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
|
||||||
onMouseLeave={() => setHovered(false)}
|
|
||||||
style={{
|
style={{
|
||||||
width: 36, height: 36, borderRadius: 8,
|
width: 42, height: 42, borderRadius: '50%', flexShrink: 0,
|
||||||
border: `1px solid ${hovered ? 'rgba(255,255,255,0.4)' : 'rgba(255,255,255,0.15)'}`,
|
background: GOLD, color: NAVY, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
background: hovered ? 'rgba(255,255,255,0.08)' : 'transparent',
|
textDecoration: 'none', cursor: 'pointer', transition: 'transform 150ms, opacity 150ms',
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
transform: hovered ? 'translateY(-3px)' : 'none', opacity: hovered ? 0.9 : 1,
|
||||||
fontSize: 11, fontWeight: 700, textDecoration: 'none',
|
|
||||||
color: hovered ? '#fff' : 'rgba(255,255,255,0.5)',
|
|
||||||
cursor: 'pointer', transition: 'all 150ms', flexShrink: 0,
|
|
||||||
}}
|
}}
|
||||||
>{label}</a>
|
>
|
||||||
|
<Icon size={19} strokeWidth={2} />
|
||||||
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const SOCIALS = [
|
/* center nav — the navbar items */
|
||||||
{ label: 'in', name: 'لینکدین', href: '#' },
|
const NAV_LINKS = [
|
||||||
{ label: 'X', name: 'توییتر', href: '#' },
|
{ label: 'رادار آینده', href: '/radar' },
|
||||||
{ label: 'آپ', name: 'آپارات', href: '#' },
|
{ label: 'آمار و داده', href: '#' },
|
||||||
{ label: 'tg', name: 'تلگرام', href: '#' },
|
{ label: 'چندرسانهای', href: '#' },
|
||||||
|
{ label: 'در یک نگاه', href: '/at-a-glance' },
|
||||||
|
{ label: 'شبکه خبرگان', href: '#' },
|
||||||
|
{ label: 'درباره ما', href: '#' },
|
||||||
|
]
|
||||||
|
|
||||||
|
function NavItem({ href, label }: { href: string; label: string }) {
|
||||||
|
const [hovered, setHovered] = useState(false)
|
||||||
|
return (
|
||||||
|
<a href={href}
|
||||||
|
onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
|
||||||
|
style={{
|
||||||
|
display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0',
|
||||||
|
fontSize: 13.5, color: hovered ? '#fff' : 'rgba(255,255,255,0.6)',
|
||||||
|
textDecoration: 'none', transition: 'color 150ms', flexDirection: 'row-reverse', justifyContent: 'flex-end',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
<span style={{ width: 4, height: 4, borderRadius: '50%', background: GOLD, flexShrink: 0 }} />
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* contact rows */
|
||||||
|
const CONTACT = [
|
||||||
|
{ Icon: MapPin, label: 'نشانی:', value: 'اصفهان، خیابان سعادتآباد' },
|
||||||
|
{ Icon: Phone, label: 'شماره تماس:', value: '۰۳۱ - ۳۸۸۸۴۵۳۹', ltr: true },
|
||||||
|
{ Icon: Mail, label: 'پست الکترونیک:', value: 'info@steelfutures.com', ltr: true, accent: true },
|
||||||
]
|
]
|
||||||
|
|
||||||
function NewsletterBox() {
|
function NewsletterBox() {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const [done, setDone] = useState(false)
|
const [done, setDone] = useState(false)
|
||||||
return (
|
return (
|
||||||
<div style={{ marginTop: 8 }}>
|
<div>
|
||||||
<div style={{
|
<div style={{ fontSize: 13, fontWeight: 700, color: '#fff', marginBottom: 12 }}>عضویت در خبرنامه اندیشکده</div>
|
||||||
fontSize: 11, fontWeight: 700,
|
<div style={{ display: 'flex', border: '1px solid rgba(255,255,255,0.18)', borderRadius: 8, overflow: 'hidden', background: 'rgba(255,255,255,0.05)' }}>
|
||||||
color: 'rgba(255,255,255,0.4)',
|
|
||||||
letterSpacing: '2px', textTransform: 'uppercase',
|
|
||||||
marginBottom: 12,
|
|
||||||
}}>
|
|
||||||
خبرنامه فولاد آینده
|
|
||||||
</div>
|
|
||||||
<div style={{ display: 'flex', border: '1px solid rgba(255,255,255,0.18)' }}>
|
|
||||||
<input
|
<input
|
||||||
type="email" value={email}
|
type="email" value={email} onChange={e => setEmail(e.target.value)}
|
||||||
onChange={e => setEmail(e.target.value)}
|
placeholder="ایمیل خود را وارد کنید..." disabled={done}
|
||||||
placeholder="ایمیل خود را وارد کنید..."
|
|
||||||
disabled={done}
|
|
||||||
style={{
|
style={{
|
||||||
flex: 1, border: 'none', padding: '10px 14px', fontSize: 13,
|
flex: 1, border: 'none', padding: '11px 14px', fontSize: 13, fontFamily: 'inherit',
|
||||||
fontFamily: 'inherit', background: 'rgba(255,255,255,0.07)',
|
background: 'transparent', color: '#fff', outline: 'none', direction: 'rtl', minWidth: 0,
|
||||||
color: '#fff', outline: 'none', direction: 'rtl', minWidth: 0,
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() => { if (email) setDone(true) }}
|
onClick={() => { if (email) setDone(true) }} disabled={done}
|
||||||
disabled={done}
|
|
||||||
style={{
|
style={{
|
||||||
background: done ? 'rgba(255,255,255,0.15)' : '#00AEEF',
|
background: GOLD, color: NAVY, border: 'none', padding: '11px 22px',
|
||||||
color: '#fff', border: 'none', padding: '10px 16px',
|
fontSize: 12, fontWeight: 800, fontFamily: 'inherit', cursor: done ? 'default' : 'pointer', whiteSpace: 'nowrap', flexShrink: 0,
|
||||||
fontSize: 12, fontWeight: 700, fontFamily: 'inherit',
|
|
||||||
cursor: done ? 'default' : 'pointer', whiteSpace: 'nowrap', flexShrink: 0,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{done ? '✓ ثبت شد' : 'عضویت'}
|
{done ? '✓ ثبت شد' : 'ثبت'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -71,53 +95,72 @@ function NewsletterBox() {
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return (
|
return (
|
||||||
<footer dir="rtl" style={{ backgroundColor: 'var(--ink)', color: 'rgba(255,255,255,0.6)' }}>
|
<footer dir="rtl" style={{ backgroundColor: NAVY, color: 'rgba(255,255,255,0.6)' }}>
|
||||||
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '60px 48px 52px' }}
|
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '60px 48px 48px' }} className="max-md:!px-6 max-md:!py-10">
|
||||||
className="max-md:!px-6 max-md:!py-10">
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 max-md:grid-cols-1 gap-12 max-md:gap-8">
|
<div className="grid grid-cols-[1.3fr_0.8fr_1.2fr] max-lg:grid-cols-2 max-md:grid-cols-1 gap-12 max-md:gap-10">
|
||||||
|
|
||||||
|
{/* ── BRAND (right side in RTL) ── */}
|
||||||
|
<div style={{ textAlign: 'right' }}>
|
||||||
|
<img src="/logo%20white.png" alt="اندیشکده فولاد آینده" style={{ height: 64, width: 'auto', display: 'inline-block', marginBottom: 12 }} />
|
||||||
|
<div style={{ fontSize: 22, fontWeight: 900, color: '#fff', lineHeight: 1.3, marginBottom: 4 }}>اندیشکده فولاد آینده</div>
|
||||||
|
<div style={{ fontSize: 10, letterSpacing: 2, color: 'rgba(255,255,255,0.35)', textTransform: 'uppercase', marginBottom: 18 }}>The Steel Futures Institute</div>
|
||||||
|
|
||||||
{/* Brand */}
|
|
||||||
<div>
|
|
||||||
<div style={{ fontSize: 24, fontWeight: 900, color: '#fff', lineHeight: 1.3, marginBottom: 6 }}>
|
|
||||||
اندیشکده فولاد آینده
|
|
||||||
</div>
|
|
||||||
<div style={{
|
|
||||||
fontSize: 10, letterSpacing: 2,
|
|
||||||
color: 'rgba(255,255,255,0.3)',
|
|
||||||
textTransform: 'uppercase',
|
|
||||||
marginBottom: 18,
|
|
||||||
lineHeight: 1.6,
|
|
||||||
}}>
|
|
||||||
The Steel Futures Institute
|
|
||||||
</div>
|
|
||||||
<p style={{
|
<p style={{
|
||||||
fontSize: 14, lineHeight: 2, color: 'rgba(255,255,255,0.6)',
|
fontSize: 13, lineHeight: 2, color: 'rgba(255,255,255,0.62)',
|
||||||
maxWidth: 460, margin: '0 0 26px',
|
border: '1px solid rgba(255,255,255,0.15)', borderRadius: 14, padding: '16px 18px', margin: '0 0 26px',
|
||||||
}}>
|
}}>
|
||||||
فضایی همدلانه برای اندیشیدن به فردای صنعت؛ جایی که دانش، آیندهپژوهی و نوآوری به بینشهایی برای توسعه صنعتی تبدیل میشوند.
|
فضایی همدلانه برای اندیشیدن به فردای صنعت؛ جایی که دانش، آیندهپژوهی و نوآوری به بینشهایی برای توسعه صنعتی تبدیل میشوند.
|
||||||
</p>
|
</p>
|
||||||
<div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
|
|
||||||
{SOCIALS.map(s => (
|
<div style={{ fontSize: 13, fontWeight: 700, color: '#fff', marginBottom: 14 }}>ما را در شبکههای اجتماعی دنبال کنید.</div>
|
||||||
<SocialIcon key={s.name} label={s.label} name={s.name} href={s.href} />
|
<div style={{ display: 'flex', gap: 12, justifyContent: 'flex-start' }}>
|
||||||
|
{SOCIALS.map((s) => (
|
||||||
|
<SocialIcon key={s.name} Icon={s.Icon} name={s.name} href={s.href} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Newsletter */}
|
{/* ── NAV (center) ── */}
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'flex-start' }}>
|
<nav aria-label="پیوندهای پایین" style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
{NAV_LINKS.map((l) => (
|
||||||
|
<NavItem key={l.label} href={l.href} label={l.label} />
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* ── CONTACT + badges + newsletter (left side in RTL) ── */}
|
||||||
|
<div>
|
||||||
|
<div style={{ fontSize: 14, fontWeight: 800, color: '#fff', marginBottom: 18 }}>اطلاعات تماس</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 26 }}>
|
||||||
|
{CONTACT.map((c) => (
|
||||||
|
<div key={c.label} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13 }}>
|
||||||
|
<c.Icon size={15} color={GOLD} style={{ flexShrink: 0 }} />
|
||||||
|
<span style={{ color: 'rgba(255,255,255,0.45)' }}>{c.label}</span>
|
||||||
|
<span style={{ color: c.accent ? GOLD : 'rgba(255,255,255,0.75)', direction: c.ltr ? 'ltr' : 'rtl' }}>{c.value}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* certification badges (placeholders — swap for real images) */}
|
||||||
|
<div style={{ display: 'flex', gap: 12, marginBottom: 26 }}>
|
||||||
|
{[0, 1, 2].map((i) => (
|
||||||
|
<div key={i} style={{ width: 66, height: 66, borderRadius: 10, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
||||||
|
<span style={{ fontSize: 9, color: 'rgba(7,29,73,0.4)', fontWeight: 700 }}>نشان</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
<NewsletterBox />
|
<NewsletterBox />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ borderTop: '1px solid rgba(255,255,255,0.08)' }}>
|
{/* copyright bar */}
|
||||||
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '20px 48px', textAlign: 'center', fontSize: 13, color: 'rgba(255,255,255,0.7)', lineHeight: 1.8 }}
|
<div style={{ background: GOLD, color: NAVY }}>
|
||||||
className="max-md:!px-6">
|
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '14px 48px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', fontSize: 12, fontWeight: 700 }}
|
||||||
<div>تمامی حقوق این وب سایت محفوظ و متعلق به شرکت فولاد مبارکه است.</div>
|
className="max-md:!px-6 max-md:!justify-center max-md:!text-center">
|
||||||
<div style={{ color: 'rgba(255,255,255,0.4)', marginTop: 4, fontSize: 12 }}>
|
<span>تمامی حقوق مادی و معنوی این وبسایت برای شرکت فولاد مبارکه اصفهان محفوظ میباشد.</span>
|
||||||
با افتخار قدرت گرفته از دیدوان؛ چشم همیشه باز مدیران
|
<span style={{ opacity: 0.8 }}>طراحی شده توسط شرکت دانشبنیان نواندیشان آتی نگار فرتاک</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react'
|
import React, { useState, useEffect, useRef } from 'react'
|
||||||
import type { CSSProperties } from 'react'
|
import type { CSSProperties } from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { Search, Menu, X, ChevronDown, Radar, Leaf, Globe, Cpu, BarChart3 } from 'lucide-react'
|
import { Search, Menu, X, ChevronDown, Radar, Leaf, Globe, Cpu, BarChart3, Video, Mic, CalendarDays } from 'lucide-react'
|
||||||
import { motion, AnimatePresence } from 'framer-motion'
|
import { motion, AnimatePresence } from 'framer-motion'
|
||||||
import { useLang } from '@/context/LangContext'
|
import { useLang } from '@/context/LangContext'
|
||||||
|
|
||||||
|
|
@ -17,8 +17,10 @@ const T = {
|
||||||
red: 'var(--red)',
|
red: 'var(--red)',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
type Section = { fa: string; en: string; to: string; Icon: React.ElementType }
|
||||||
|
|
||||||
/* ─── dropdown sections under رادار آینده ─── */
|
/* ─── dropdown sections under رادار آینده ─── */
|
||||||
const SECTIONS: { fa: string; en: string; to: string; Icon: React.ElementType }[] = [
|
const SECTIONS: Section[] = [
|
||||||
{ fa: 'آیندهپژوهی و رصد هوشمند', en: 'Foresight & Intelligence', to: '/radar', Icon: Radar },
|
{ fa: 'آیندهپژوهی و رصد هوشمند', en: 'Foresight & Intelligence', to: '/radar', Icon: Radar },
|
||||||
{ fa: 'پایداری و فولاد سبز', en: 'Sustainability & Green Steel', to: '/sustainability', Icon: Leaf },
|
{ fa: 'پایداری و فولاد سبز', en: 'Sustainability & Green Steel', to: '/sustainability', Icon: Leaf },
|
||||||
{ fa: 'ژئوپلیتیک و اقتصاد جهانی', en: 'Geopolitics & Global Economy', to: '/geopolitics', Icon: Globe },
|
{ fa: 'ژئوپلیتیک و اقتصاد جهانی', en: 'Geopolitics & Global Economy', to: '/geopolitics', Icon: Globe },
|
||||||
|
|
@ -26,11 +28,19 @@ const SECTIONS: { fa: string; en: string; to: string; Icon: React.ElementType }[
|
||||||
{ fa: 'بازار و زنجیره فولاد', en: 'Market & Steel Chain', to: '/pulse', Icon: BarChart3 },
|
{ fa: 'بازار و زنجیره فولاد', en: 'Market & Steel Chain', to: '/pulse', Icon: BarChart3 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/* ─── dropdown sections under رسانه و رویداد ─── */
|
||||||
|
const MEDIA: Section[] = [
|
||||||
|
{ fa: 'ویدیوکست و پادکست', en: 'Videocast & Podcast', to: '#', Icon: Video },
|
||||||
|
{ fa: 'نشستهای تخصصی', en: 'Expert Sessions', to: '#', Icon: Mic },
|
||||||
|
{ fa: 'رویدادها', en: 'Events', to: '#', Icon: CalendarDays },
|
||||||
|
]
|
||||||
|
|
||||||
/* ─── top-level nav items ─── */
|
/* ─── top-level nav items ─── */
|
||||||
const TOP_NAV: { fa: string; en: string; to?: string; dropdown?: boolean }[] = [
|
type TopNav = { fa: string; en: string; to?: string; dropdown?: 'radar' | 'media' }
|
||||||
{ fa: 'رادار آینده', en: 'Radar', dropdown: true },
|
const TOP_NAV: TopNav[] = [
|
||||||
{ fa: 'تحلیلهای استراتژیک', en: 'Strategic Analysis', to: '#' },
|
{ fa: 'رادار آینده', en: 'Radar', dropdown: 'radar' },
|
||||||
{ fa: 'چندرسانهای', en: 'Multimedia', to: '#' },
|
{ fa: 'نبض صنعت', en: 'Industry Pulse', to: '/pulse' },
|
||||||
|
{ fa: 'رسانه و رویداد', en: 'Media & Events', dropdown: 'media' },
|
||||||
{ fa: 'در یک نگاه', en: 'At a Glance', to: '/at-a-glance' },
|
{ fa: 'در یک نگاه', en: 'At a Glance', to: '/at-a-glance' },
|
||||||
{ fa: 'شبکه خبرگان', en: 'Expert Network', to: '#' },
|
{ fa: 'شبکه خبرگان', en: 'Expert Network', to: '#' },
|
||||||
{ fa: 'درباره ما', en: 'About', to: '#' },
|
{ fa: 'درباره ما', en: 'About', to: '#' },
|
||||||
|
|
@ -43,8 +53,8 @@ const META_LEFT: { fa: string; en: string }[] = [
|
||||||
{ fa: 'رسانه', en: 'Press' },
|
{ fa: 'رسانه', en: 'Press' },
|
||||||
]
|
]
|
||||||
|
|
||||||
/* ─── رادار آینده dropdown card ─── */
|
/* ─── generic nav dropdown card ─── */
|
||||||
function RadarDropdown({ lang }: { lang: 'fa' | 'en' }) {
|
function NavDropdown({ lang, label, sections }: { lang: 'fa' | 'en'; label: string; sections: Section[] }) {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
|
@ -70,7 +80,7 @@ function RadarDropdown({ lang }: { lang: 'fa' | 'en' }) {
|
||||||
borderBottom: open ? `2px solid ${T.red}` : '2px solid transparent',
|
borderBottom: open ? `2px solid ${T.red}` : '2px solid transparent',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{lang === 'fa' ? 'رادار آینده' : 'Radar'}
|
{label}
|
||||||
<ChevronDown size={12} style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 200ms' }} />
|
<ChevronDown size={12} style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 200ms' }} />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
@ -92,9 +102,9 @@ function RadarDropdown({ lang }: { lang: 'fa' | 'en' }) {
|
||||||
direction: lang === 'fa' ? 'rtl' : 'ltr',
|
direction: lang === 'fa' ? 'rtl' : 'ltr',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{SECTIONS.map((item, i) => (
|
{sections.map((item, i) => (
|
||||||
<NavLink
|
<NavLink
|
||||||
key={item.to}
|
key={i}
|
||||||
to={item.to}
|
to={item.to}
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
style={({ isActive }: { isActive: boolean }): CSSProperties => ({
|
style={({ isActive }: { isActive: boolean }): CSSProperties => ({
|
||||||
|
|
@ -102,7 +112,7 @@ function RadarDropdown({ lang }: { lang: 'fa' | 'en' }) {
|
||||||
padding: '15px 20px', textDecoration: 'none',
|
padding: '15px 20px', textDecoration: 'none',
|
||||||
color: isActive ? T.red : '#3d3d3d',
|
color: isActive ? T.red : '#3d3d3d',
|
||||||
background: isActive ? 'rgba(155,28,28,0.04)' : 'transparent',
|
background: isActive ? 'rgba(155,28,28,0.04)' : 'transparent',
|
||||||
borderBottom: i < SECTIONS.length - 1 ? '1px solid rgba(7,29,73,0.07)' : 'none',
|
borderBottom: i < sections.length - 1 ? '1px solid rgba(7,29,73,0.07)' : 'none',
|
||||||
transition: 'background 100ms', fontSize: 14, fontWeight: 600,
|
transition: 'background 100ms', fontSize: 14, fontWeight: 600,
|
||||||
})}
|
})}
|
||||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = 'rgba(7,29,73,0.03)' }}
|
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = 'rgba(7,29,73,0.03)' }}
|
||||||
|
|
@ -219,7 +229,7 @@ export default function Header() {
|
||||||
to="/"
|
to="/"
|
||||||
style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 12, textDecoration: 'none', flexShrink: 0, lineHeight: 1 }}
|
style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 12, textDecoration: 'none', flexShrink: 0, lineHeight: 1 }}
|
||||||
>
|
>
|
||||||
<img src="/logo.png?v=2" alt="" aria-hidden="true"
|
<img src="/Frame%202095585206%20(2).png" alt="" aria-hidden="true"
|
||||||
style={{ height: 52, width: 'auto', display: 'block', flexShrink: 0, marginTop: -8 }}
|
style={{ height: 52, width: 'auto', display: 'block', flexShrink: 0, marginTop: -8 }}
|
||||||
className="max-md:h-[40px]"
|
className="max-md:h-[40px]"
|
||||||
/>
|
/>
|
||||||
|
|
@ -242,7 +252,7 @@ export default function Header() {
|
||||||
>
|
>
|
||||||
{TOP_NAV.map((item) =>
|
{TOP_NAV.map((item) =>
|
||||||
item.dropdown
|
item.dropdown
|
||||||
? <RadarDropdown key="radar" lang={lang} />
|
? <NavDropdown key={item.fa} lang={lang} label={lang === 'fa' ? item.fa : item.en} sections={item.dropdown === 'radar' ? SECTIONS : MEDIA} />
|
||||||
: <PlainNavItem key={item.fa} label={lang === 'fa' ? item.fa : item.en} to={item.to!} />
|
: <PlainNavItem key={item.fa} label={lang === 'fa' ? item.fa : item.en} to={item.to!} />
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { useEffect, useRef } from 'react'
|
||||||
|
import createGlobe from 'cobe'
|
||||||
|
|
||||||
|
/* Lightweight WebGL globe (cobe) — auto-rotating, blue dotted landmasses with
|
||||||
|
glowing cyan markers, matching the reference. */
|
||||||
|
export default function Globe({ size = 600 }: { size?: number }) {
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const canvas = canvasRef.current
|
||||||
|
if (!canvas) return
|
||||||
|
|
||||||
|
let phi = 0
|
||||||
|
let raf = 0
|
||||||
|
let width = canvas.offsetWidth
|
||||||
|
const onResize = () => { width = canvas.offsetWidth }
|
||||||
|
window.addEventListener('resize', onResize)
|
||||||
|
|
||||||
|
const globe = createGlobe(canvas, {
|
||||||
|
devicePixelRatio: 2,
|
||||||
|
width: width * 2,
|
||||||
|
height: width * 2,
|
||||||
|
phi: 0,
|
||||||
|
theta: 0.25,
|
||||||
|
dark: 1,
|
||||||
|
diffuse: 1.4,
|
||||||
|
mapSamples: 18000,
|
||||||
|
mapBrightness: 7,
|
||||||
|
baseColor: [0.06, 0.13, 0.4], // deep blue landmass dots
|
||||||
|
markerColor: [0.22, 0.68, 1], // glowing cyan/blue markers
|
||||||
|
glowColor: [0.18, 0.36, 0.85], // blue atmosphere glow
|
||||||
|
markers: [
|
||||||
|
{ location: [35.69, 51.39], size: 0.10 }, // Tehran
|
||||||
|
{ location: [31.23, 121.47], size: 0.09 }, // Shanghai / Dalian
|
||||||
|
{ location: [33.31, 44.36], size: 0.06 }, // Baghdad / Basra
|
||||||
|
{ location: [51.92, 4.47], size: 0.06 }, // Rotterdam
|
||||||
|
{ location: [25.20, 55.27], size: 0.06 }, // Dubai
|
||||||
|
{ location: [41.01, 28.97], size: 0.06 }, // Istanbul
|
||||||
|
{ location: [19.07, 72.88], size: 0.07 }, // Mumbai
|
||||||
|
{ location: [-23.55, -46.63], size: 0.07 },// São Paulo
|
||||||
|
{ location: [55.75, 37.62], size: 0.06 }, // Moscow
|
||||||
|
{ location: [37.56, 126.97], size: 0.06 }, // Seoul
|
||||||
|
{ location: [-1.29, 36.82], size: 0.06 }, // Nairobi
|
||||||
|
{ location: [40.71, -74.0], size: 0.07 }, // New York
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
// cobe v2 drives the loop externally via globe.update()
|
||||||
|
const tick = () => {
|
||||||
|
phi += 0.0045
|
||||||
|
globe.update({ phi, width: width * 2, height: width * 2 })
|
||||||
|
raf = requestAnimationFrame(tick)
|
||||||
|
}
|
||||||
|
raf = requestAnimationFrame(tick)
|
||||||
|
requestAnimationFrame(() => { canvas.style.opacity = '1' })
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(raf)
|
||||||
|
globe.destroy()
|
||||||
|
window.removeEventListener('resize', onResize)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%', maxWidth: size, aspectRatio: '1', margin: '0 auto', position: 'relative' }}>
|
||||||
|
<canvas
|
||||||
|
ref={canvasRef}
|
||||||
|
style={{ width: '100%', height: '100%', contain: 'layout paint size', opacity: 0, transition: 'opacity 1s ease' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,9 @@
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { motion } from 'framer-motion'
|
import { motion } from 'framer-motion'
|
||||||
import WorldMap from '@/components/ui/world-map'
|
import Globe from '@/components/ui/globe'
|
||||||
import { events } from '@/data/events'
|
import { events } from '@/data/events'
|
||||||
import { useLang } from '@/context/LangContext'
|
import { useLang } from '@/context/LangContext'
|
||||||
|
|
||||||
const ROUTES = [
|
|
||||||
{ start: { lat: 35.69, lng: 51.39 }, end: { lat: 33.31, lng: 44.36 } },
|
|
||||||
{ start: { lat: 35.69, lng: 51.39 }, end: { lat: 41.30, lng: 69.24 } },
|
|
||||||
{ start: { lat: 31.23, lng: 121.47 }, end: { lat: 51.92, lng: 4.47 } },
|
|
||||||
{ start: { lat: 31.23, lng: 121.47 }, end: { lat: 6.45, lng: 3.39 } },
|
|
||||||
{ start: { lat: 31.23, lng: 121.47 }, end: { lat: 1.35, lng: 103.82 } },
|
|
||||||
{ start: { lat: 55.75, lng: 37.62 }, end: { lat: 39.91, lng: 116.39 } },
|
|
||||||
{ start: { lat: 55.75, lng: 37.62 }, end: { lat: 35.69, lng: 51.39 } },
|
|
||||||
{ start: { lat: 19.07, lng: 72.88 }, end: { lat: 25.20, lng: 55.27 } },
|
|
||||||
{ start: { lat: 19.07, lng: 72.88 }, end: { lat: -4.05, lng: 39.67 } },
|
|
||||||
{ start: { lat: -23.55, lng: -46.63 }, end: { lat: 31.23, lng: 121.47 } },
|
|
||||||
{ start: { lat: 37.56, lng: 126.97 }, end: { lat: 1.35, lng: 103.82 } },
|
|
||||||
{ start: { lat: 41.01, lng: 28.97 }, end: { lat: 52.52, lng: 13.40 } },
|
|
||||||
{ start: { lat: -33.87, lng: 151.21 }, end: { lat: 31.23, lng: 121.47 } },
|
|
||||||
]
|
|
||||||
|
|
||||||
const TYPE_COLOR: Record<string, string> = {
|
const TYPE_COLOR: Record<string, string> = {
|
||||||
conference: 'var(--ink)', exhibition: '#6b4a00',
|
conference: 'var(--ink)', exhibition: '#6b4a00',
|
||||||
seminar: '#1a4a2a', international: 'var(--red)',
|
seminar: '#1a4a2a', international: 'var(--red)',
|
||||||
|
|
@ -69,7 +53,7 @@ export default function MapEventsSection() {
|
||||||
<p style={{ fontSize: 13, color: 'var(--ink-4)', lineHeight: 1.7, maxWidth: 460 }}>{t.mapSub}</p>
|
<p style={{ fontSize: 13, color: 'var(--ink-4)', lineHeight: 1.7, maxWidth: 460 }}>{t.mapSub}</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: '8px 16px 32px' }}>
|
<div style={{ padding: '8px 16px 32px' }}>
|
||||||
<WorldMap dots={ROUTES} lineColor="#9b1c1c" dotColor="#c8c2bc" />
|
<Globe size={460} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,25 @@
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
import { Telescope, Scale, Database, Users, Lightbulb, type LucideIcon } from 'lucide-react'
|
||||||
import { useLang } from '@/context/LangContext'
|
import { useLang } from '@/context/LangContext'
|
||||||
import { RadarCard } from '@/pages/Radar/Radar'
|
import { RadarCard } from '@/pages/Radar/Radar'
|
||||||
import { RADAR_ITEMS } from '@/content/radar'
|
import { RADAR_ITEMS } from '@/content/radar'
|
||||||
|
|
||||||
/* ─── Tech data ──────────────────────────────────────── */
|
/* ─── رویکرد ما — the institute's approach (new content, not duplicated in the navbar) ─── */
|
||||||
const TECHS = {
|
type Area = { Icon: LucideIcon; color: string; title: string; desc: string }
|
||||||
|
const RESEARCH_AREAS: Record<'fa' | 'en', Area[]> = {
|
||||||
fa: [
|
fa: [
|
||||||
{
|
{ Icon: Telescope, color: '#c9a227', title: 'آیندهنگاری علمی', desc: 'بهجای پیشبینی تکنقطهای، با سناریوپردازی و تحلیل روند، چند آیندهٔ محتمل صنعت فولاد را ترسیم میکنیم.' },
|
||||||
num: '۰۱', tag: 'انرژی پاک',
|
{ Icon: Database, color: '#2471a3', title: 'تحلیل دادهمحور', desc: 'هر بینش بر پایهٔ دادههای معتبر جهانی و داخلی است، نه گمانهزنی؛ تصمیمسازی با شواهد قابلاتکا.' },
|
||||||
title: 'فولاد هیدروژنی (DRI-H₂)',
|
{ Icon: Scale, color: '#1e8449', title: 'بیطرفی و استقلال', desc: 'تحلیلهای ما مستقل از منافع کوتاهمدت است؛ شفاف و بدون جانبداری از یک بازیگر خاص.' },
|
||||||
desc: 'جایگزینی کک با هیدروژن سبز در کورههای احیای مستقیم؛ اولین کارخانه تجاری اروپایی در ۲۰۲۴ وارد مرحله تولید شد. ظرفیت تولید ۲.۵ میلیون تن در سال.',
|
{ Icon: Users, color: '#7d3c98', title: 'هماندیشی خبرگان', desc: 'شبکهای از مدیران، پژوهشگران و فعالان صنعت که دانش پراکنده را به بینش جمعی تبدیل میکند.' },
|
||||||
img: '/news/photo-1613665813446-82a78c468a1d.jpg',
|
{ Icon: Lightbulb, color: '#c0392b', title: 'از تحلیل تا اقدام', desc: 'یافتهها را به راهبردهای عملی و قابلاجرا برای رهبران صنعت ترجمه میکنیم، نه گزارشهای روی طاقچه.' },
|
||||||
horizon: '۲۰۲۷–۲۰۳۰', accentColor: '#0d6b3e',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
num: '۰۲', tag: 'هوش مصنوعی',
|
|
||||||
title: 'دیجیتالسازی و AI در تولید فولاد',
|
|
||||||
desc: 'یادگیری ماشین در بهینهسازی فرآیند ذوب، کنترل کیفیت آنلاین و پیشبینی خرابی تجهیزات. کاهش ۱۵–۲۰٪ ضایعات و صرفهجویی ۸٪ در مصرف انرژی.',
|
|
||||||
img: '/news/photo-1485827404703-89b55fcc595e.jpg',
|
|
||||||
horizon: '۲۰۲۵–۲۰۲۸', accentColor: '#1a4a7a',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
num: '۰۳', tag: 'فناوری نوین',
|
|
||||||
title: 'الکترولیز اکسید مذاب (MOE)',
|
|
||||||
desc: 'تولید فولاد از طریق الکترولیز مستقیم اکسید آهن با برق تجدیدپذیر — بدون انتشار CO₂. MIT این فناوری را «انقلاب صنعتی بعدی» نامیده است.',
|
|
||||||
img: '/news/photo-1451187580459-43490279c0fa.jpg',
|
|
||||||
horizon: '۲۰۳۰–۲۰۳۵', accentColor: '#6b21a8',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
en: [
|
en: [
|
||||||
{
|
{ Icon: Telescope, color: '#c9a227', title: 'Scientific Foresight', desc: 'Instead of single-point prediction, we map several plausible futures of the steel industry through scenario planning.' },
|
||||||
num: '01', tag: 'Clean Energy',
|
{ Icon: Database, color: '#2471a3', title: 'Data-Driven Analysis', desc: 'Every insight rests on credible global and domestic data — evidence, not guesswork.' },
|
||||||
title: 'Hydrogen Steel (DRI-H₂)',
|
{ Icon: Scale, color: '#1e8449', title: 'Independence & Neutrality', desc: 'Our analysis is independent of short-term interests — transparent and unbiased toward any single actor.' },
|
||||||
desc: "Replacing coke with green hydrogen in direct reduction furnaces; Europe's first commercial plant entered production in 2024 with 2.5 million ton annual capacity.",
|
{ Icon: Users, color: '#7d3c98', title: 'Expert Collaboration', desc: 'A network of executives, researchers and practitioners turning scattered knowledge into collective insight.' },
|
||||||
img: '/news/photo-1613665813446-82a78c468a1d.jpg',
|
{ Icon: Lightbulb, color: '#c0392b', title: 'From Analysis to Action', desc: 'We translate findings into practical strategies for industry leaders — not shelf-ware reports.' },
|
||||||
horizon: '2027–2030', accentColor: '#0d6b3e',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
num: '02', tag: 'Artificial Intelligence',
|
|
||||||
title: 'Digitalization & AI in Steel Production',
|
|
||||||
desc: 'Machine learning for smelting optimization, online quality control, and equipment failure prediction. Cuts waste by 15–20% and energy use by 8%.',
|
|
||||||
img: '/news/photo-1485827404703-89b55fcc595e.jpg',
|
|
||||||
horizon: '2025–2028', accentColor: '#1a4a7a',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
num: '03', tag: 'Emerging Tech',
|
|
||||||
title: 'Molten Oxide Electrolysis (MOE)',
|
|
||||||
desc: 'Producing steel by direct electrolysis of iron oxide using renewable electricity — zero CO₂ emissions. MIT has called it "the next industrial revolution".',
|
|
||||||
img: '/news/photo-1451187580459-43490279c0fa.jpg',
|
|
||||||
horizon: '2030–2035', accentColor: '#6b21a8',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,26 +28,21 @@ const T = {
|
||||||
radarOverline: 'FUTURE RADAR', radarHeading: 'رادار آینده',
|
radarOverline: 'FUTURE RADAR', radarHeading: 'رادار آینده',
|
||||||
radarSub: 'سیگنالهای جهانی با اثر مستقیم بر صنعت فولاد ایران',
|
radarSub: 'سیگنالهای جهانی با اثر مستقیم بر صنعت فولاد ایران',
|
||||||
radarAll: 'همه سیگنالها ←',
|
radarAll: 'همه سیگنالها ←',
|
||||||
techOverline: 'TECH FRONTIER', techHeading: 'مرز فناوری',
|
areasOverline: 'OUR APPROACH', areasHeading: 'رویکرد ما',
|
||||||
techSub: 'فناوریهای نوظهور و افق کاربرد آنها در صنعت فولاد',
|
areasSub: 'اصول و روش کار اندیشکده فولاد آینده در تحلیل و آیندهنگاری صنعت',
|
||||||
techAll: 'همه فناوریها ←',
|
|
||||||
horizon: 'افق زمانی',
|
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
radarOverline: 'FUTURE RADAR', radarHeading: 'Future Radar',
|
radarOverline: 'FUTURE RADAR', radarHeading: 'Future Radar',
|
||||||
radarSub: 'Global signals with direct impact on Iran\'s steel industry',
|
radarSub: 'Global signals with direct impact on Iran\'s steel industry',
|
||||||
radarAll: 'All Signals →',
|
radarAll: 'All Signals →',
|
||||||
techOverline: 'TECH FRONTIER', techHeading: 'Tech Frontier',
|
areasOverline: 'OUR APPROACH', areasHeading: 'Our Approach',
|
||||||
techSub: 'Emerging technologies and their application horizon in the steel industry',
|
areasSub: 'How the Steel Futures Institute works — its principles for analysis and foresight',
|
||||||
techAll: 'All Technologies →',
|
|
||||||
horizon: 'Horizon',
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RadarTechSection() {
|
export default function RadarTechSection() {
|
||||||
const { lang } = useLang()
|
const { lang } = useLang()
|
||||||
const t = T[lang]
|
const t = T[lang]
|
||||||
const techs = TECHS[lang]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section dir={lang === 'fa' ? 'rtl' : 'ltr'} style={{ background: 'var(--paper-2)' }}>
|
<section dir={lang === 'fa' ? 'rtl' : 'ltr'} style={{ background: 'var(--paper-2)' }}>
|
||||||
|
|
@ -104,61 +69,43 @@ export default function RadarTechSection() {
|
||||||
{/* divider */}
|
{/* divider */}
|
||||||
<div style={{ height: 1, background: 'var(--rule-thin)' }} />
|
<div style={{ height: 1, background: 'var(--rule-thin)' }} />
|
||||||
|
|
||||||
{/* ══ مرز فناوری ══ */}
|
{/* ══ حوزههای پژوهشی ══ */}
|
||||||
<div style={{ paddingTop: 56, paddingBottom: 64 }}>
|
<div style={{ paddingTop: 56, paddingBottom: 64 }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 32, flexWrap: 'wrap', gap: 12 }}>
|
<div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 32, flexWrap: 'wrap', gap: 12 }}>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontSize: 9, fontWeight: 700, letterSpacing: '3px', textTransform: 'uppercase', color: 'var(--ink-4)', marginBottom: 6 }}>{t.techOverline}</div>
|
<div style={{ fontSize: 9, fontWeight: 700, letterSpacing: '3px', textTransform: 'uppercase', color: 'var(--ink-4)', marginBottom: 6 }}>{t.areasOverline}</div>
|
||||||
<h2 style={{ fontSize: 'clamp(22px,2.5vw,32px)', fontWeight: 900, color: 'var(--ink)', letterSpacing: '-0.5px', marginBottom: 6 }}>{t.techHeading}</h2>
|
<h2 style={{ fontSize: 'clamp(22px,2.5vw,32px)', fontWeight: 900, color: 'var(--ink)', letterSpacing: '-0.5px', marginBottom: 6 }}>{t.areasHeading}</h2>
|
||||||
<p style={{ fontSize: 13, color: 'var(--ink-4)' }}>{t.techSub}</p>
|
<p style={{ fontSize: 13, color: 'var(--ink-4)' }}>{t.areasSub}</p>
|
||||||
</div>
|
</div>
|
||||||
<Link to="/technology" style={{ fontSize: 12, fontWeight: 700, color: 'var(--red)', textDecoration: 'none', whiteSpace: 'nowrap' }}>{t.techAll}</Link>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-3 max-md:grid-cols-1" style={{ gap: 16 }}>
|
<div className="grid grid-cols-3 max-md:grid-cols-1 max-lg:grid-cols-2" style={{ gap: 16 }}>
|
||||||
{techs.map((tech, i) => (
|
{RESEARCH_AREAS[lang].map((a, i) => {
|
||||||
|
const Icon = a.Icon
|
||||||
|
return (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
style={{
|
style={{
|
||||||
background: '#fff', overflow: 'hidden',
|
background: '#fff', borderRadius: 16, padding: '26px 24px',
|
||||||
boxShadow: '0 2px 12px rgba(0,0,0,0.07)',
|
boxShadow: '0 2px 12px rgba(0,0,0,0.06)', display: 'flex', flexDirection: 'column', gap: 14,
|
||||||
display: 'flex', flexDirection: 'column',
|
border: '1px solid var(--rule-thin)', transition: 'transform 0.2s, box-shadow 0.2s',
|
||||||
transition: 'transform 0.2s, box-shadow 0.2s', cursor: 'pointer',
|
|
||||||
}}
|
}}
|
||||||
onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.transform = 'translateY(-4px)'; (e.currentTarget as HTMLDivElement).style.boxShadow = '0 10px 30px rgba(0,0,0,0.12)' }}
|
onMouseEnter={e => { const d = e.currentTarget as HTMLElement; d.style.transform = 'translateY(-4px)'; d.style.boxShadow = '0 14px 34px -18px rgba(7,29,73,0.25)' }}
|
||||||
onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.transform = 'translateY(0)'; (e.currentTarget as HTMLDivElement).style.boxShadow = '0 2px 12px rgba(0,0,0,0.07)' }}
|
onMouseLeave={e => { const d = e.currentTarget as HTMLElement; d.style.transform = 'translateY(0)'; d.style.boxShadow = '0 2px 12px rgba(0,0,0,0.06)' }}
|
||||||
>
|
>
|
||||||
{/* Image */}
|
|
||||||
<div style={{ position: 'relative', height: 160, overflow: 'hidden' }}>
|
|
||||||
<img src={tech.img} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block', transition: 'transform 0.4s' }}
|
|
||||||
onMouseEnter={e => (e.currentTarget.style.transform = 'scale(1.06)')}
|
|
||||||
onMouseLeave={e => (e.currentTarget.style.transform = 'scale(1)')}
|
|
||||||
/>
|
|
||||||
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(0,0,0,0.5) 0%, transparent 60%)' }} />
|
|
||||||
<div style={{
|
<div style={{
|
||||||
position: 'absolute', bottom: 12,
|
width: 52, height: 52, borderRadius: 14, flexShrink: 0,
|
||||||
right: lang === 'fa' ? 12 : 'auto', left: lang === 'en' ? 12 : 'auto',
|
background: `${a.color}15`, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
}}>
|
}}>
|
||||||
<span style={{ background: tech.accentColor, color: '#fff', fontSize: 9, fontWeight: 700, padding: '2px 8px', letterSpacing: '1px', textTransform: 'uppercase' }}>{tech.tag}</span>
|
<Icon size={26} color={a.color} strokeWidth={2} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div>
|
||||||
position: 'absolute', top: 12,
|
<h3 style={{ fontSize: 16, fontWeight: 900, color: 'var(--ink)', lineHeight: 1.4, margin: '0 0 8px' }}>{a.title}</h3>
|
||||||
right: lang === 'fa' ? 12 : 'auto', left: lang === 'en' ? 12 : 'auto',
|
<p style={{ fontSize: 12.5, color: 'var(--ink-4)', lineHeight: 1.85, margin: 0 }}>{a.desc}</p>
|
||||||
fontSize: 36, fontWeight: 900, color: 'rgba(255,255,255,0.25)', direction: 'ltr', lineHeight: 1,
|
|
||||||
}}>{tech.num}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div style={{ padding: '20px', flex: 1, display: 'flex', flexDirection: 'column', gap: 10, borderTop: `3px solid ${tech.accentColor}` }}>
|
|
||||||
<h3 style={{ fontSize: 14, fontWeight: 800, color: 'var(--ink)', lineHeight: 1.5 }}>{tech.title}</h3>
|
|
||||||
<p style={{ fontSize: 12, color: 'var(--ink-4)', lineHeight: 1.75, flex: 1 }}>{tech.desc}</p>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 'auto' }}>
|
|
||||||
<span style={{ fontSize: 9, fontWeight: 700, color: 'var(--ink-5)', letterSpacing: '1px', textTransform: 'uppercase' }}>{t.horizon}:</span>
|
|
||||||
<span style={{ fontSize: 11, fontWeight: 700, color: tech.accentColor }}>{tech.horizon}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue