Files
teknav-bak/global/src/global-home.jsx
T
arsam 24b71ad8de Import source: global/src/global-home
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:27:16 +03:30

491 lines
30 KiB
React

// global-home.jsx — Homepage for Teknav Global (English, LTR)
import { useState, useEffect, useRef } from 'react';
import { articles as allArticlesData, authors, categories, siteConfig } from '../global-data.js';
import { useNav, useAuth, AuthorAvatar, CategoryBadge, TypeBadge, NewsletterForm, pillBtn } from './global-ui.jsx';
// ── Hero Neural Background ──────────────────────────────────────────────────
function HeroBackground() {
const canvasRef = useRef();
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
let raf, t = 0;
const palette = [
'rgba(15,107,115,',
'rgba(196,106,77,',
'rgba(47,143,107,',
];
const nodes = Array.from({ length: 32 }, (_, i) => ({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: (Math.random() - 0.5) * 0.35,
vy: (Math.random() - 0.5) * 0.35,
r: Math.random() * 3 + 1.5,
color: palette[i % palette.length],
phase: Math.random() * Math.PI * 2,
}));
const resize = () => { canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; };
resize();
window.addEventListener('resize', resize);
const draw = () => {
t += 0.012;
ctx.clearRect(0, 0, canvas.width, canvas.height);
nodes.forEach(n => {
n.x += n.vx; n.y += n.vy;
if (n.x < 0 || n.x > canvas.width) n.vx *= -1;
if (n.y < 0 || n.y > canvas.height) n.vy *= -1;
nodes.forEach(m => {
const d = Math.hypot(n.x - m.x, n.y - m.y);
if (d < 130) {
ctx.beginPath();
ctx.moveTo(n.x, n.y); ctx.lineTo(m.x, m.y);
ctx.strokeStyle = `rgba(15,107,115,${0.18 * (1 - d / 130)})`;
ctx.lineWidth = 0.8; ctx.stroke();
}
});
const pulse = 0.45 + 0.18 * Math.sin(t + n.phase);
ctx.beginPath();
ctx.arc(n.x, n.y, n.r, 0, Math.PI * 2);
ctx.fillStyle = n.color + pulse + ')';
ctx.fill();
});
raf = requestAnimationFrame(draw);
};
draw();
return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); };
}, []);
return <canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }} />;
}
// ── Article Card (grid) ─────────────────────────────────────────────────────
function ArticleCard({ article, delay = 0 }) {
const { navigate } = useNav();
const [vis, setVis] = useState(false);
const ref = useRef();
useEffect(() => {
const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) setVis(true); }, { threshold: 0.1 });
if (ref.current) obs.observe(ref.current);
return () => obs.disconnect();
}, []);
const author = authors.find(a => a.id === article.author);
const cat = categories.find(c => c.id === article.category);
return (
<div ref={ref} onClick={() => navigate('/article/' + article.slug)} style={{
background: '#fff', borderRadius: 12, border: '1px solid #E4DDD2',
padding: 24, cursor: 'pointer',
opacity: vis ? 1 : 0, transform: vis ? 'translateY(0)' : 'translateY(24px)',
transition: `opacity 0.5s ${delay}ms, transform 0.5s ${delay}ms, box-shadow 0.2s`,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}} onMouseEnter={e => e.currentTarget.style.boxShadow = '0 8px 32px rgba(0,0,0,0.1)'}
onMouseLeave={e => e.currentTarget.style.boxShadow = '0 2px 12px rgba(0,0,0,0.04)'}>
<div style={{ height: 120, borderRadius: 8, background: '#F4EFE6', marginBottom: 16, overflow: 'hidden', position: 'relative' }}>
{article.photo ? (
<img src={article.photo} alt={article.title} loading="lazy"
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
onError={e => { e.target.style.display = 'none'; }} />
) : (
<div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ width: 40, height: 40, borderRadius: '50%', background: cat?.color || '#0F6B73', opacity: 0.3 }} />
</div>
)}
</div>
<div style={{ display: 'flex', gap: 6, marginBottom: 10, flexWrap: 'wrap' }}>
{article.type && <TypeBadge type={article.type} small />}
<CategoryBadge name={cat?.name || article.category} color={cat?.color} small />
</div>
<h3 style={{ fontSize: 15, fontWeight: 700, color: '#263238', margin: '0 0 8px', lineHeight: 1.5, fontFamily: 'Inter,sans-serif' }}>{article.title}</h3>
<p style={{ fontSize: 12, color: '#5F6B6D', lineHeight: 1.7, margin: '0 0 16px' }}>{(article.subtitle || article.summary || '').slice(0, 100)}...</p>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 11, color: '#5F6B6D' }}>
<span>{article.date}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
{author && <AuthorAvatar author={author} size={22} />}
<span>{article.readTime} min</span>
</div>
</div>
</div>
);
}
// ── Featured Article ────────────────────────────────────────────────────────
function FeaturedArticle({ article }) {
const { navigate } = useNav();
const author = authors.find(a => a.id === article.author);
const cat = categories.find(c => c.id === article.category);
return (
<div onClick={() => navigate('/article/' + article.slug)} style={{
background: '#fff', borderRadius: 16, border: '1px solid #E4DDD2', padding: 0,
cursor: 'pointer', overflow: 'hidden',
boxShadow: '0 4px 24px rgba(0,0,0,0.06)',
display: 'grid', gridTemplateColumns: '1fr 1fr', minHeight: 280,
transition: 'box-shadow 0.2s',
}} className="featured-card"
onMouseEnter={e => e.currentTarget.style.boxShadow = '0 12px 48px rgba(0,0,0,0.12)'}
onMouseLeave={e => e.currentTarget.style.boxShadow = '0 4px 24px rgba(0,0,0,0.06)'}>
<div style={{ padding: '32px 24px 32px 32px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
<div>
<div style={{ display: 'flex', gap: 8, marginBottom: 14 }}>
{article.type && <TypeBadge type={article.type} />}
<CategoryBadge name={cat?.name || article.category} color={cat?.color} />
</div>
<h2 style={{ fontSize: 22, fontWeight: 800, color: '#263238', margin: '0 0 12px', lineHeight: 1.5, fontFamily: 'Inter,sans-serif' }}>{article.title}</h2>
<p style={{ fontSize: 14, color: '#5F6B6D', lineHeight: 1.8, margin: 0 }}>{article.subtitle || article.summary}</p>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 20, paddingTop: 16, borderTop: '1px solid #E4DDD2' }}>
{author && <AuthorAvatar author={author} size={36} />}
<div>
<div style={{ fontSize: 13, fontWeight: 600, color: '#263238' }}>{author?.name}</div>
<div style={{ fontSize: 11, color: '#5F6B6D' }}>{article.date} · {article.readTime} min read</div>
</div>
</div>
</div>
<div style={{ background: '#F4EFE6', overflow: 'hidden' }}>
{article.photo ? (
<img src={article.photo} alt={article.title} loading="eager"
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
onError={e => { e.target.style.display = 'none'; }} />
) : (
<div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ width: 80, height: 80, borderRadius: '50%', background: cat?.color || '#0F6B73', opacity: 0.15 }} />
</div>
)}
</div>
</div>
);
}
// ── Authors Section ─────────────────────────────────────────────────────────
function AuthorsSection() {
const { navigate } = useNav();
return (
<section style={{ padding: '60px 0' }}>
<h2 style={sectionTitle}>Teknav Authors</h2>
<p style={sectionSubtitle}>The specialists who write Teknav's deep technology analysis</p>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(200px,1fr))', gap: 16 }} className="authors-grid">
{authors.map(author => (
<div key={author.id} style={{
background: '#fff', border: '1px solid #E4DDD2', borderRadius: 12, padding: 20,
cursor: 'pointer', textAlign: 'center', transition: 'all 0.2s',
}} onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-4px)'; e.currentTarget.style.boxShadow = '0 8px 24px rgba(0,0,0,0.08)'; }}
onMouseLeave={e => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; }}>
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: 12 }}>
<AuthorAvatar author={author} size={56} />
</div>
<div style={{ fontSize: 14, fontWeight: 700, color: '#263238', marginBottom: 4 }}>{author.name}</div>
<div style={{ fontSize: 11, color: '#5F6B6D', marginBottom: 8 }}>{author.specialty}</div>
<div style={{ fontSize: 11, color: '#0F6B73', fontWeight: 600 }}>{author.articleCount} articles</div>
</div>
))}
</div>
</section>
);
}
// ── Hero Section ─────────────────────────────────────────────────────────────
function HeroSection({ featured, navigate }) {
const wrapRef = useRef();
const cardRef = useRef();
useEffect(() => {
const wrap = wrapRef.current;
const card = cardRef.current;
if (!wrap || !card) return;
const onMove = e => {
const r = wrap.getBoundingClientRect();
const dx = (e.clientX - r.left) / r.width - 0.5;
const dy = (e.clientY - r.top) / r.height - 0.5;
card.style.transform = `perspective(900px) rotateX(${(-dy * 4).toFixed(2)}deg) rotateY(${(dx * 6).toFixed(2)}deg)`;
};
const onLeave = () => { card.style.transform = 'perspective(900px) rotateX(0) rotateY(0)'; };
wrap.addEventListener('mousemove', onMove);
wrap.addEventListener('mouseleave', onLeave);
return () => { wrap.removeEventListener('mousemove', onMove); wrap.removeEventListener('mouseleave', onLeave); };
}, []);
return (
<div ref={wrapRef} style={{ position: 'relative', background: '#F4F1EC', overflow: 'hidden', minHeight: 560 }}>
<div style={{ position: 'absolute', top: '20%', left: '10%', width: 520, height: 520, borderRadius: '50%', background: 'radial-gradient(circle, rgba(15,107,115,0.10) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', bottom: '0%', right: '15%', width: 380, height: 380, borderRadius: '50%', background: 'radial-gradient(circle, rgba(196,106,77,0.10) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(15,42,46,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(15,42,46,0.04) 1px, transparent 1px)', backgroundSize: '48px 48px', maskImage: 'radial-gradient(circle at 50% 40%, #000 30%, transparent 75%)', WebkitMaskImage: 'radial-gradient(circle at 50% 40%, #000 30%, transparent 75%)', pointerEvents: 'none' }} />
<HeroBackground />
<div className="home-hero-inner" style={{ position: 'relative', zIndex: 2, maxWidth: 1280, margin: '0 auto', padding: '76px 24px 70px' }}>
<div style={{ maxWidth: 600, marginBottom: 44 }}>
<div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: 'rgba(15,107,115,0.08)', border: '1px solid rgba(15,107,115,0.25)', color: '#0F6B73', padding: '6px 16px', borderRadius: 999, fontSize: 11, fontWeight: 700, marginBottom: 26, letterSpacing: '0.08em', animation: 'heroReveal 0.6s 0.1s both' }}>
<span style={{ width: 6, height: 6, borderRadius: '50%', background: '#0F6B73', display: 'inline-block', animation: 'pulseRing 2.2s infinite' }} />
Deep Technology Analysis
</div>
<h1 style={{ fontSize: 'clamp(34px,5.4vw,58px)', fontWeight: 800, color: '#0F2A2E', margin: '0 0 4px', lineHeight: 1.25, fontFamily: 'Inter,sans-serif', animation: 'heroReveal 0.7s 0.35s both', letterSpacing: '-0.02em' }}>
Understand more.
</h1>
<h1 className="gold-shimmer" style={{ fontSize: 'clamp(34px,5.4vw,58px)', fontWeight: 800, margin: '0 0 22px', lineHeight: 1.25, fontFamily: 'Inter,sans-serif', animation: 'heroReveal 0.7s 0.6s both', letterSpacing: '-0.02em' }}>
Build better.
</h1>
<p style={{ fontSize: 16, color: '#4A5A5C', lineHeight: 2, margin: '0 0 32px', animation: 'heroReveal 0.7s 0.85s both', maxWidth: 540 }}>
Scientific, independent analysis of AI engineering, data infrastructure, cybersecurity, and the future of software.
</p>
<div className="home-hero-actions" style={{ display: 'flex', gap: 12, flexWrap: 'wrap', animation: 'heroReveal 0.7s 1.1s both' }}>
<button onClick={() => navigate('/articles')} style={{ background: '#0F6B73', color: '#fff', border: 'none', padding: '14px 32px', borderRadius: 10, fontSize: 14, fontWeight: 700, cursor: 'pointer', fontFamily: 'Inter,sans-serif', boxShadow: '0 6px 22px rgba(15,107,115,0.28)', transition: 'transform 0.2s ease, box-shadow 0.2s ease' }}
onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = '0 10px 28px rgba(15,107,115,0.35)'; }}
onMouseLeave={e => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = '0 6px 22px rgba(15,107,115,0.28)'; }}>
All Articles →
</button>
<button onClick={() => navigate('/category/ai')} style={{ background: 'rgba(196,106,77,0.08)', color: '#A8512E', border: '1px solid rgba(196,106,77,0.45)', padding: '14px 30px', borderRadius: 10, fontSize: 14, fontWeight: 600, cursor: 'pointer', fontFamily: 'Inter,sans-serif', transition: 'all 0.2s' }}
onMouseEnter={e => e.currentTarget.style.background = 'rgba(196,106,77,0.16)'}
onMouseLeave={e => e.currentTarget.style.background = 'rgba(196,106,77,0.08)'}>
AI Engineering
</button>
</div>
</div>
{featured && (
<div ref={cardRef} className="hero-tilt" style={{ background: '#fff', border: '1px solid #E4DDD2', borderRadius: 16, padding: '20px 24px', maxWidth: 580, animation: 'heroReveal 0.7s 1.35s both', boxShadow: '0 14px 40px rgba(15,42,46,0.08), 0 2px 8px rgba(15,42,46,0.04)', position: 'relative', overflow: 'hidden' }}>
<div style={{ position: 'absolute', top: 0, left: 0, bottom: 0, width: 4, background: 'linear-gradient(180deg, #D49A2A, #C46A4D)' }} />
<div style={{ fontSize: 10, color: '#C46A4D', fontWeight: 700, marginBottom: 10, letterSpacing: '0.1em', display: 'flex', alignItems: 'center', gap: 6 }}>
<span style={{ display: 'inline-block', animation: 'float-y 3s ease-in-out infinite' }}>✦</span>
Featured
</div>
<div onClick={() => navigate('/article/' + featured.slug)} style={{ fontSize: 18, fontWeight: 700, color: '#0F2A2E', cursor: 'pointer', lineHeight: 1.65, transition: 'color 0.15s', fontFamily: 'Inter,sans-serif' }}
onMouseEnter={e => e.currentTarget.style.color = '#0F6B73'}
onMouseLeave={e => e.currentTarget.style.color = '#0F2A2E'}>
{featured.title}
</div>
<div style={{ fontSize: 12, color: '#5F6B6D', marginTop: 12, display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
<span style={{ fontWeight: 600, color: '#0F6B73' }}>{authors.find(a => a.id === featured.author)?.name}</span>
<span style={{ opacity: 0.4 }}>·</span>
<span>{featured.type}</span>
<span style={{ opacity: 0.4 }}>·</span>
<span>{featured.readTime} min read</span>
</div>
</div>
)}
</div>
<svg viewBox="0 0 1440 60" preserveAspectRatio="none" style={{ position: 'absolute', bottom: -1, left: 0, width: '100%', height: 50, display: 'block', pointerEvents: 'none' }}>
<path d="M0,40 C240,60 480,10 720,30 C960,50 1200,15 1440,35 L1440,60 L0,60 Z" fill="#ebe3d2" />
</svg>
</div>
);
}
// ── Stats Bar ───────────────────────────────────────────────────────────────
function CountUp({ to, suffix = '', duration = 1400 }) {
const [n, setN] = useState(0);
const ref = useRef();
const started = useRef(false);
useEffect(() => {
const obs = new IntersectionObserver(([e]) => {
if (e.isIntersecting && !started.current) {
started.current = true;
const start = performance.now();
const tick = (now) => {
const p = Math.min((now - start) / duration, 1);
const eased = 1 - Math.pow(1 - p, 3);
setN(Math.round(to * eased));
if (p < 1) requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
}
}, { threshold: 0.4 });
if (ref.current) obs.observe(ref.current);
return () => obs.disconnect();
}, [to, duration]);
return <span ref={ref}>{n.toLocaleString('en-US')}{suffix}</span>;
}
function StatsBar() {
const stats = [
{ label: 'Articles published', to: 75, suffix: '+', icon: '◉' },
{ label: 'Active authors', to: 2, suffix: '', icon: '✎' },
{ label: 'Monthly readers', to: 65000, suffix: '+', icon: '◐' },
{ label: 'Avg. read time', to: 10, suffix: ' min', icon: '◷' },
];
return (
<div style={{ background: '#ebe3d2', padding: '40px 24px', borderTop: '1px solid rgba(15,42,46,0.06)', borderBottom: '1px solid rgba(15,42,46,0.06)' }}>
<div style={{ maxWidth: 1280, margin: '0 auto', display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(180px,1fr))', gap: 16 }} className="stats-bar-inner">
{stats.map((s, i) => (
<div key={s.label} className="lift-on-hover" style={{ textAlign: 'center', padding: '12px 8px', borderRadius: 12, position: 'relative' }}>
<div style={{ fontSize: 14, color: '#0F6B73', marginBottom: 6, opacity: 0.7 }}>{s.icon}</div>
<div style={{ fontSize: 30, fontWeight: 900, color: '#A8761B', marginBottom: 6, fontFamily: 'Inter,sans-serif', letterSpacing: '-0.02em' }}>
<CountUp to={s.to} suffix={s.suffix} />
</div>
<div style={{ fontSize: 13, color: '#4A5A5C', fontWeight: 500 }}>{s.label}</div>
{i < stats.length - 1 && (
<div style={{ position: 'absolute', right: 0, top: '20%', height: '60%', width: 1, background: 'rgba(15,42,46,0.08)' }} />
)}
</div>
))}
</div>
</div>
);
}
// ── Shared section styles ───────────────────────────────────────────────────
const sectionTitle = { fontSize: 22, fontWeight: 800, color: '#263238', margin: '0 0 8px', fontFamily: 'Inter,sans-serif' };
const sectionSubtitle = { fontSize: 14, color: '#5F6B6D', margin: '0 0 32px', lineHeight: 1.7 };
// ── Article Row Compact ─────────────────────────────────────────────────────
function ArticleRowCompact({ article }) {
const { navigate } = useNav();
const cat = categories.find(c => c.id === article.category);
return (
<div onClick={() => navigate('/article/' + article.slug)} style={{
display: 'flex', gap: 20, padding: '20px 0', borderBottom: '1px solid #E4DDD2',
cursor: 'pointer', alignItems: 'flex-start', transition: 'background 0.15s',
}} onMouseEnter={e => e.currentTarget.style.background = '#F4EFE620'}
onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', gap: 6, marginBottom: 8 }}>
{article.type && <TypeBadge type={article.type} small />}
<CategoryBadge name={cat?.name || article.category} color={cat?.color} small />
</div>
<h3 style={{ fontSize: 16, fontWeight: 700, color: '#263238', margin: '0 0 6px', lineHeight: 1.5 }}>{article.title}</h3>
<p style={{ fontSize: 13, color: '#5F6B6D', margin: '0 0 10px', lineHeight: 1.7 }}>{(article.subtitle || '').slice(0, 140)}…</p>
<div style={{ fontSize: 11, color: '#5F6B6D' }}>
{authors.find(a => a.id === article.author)?.name} · {article.date} · {article.readTime} min
</div>
</div>
<div style={{ width: 80, height: 80, background: '#F4EFE6', borderRadius: 8, overflow: 'hidden', flexShrink: 0 }}>
{article.photo && (
<img src={article.photo} alt={article.title} loading="lazy"
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
onError={e => { e.target.style.display = 'none'; }} />
)}
</div>
</div>
);
}
// ── Homepage ────────────────────────────────────────────────────────────────
export default function HomePage() {
const { navigate } = useNav();
const articles = allArticlesData;
const featured = articles.find(a => a.featured) || articles[0];
const latest = articles.filter(a => a.id !== featured?.id).slice(0, 6);
const popular = [...articles].sort((a, b) => (b.views || 0) - (a.views || 0)).slice(0, 4);
const aiArticles = articles.filter(a => a.category === 'ai').slice(0, 5);
const securityArticles = articles.filter(a => a.category === 'security').slice(0, 5);
return (
<main style={{ paddingTop: 64, background: '#FAF7F0', minHeight: '100vh', fontFamily: 'Inter,sans-serif' }}>
<HeroSection featured={featured} navigate={navigate} />
<StatsBar />
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '0 24px' }}>
{featured && (
<section className="home-section" style={{ padding: '60px 0 40px' }} aria-labelledby="featured-title">
<h2 id="featured-title" style={sectionTitle}>Featured</h2>
<p style={sectionSubtitle}>The deepest analysis this week</p>
<FeaturedArticle article={featured} />
</section>
)}
<section className="home-section" style={{ padding: '40px 0' }} aria-labelledby="latest-title">
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
<h2 id="latest-title" style={{ ...sectionTitle, margin: 0 }}>Latest</h2>
<button onClick={() => navigate('/articles')} style={{ background: 'none', border: 'none', color: '#0F6B73', fontSize: 13, fontWeight: 600, cursor: 'pointer', fontFamily: 'Inter,sans-serif' }}>View all →</button>
</div>
<p style={sectionSubtitle}>The latest analysis from Teknav</p>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(280px,1fr))', gap: 20 }} className="article-grid">
{latest.map((a, i) => <ArticleCard key={a.id} article={a} delay={i * 80} />)}
</div>
</section>
{aiArticles.length > 0 && (
<section className="home-section" style={{ padding: '40px 0', borderTop: '2px solid #0F6B7318' }} aria-labelledby="ai-title">
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 8 }}>
<div style={{ width: 36, height: 36, borderRadius: 10, background: '#0F6B73', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ color: '#fff', fontSize: 16 }}>⚙</span>
</div>
<div>
<h2 id="ai-title" style={{ ...sectionTitle, margin: 0 }}>AI Engineering</h2>
<p style={{ ...sectionSubtitle, margin: 0 }}>Production AI systems, agents, and model infrastructure</p>
</div>
<button onClick={() => navigate('/category/ai')} style={{ marginLeft: 'auto', background: 'none', border: '1px solid #0F6B7340', color: '#0F6B73', fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'Inter,sans-serif', padding: '6px 14px', borderRadius: 999 }}>View section →</button>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 1, marginTop: 20 }}>
{aiArticles.map(a => <ArticleRowCompact key={a.id} article={a} />)}
</div>
</section>
)}
{securityArticles.length > 0 && (
<section className="home-section" style={{ padding: '40px 0', borderTop: '2px solid #C76D4A18' }} aria-labelledby="security-title">
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 8 }}>
<div style={{ width: 36, height: 36, borderRadius: 10, background: '#C76D4A', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ color: '#fff', fontSize: 16 }}>⚖</span>
</div>
<div>
<h2 id="security-title" style={{ ...sectionTitle, margin: 0 }}>Security & Legal</h2>
<p style={{ ...sectionSubtitle, margin: 0 }}>AI security, legal liability, and governance</p>
</div>
<button onClick={() => navigate('/category/security')} style={{ marginLeft: 'auto', background: 'none', border: '1px solid #C76D4A40', color: '#C76D4A', fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'Inter,sans-serif', padding: '6px 14px', borderRadius: 999 }}>View section →</button>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 1, marginTop: 20 }}>
{securityArticles.map(a => <ArticleRowCompact key={a.id} article={a} />)}
</div>
</section>
)}
<section className="home-section" style={{ padding: '40px 0' }} aria-labelledby="popular-title">
<h2 id="popular-title" style={sectionTitle}>Most Read</h2>
<p style={sectionSubtitle}>Teknav's most-read articles</p>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(280px,1fr))', gap: 20 }} className="article-grid">
{popular.map((a, i) => <ArticleCard key={a.id} article={a} delay={i * 100} />)}
</div>
</section>
<section className="home-section" style={{ padding: '40px 0' }} aria-labelledby="categories-title">
<h2 id="categories-title" style={sectionTitle}>Topics</h2>
<p style={sectionSubtitle}>Explore by area of expertise</p>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(200px,1fr))', gap: 12 }} className="categories-grid">
{categories.map(cat => (
<div key={cat.id} onClick={() => navigate('/category/' + cat.id)} style={{
background: '#fff', border: `1px solid ${cat.color}30`, borderRadius: 10, padding: '20px 16px',
cursor: 'pointer', transition: 'all 0.2s', borderLeft: `3px solid ${cat.color}`,
}} onMouseEnter={e => e.currentTarget.style.background = cat.color + '08'}
onMouseLeave={e => e.currentTarget.style.background = '#fff'}>
<div style={{ fontSize: 14, fontWeight: 700, color: '#263238', marginBottom: 4 }}>{cat.name}</div>
<div style={{ fontSize: 11, color: '#5F6B6D', marginBottom: 10 }}>{cat.description}</div>
<div style={{ fontSize: 11, color: cat.color, fontWeight: 600 }}>{allArticlesData.filter(a => a.category === cat.id).length} articles</div>
</div>
))}
</div>
</section>
<AuthorsSection />
<section style={{ padding: '40px 0 60px' }} aria-labelledby="newsletter-title">
<div className="newsletter-box" style={{ background: '#ebe3d2', borderRadius: 20, padding: '52px 32px', textAlign: 'center', position: 'relative', overflow: 'hidden', border: '1px solid rgba(15,42,46,0.06)' }}>
<div style={{ position: 'absolute', top: -80, left: -80, width: 280, height: 280, borderRadius: '50%', background: 'radial-gradient(circle, rgba(15,107,115,0.10) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', bottom: -60, right: -60, width: 220, height: 220, borderRadius: '50%', background: 'radial-gradient(circle, rgba(196,106,77,0.10) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'relative', zIndex: 1 }}>
<div style={{ fontSize: 22, marginBottom: 6, color: '#0F6B73' }}>✉</div>
<h2 id="newsletter-title" style={{ fontSize: 26, fontWeight: 800, color: '#0F2A2E', margin: '0 0 10px', fontFamily: 'Inter,sans-serif', letterSpacing: '-0.02em' }}>Subscribe to Teknav</h2>
<p style={{ fontSize: 14, color: '#4A5A5C', margin: '0 0 28px', lineHeight: 1.9, maxWidth: 520, marginLeft: 'auto', marginRight: 'auto' }}>Every week, Teknav's best analysis delivered straight to your inbox</p>
<NewsletterForm />
</div>
</div>
</section>
</div>
<style>{`
@media (max-width: 640px) {
.featured-card { grid-template-columns: 1fr !important; }
.stats-bar-inner { grid-template-columns: repeat(2, 1fr) !important; }
.article-grid { grid-template-columns: 1fr !important; }
.authors-grid { grid-template-columns: repeat(2, 1fr) !important; }
.categories-grid { grid-template-columns: repeat(2, 1fr) !important; }
.newsletter-box { padding: 36px 20px !important; }
}
`}</style>
</main>
);
}
export { ArticleCard, ArticleRowCompact, sectionTitle, sectionSubtitle };