pradit/pages/Home.tsx
2025-11-20 17:04:57 +07:00

700 lines
35 KiB
TypeScript

import React, { useState } from "react";
import { TerminalBlock } from "../components/TerminalBlock";
import {
ArrowRight,
Activity,
Search,
Database,
ChevronRight,
GitCommit,
BarChart,
Server,
Shield,
Box,
Cloud,
Layers,
Cpu,
Lock,
X,
Zap,
Globe,
} from "lucide-react";
import { Link } from "react-router-dom";
import { useLanguage } from "../App";
// Type definition for Projects
interface ProjectData {
id: string;
category: string;
title: string;
shortDesc: string;
fullDesc: string;
metrics: { label: string; value: string }[];
stack: string[];
architecture: string;
challenge: string;
}
export const Home: React.FC = () => {
const { language } = useLanguage();
const [selectedProject, setSelectedProject] = useState<ProjectData | null>(
null,
);
const content = {
en: {
new_research: "New Research: LoRA Without Regret",
hero_title: "Engineering Intelligence.",
hero_subtitle:
"We bridge the gap between research papers and production environments. Specialized consulting for LLM infrastructure, evaluation pipelines, and custom model adaptation.",
btn_services: "View Services",
btn_research: "Read Research",
latest_thinking: "Latest Thinking",
view_archive: "View Archive",
lora_desc:
"Fine-tuning large models is expensive. Low-rank adaptation (LoRA) promises efficiency, but does it sacrifice performance? Our deep dive into rank scaling and matrix initialization.",
technical_deep_dive: "Technical Deep Dive",
expertise_title: "Our Expertise",
process_title: "The Pipeline",
process_desc:
"We don't just write code; we engineer systems. Our engagement process is designed for transparency and velocity.",
projects_title: "Selected Deployments",
projects_desc:
"We don't sell hours. We sell shipped, production-grade systems. Click on a project to view the architecture.",
trusted_stack: "Built with Production Standards",
modal_stack: "Tech Stack",
modal_impact: "Business Impact",
modal_arch: "Architecture Highlight",
modal_challenge: "The Challenge",
close: "Close",
services: {
mvp: {
title: "MVP & Prototyping",
desc: "From concept to deployed model in weeks. We build robust POCs using the latest foundation models (Gemini, Claude, OpenAI) to validate business value before heavy investment.",
},
audit: {
title: "System Audit",
desc: "Why is your RAG pipeline hallucinating? We perform deep architectural audits, evaluating retrieval quality, prompt efficacy, and security vulnerabilities.",
},
integration: {
title: "Custom Integration",
desc: "Fine-tuning and integrating open-weights models into your secure infrastructure. We handle the MLOps so you own your weights and your data.",
},
},
learn_more: "Learn more",
process_steps: [
{
step: "01",
title: "Discovery & Audit",
desc: "We define the metric that matters. Is it latency? Accuracy? Cost?",
},
{
step: "02",
title: "Prototyping",
desc: "Rapid iteration using state-of-the-art models to validate feasibility.",
},
{
step: "03",
title: "Evaluation (Evals)",
desc: "We build a custom test suite (Pass@k, RAGAS) before we ship.",
},
{
step: "04",
title: "Production",
desc: "Containerization, CI/CD pipelines, and observability setup.",
},
],
stack: {
infra: "Infrastructure",
orchestration: "Orchestration",
inference: "Inference & Serving",
data: "Data & Vector Ops",
},
projects: [
{
id: "compliance",
category: "FinTech / Legal",
title: "ComplianceGuard AI",
shortDesc:
"Automated regulatory compliance checking for a Tier-1 bank. Reduced manual review time by 85% using a secure RAG pipeline.",
fullDesc:
"We architected a secure, on-premise Retrieval Augmented Generation (RAG) system that ingests thousands of changing regulatory documents (PDFs) and cross-references them with loan applications in real-time.",
challenge:
"The client was spending 2000+ man-hours monthly manually checking loan applications against constantly updating Bank of Thailand regulations. Privacy requirements prevented using public APIs.",
architecture:
'Hybrid-cloud setup. Sensitive data stays on-prem (OpenShift) using a fine-tuned Llama-3-70B for inference. Regulatory documents are indexed in Weaviate. LangChain orchestrates the "Reasoning" step to cite specific regulatory clauses.',
metrics: [
{ label: "Review Time", value: "-85%" },
{ label: "False Positives", value: "< 2%" },
{ label: "Cost Saving", value: "$45k/mo" },
],
stack: [
"Llama 3 70B",
"Weaviate",
"OpenShift",
"LangChain",
"Python",
],
},
{
id: "retail",
category: "E-Commerce",
title: "OmniFlow Agentic Router",
shortDesc:
"High-throughput customer support agent handling 50k+ daily tickets. Deflects 92% of queries with sub-2s latency.",
fullDesc:
"A sophisticated multi-agent system that acts as the first line of defense for a major e-commerce platform. It uses tool-calling to actually perform actions (check status, process refund) rather than just chatting.",
challenge:
'During "11.11" sales events, support volume spikes 10x. Traditional chatbots were too rigid, and human agents were overwhelmed. The system needed to be autonomous but safe.',
architecture:
'We built a Router Agent using GPT-4o-mini for speed. It classifies intent and routes to specialized Sub-Agents (Refund Agent, Logistics Agent). We implemented a "Human-in-the-loop" handover protocol for low-confidence scores.',
metrics: [
{ label: "Deflection Rate", value: "92%" },
{ label: "Avg Response", value: "1.2s" },
{ label: "CSAT Score", value: "4.8/5" },
],
stack: ["GPT-4o", "Redis", "FastAPI", "Kubernetes", "Postgres"],
},
],
},
th: {
new_research: "งานวิจัยใหม่: LoRA โดยไม่เสียใจ",
hero_title: "วิศวกรรมแห่งปัญญาประดิษฐ์",
hero_subtitle:
"เราเชื่อมช่องว่างระหว่างงานวิจัยทางวิชาการและการใช้งานจริง เชี่ยวชาญด้านโครงสร้างพื้นฐาน LLM, การประเมินผล และการปรับแต่งโมเดลตามความต้องการ",
btn_services: "ดูบริการของเรา",
btn_research: "อ่านงานวิจัย",
latest_thinking: "แนวคิดล่าสุด",
view_archive: "ดูบทความทั้งหมด",
lora_desc:
"การ Fine-tune โมเดลขนาดใหญ่มีค่าใช้จ่ายสูง LoRA สัญญาว่าจะเพิ่มประสิทธิภาพ แต่จะลดคุณภาพหรือไม่? เจาะลึกเรื่อง Rank scaling และการเริ่มต้น Matrix",
technical_deep_dive: "เจาะลึกทางเทคนิค",
expertise_title: "ความเชี่ยวชาญของเรา",
process_title: "กระบวนการทำงาน",
process_desc:
"เราไม่ได้แค่เขียนโค้ด แต่เราออกแบบระบบ กระบวนการของเราเน้นความโปร่งใสและความรวดเร็ว",
projects_title: "ผลงานที่ผ่านมา",
projects_desc:
"เราไม่ได้ขายชั่วโมงการทำงาน แต่เราส่งมอบระบบที่ใช้งานได้จริง คลิกที่โปรเจกต์เพื่อดูสถาปัตยกรรม",
trusted_stack: "สร้างด้วยมาตรฐานระดับ Production",
modal_stack: "Tech Stack",
modal_impact: "ผลลัพธ์ทางธุรกิจ",
modal_arch: "จุดเด่นของสถาปัตยกรรม",
modal_challenge: "ความท้าทาย",
close: "ปิด",
services: {
mvp: {
title: "MVP และต้นแบบ",
desc: "จากแนวคิดสู่โมเดลที่ใช้งานได้จริงในไม่กี่สัปดาห์ เราสร้าง POC ที่แข็งแกร่งด้วยโมเดลล่าสุด (Gemini, Claude, OpenAI) เพื่อตรวจสอบความคุ้มค่าก่อนการลงทุนจริง",
},
audit: {
title: "ตรวจสอบระบบ",
desc: "ทำไมระบบ RAG ของคุณถึงให้ข้อมูลผิด? เราตรวจสอบสถาปัตยกรรมอย่างละเอียด ประเมินคุณภาพการสืบค้น และช่องโหว่ด้านความปลอดภัย",
},
integration: {
title: "การรวมระบบตามสั่ง",
desc: "ปรับแต่ง (Fine-tune) และรวมโมเดล Open-weights เข้ากับโครงสร้างพื้นฐานที่ปลอดภัยของคุณ เราดูแล MLOps เพื่อให้คุณเป็นเจ้าของข้อมูลและโมเดลอย่างแท้จริง",
},
},
learn_more: "เรียนรู้เพิ่มเติม",
process_steps: [
{
step: "01",
title: "ค้นหา & ตรวจสอบ",
desc: "เรากำหนดตัวชี้วัดที่สำคัญที่สุด ไม่ว่าจะเป็น ความหน่วง ความแม่นยำ หรือต้นทุน",
},
{
step: "02",
title: "สร้างต้นแบบ",
desc: "ทำซ้ำอย่างรวดเร็วโดยใช้โมเดลล่าสุดเพื่อตรวจสอบความเป็นไปได้",
},
{
step: "03",
title: "การประเมินผล (Evals)",
desc: "เราสร้างชุดทดสอบเฉพาะ (Pass@k, RAGAS) ก่อนส่งมอบงาน",
},
{
step: "04",
title: "Production",
desc: "การทำ Containerization, ระบบ CI/CD และการติดตั้งระบบสังเกตการณ์",
},
],
stack: {
infra: "Infrastructure",
orchestration: "Orchestration",
inference: "Inference & Serving",
data: "Data & Vector Ops",
},
projects: [
{
id: "compliance",
category: "FinTech / Legal",
title: "ComplianceGuard AI",
shortDesc:
"ระบบตรวจสอบการปฏิบัติตามกฎระเบียบอัตโนมัติสำหรับธนาคารชั้นนำ ลดเวลาการตรวจสอบด้วยคนลง 85% โดยใช้ RAG pipeline ที่ปลอดภัย",
fullDesc:
"เราออกแบบระบบ Retrieval Augmented Generation (RAG) ภายในองค์กรที่ปลอดภัย ซึ่งนำเข้าเอกสารกฎระเบียบหลายพันฉบับที่เปลี่ยนแปลงตลอดเวลา และตรวจสอบเทียบกับคำขอสินเชื่อแบบเรียลไทม์",
challenge:
"ลูกค้าใช้เวลาคนทำงานกว่า 2,000 ชั่วโมงต่อเดือนในการตรวจสอบคำขอสินเชื่อด้วยตนเองเทียบกับกฎระเบียบธนาคารแห่งประเทศไทย ข้อกำหนดด้านความเป็นส่วนตัวไม่อนุญาตให้ใช้ Public API",
architecture:
'ระบบ Hybrid-cloud ข้อมูลสำคัญอยู่ภายในองค์กร (OpenShift) โดยใช้ Llama-3-70B ที่ปรับแต่งแล้ว เอกสารกฎระเบียบถูกจัดทำดัชนีใน Weaviate LangChain ควบคุมขั้นตอน "การให้เหตุผล" เพื่ออ้างอิงข้อกฎหมายเฉพาะ',
metrics: [
{ label: "เวลาตรวจสอบ", value: "-85%" },
{ label: "False Positives", value: "< 2%" },
{ label: "ประหยัดต้นทุน", value: "$45k/เดือน" },
],
stack: [
"Llama 3 70B",
"Weaviate",
"OpenShift",
"LangChain",
"Python",
],
},
{
id: "retail",
category: "E-Commerce",
title: "OmniFlow Agentic Router",
shortDesc:
"ระบบตอบรับลูกค้าความเร็วสูง รองรับ 50,000+ ตั๋วต่อวัน แก้ไขปัญหาอัตโนมัติได้ 92% ด้วยความเร็วต่ำกว่า 2 วินาที",
fullDesc:
"ระบบ Multi-agent อัจฉริยะที่ทำหน้าที่เป็นด่านหน้าสำหรับแพลตฟอร์มอีคอมเมิร์ซขนาดใหญ่ ใช้การเรียกใช้เครื่องมือ (Tool-calling) เพื่อดำเนินการจริง (ตรวจสอบสถานะ, คืนเงิน) แทนที่จะเป็นแค่การแชท",
challenge:
'ในช่วงเทศกาล "11.11" ปริมาณการติดต่อเพิ่มขึ้น 10 เท่า Chatbot แบบเดิมแข็งทื่อเกินไป และพนักงานรับมือไม่ไหว ระบบต้องทำงานอัตโนมัติแต่ปลอดภัย',
architecture:
'เราสร้าง Router Agent โดยใช้ GPT-4o-mini เพื่อความเร็ว โดยจำแนกเจตนาและส่งต่อไปยัง Agent เฉพาะทาง (Refund Agent, Logistics Agent) เราใช้โปรโตคอล "Human-in-the-loop" สำหรับเคสที่มีความมั่นใจต่ำ',
metrics: [
{ label: "อัตราการตอบกลับ", value: "92%" },
{ label: "ความเร็วเฉลี่ย", value: "1.2s" },
{ label: "คะแนน CSAT", value: "4.8/5" },
],
stack: ["GPT-4o", "Redis", "FastAPI", "Kubernetes", "Postgres"],
},
],
},
};
const t = content[language];
return (
<div className="flex flex-col">
{/* Hero Section */}
<section className="pt-24 pb-24 bg-paper border-b border-gray-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
<div>
<Link
to="/research/lora-without-regret"
className="inline-flex items-center space-x-2 mb-8 bg-blue-50 border border-blue-100 rounded-full px-4 py-1.5 text-xs font-bold uppercase tracking-widest text-accent hover:bg-blue-100 transition-colors"
>
<span className="w-2 h-2 rounded-full bg-accent animate-pulse"></span>
<span>{t.new_research}</span>
</Link>
<h1 className="font-serif text-5xl md:text-6xl text-ink leading-tight mb-8">
{t.hero_title}
</h1>
<p className="font-serif text-lg text-subtle mb-10 max-w-lg leading-relaxed">
{t.hero_subtitle}
</p>
<div className="flex flex-col sm:flex-row gap-4">
<Link
to="/services"
className="inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium text-white bg-ink hover:bg-gray-800 transition-all shadow-sm rounded-sm"
>
{t.btn_services}
</Link>
<Link
to="/research"
className="inline-flex items-center justify-center px-6 py-3 border border-gray-200 text-base font-medium text-ink bg-white hover:bg-gray-50 transition-all rounded-sm"
>
{t.btn_research}
</Link>
</div>
</div>
{/* Technical Trust Signal with Typing Effect */}
<div className="lg:pl-12">
<TerminalBlock
title="audit_pipeline.py"
typingEffect={true}
lines={[
"$ python run_evals.py --model=gemini-2.5-pro",
"# Loading dataset: humaneval_v2...",
"# Initializing sandbox environment...",
"> Running 164 test cases...",
"> Pass@1: 92.4% [OK]",
"> Latency (p99): 450ms [WARN]",
"# Optimization suggestion:",
"# Switch to batch inference or semantic caching.",
"$ _",
]}
className="transform lg:rotate-1 hover:rotate-0 transition-transform duration-500"
/>
</div>
</div>
</div>
</section>
{/* Trusted Stack / Logos (Revamped) */}
<section className="py-20 bg-gray-50 border-b border-gray-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
{/* Infrastructure */}
<div className="flex flex-col items-center text-center">
<div className="mb-4 p-3 bg-white rounded-full shadow-sm border border-gray-100">
<Cloud className="text-subtle" size={24} />
</div>
<h4 className="font-sans text-xs font-bold uppercase tracking-widest text-ink mb-2">
{t.stack.infra}
</h4>
<p className="font-mono text-xs text-subtle">
AWS, GCP, Azure, Terraform
</p>
</div>
{/* Orchestration */}
<div className="flex flex-col items-center text-center">
<div className="mb-4 p-3 bg-white rounded-full shadow-sm border border-gray-100">
<Box className="text-subtle" size={24} />
</div>
<h4 className="font-sans text-xs font-bold uppercase tracking-widest text-ink mb-2">
{t.stack.orchestration}
</h4>
<p className="font-mono text-xs text-subtle">
Kubernetes, Docker, Ray, Airflow
</p>
</div>
{/* Inference */}
<div className="flex flex-col items-center text-center">
<div className="mb-4 p-3 bg-white rounded-full shadow-sm border border-gray-100">
<Cpu className="text-subtle" size={24} />
</div>
<h4 className="font-sans text-xs font-bold uppercase tracking-widest text-ink mb-2">
{t.stack.inference}
</h4>
<p className="font-mono text-xs text-subtle">
vLLM, TorchServe, ONNX Runtime
</p>
</div>
{/* Data */}
<div className="flex flex-col items-center text-center">
<div className="mb-4 p-3 bg-white rounded-full shadow-sm border border-gray-100">
<Layers className="text-subtle" size={24} />
</div>
<h4 className="font-sans text-xs font-bold uppercase tracking-widest text-ink mb-2">
{t.stack.data}
</h4>
<p className="font-mono text-xs text-subtle">
Pinecone, Weaviate, Postgres, Redis
</p>
</div>
</div>
</div>
</section>
{/* Featured Research Snippet */}
<section className="py-24 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-baseline justify-between mb-12">
<h2 className="font-sans font-bold text-xs uppercase tracking-widest text-subtle">
{t.latest_thinking}
</h2>
<Link
to="/research"
className="group flex items-center text-sm font-serif text-ink hover:text-accent"
>
{t.view_archive}{" "}
<ArrowRight className="ml-2 w-4 h-4 group-hover:translate-x-1 transition-transform" />
</Link>
</div>
<Link to="/research/lora-without-regret" className="block group">
<article className="grid grid-cols-1 md:grid-cols-2 gap-12 border-t border-gray-100 pt-12">
<div>
<h3 className="font-serif text-3xl text-ink mb-4 group-hover:text-gray-600 transition-colors">
LoRA Without Regret
</h3>
<p className="font-serif text-subtle text-lg leading-relaxed mb-6">
{t.lora_desc}
</p>
<span className="text-xs font-sans font-bold uppercase text-accent">
{t.technical_deep_dive}
</span>
</div>
<div className="bg-gray-50 p-8 flex items-center justify-center border border-gray-100">
{/* Mini visualization for the teaser */}
<div className="grid grid-cols-12 gap-1 w-full max-w-xs opacity-50 group-hover:opacity-80 transition-opacity">
{[...Array(48)].map((_, i) => (
<div
key={i}
className="aspect-square bg-blue-500"
style={{ opacity: Math.random() }}
/>
))}
</div>
</div>
</article>
</Link>
</div>
</section>
{/* Services Preview */}
<section className="py-24 bg-paper border-t border-gray-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h2 className="font-sans font-bold text-xs uppercase tracking-widest text-subtle mb-16">
{t.expertise_title}
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{/* Service 1 */}
<div className="group p-8 border border-gray-200 bg-white hover:border-gray-400 transition-colors cursor-pointer relative overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition-opacity">
<Activity size={64} />
</div>
<h3 className="font-serif text-xl text-ink mb-4 font-bold">
{t.services.mvp.title}
</h3>
<p className="font-serif text-sm text-subtle leading-relaxed mb-8">
{t.services.mvp.desc}
</p>
<Link
to="/services"
className="inline-flex items-center text-xs font-bold uppercase tracking-wider text-ink group-hover:text-accent"
>
{t.learn_more} <ChevronRight size={16} className="ml-1" />
</Link>
</div>
{/* Service 2 */}
<div className="group p-8 border border-gray-200 bg-white hover:border-gray-400 transition-colors cursor-pointer relative overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition-opacity">
<Search size={64} />
</div>
<h3 className="font-serif text-xl text-ink mb-4 font-bold">
{t.services.audit.title}
</h3>
<p className="font-serif text-sm text-subtle leading-relaxed mb-8">
{t.services.audit.desc}
</p>
<Link
to="/services"
className="inline-flex items-center text-xs font-bold uppercase tracking-wider text-ink group-hover:text-accent"
>
{t.learn_more} <ChevronRight size={16} className="ml-1" />
</Link>
</div>
{/* Service 3 */}
<div className="group p-8 border border-gray-200 bg-white hover:border-gray-400 transition-colors cursor-pointer relative overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition-opacity">
<Database size={64} />
</div>
<h3 className="font-serif text-xl text-ink mb-4 font-bold">
{t.services.integration.title}
</h3>
<p className="font-serif text-sm text-subtle leading-relaxed mb-8">
{t.services.integration.desc}
</p>
<Link
to="/services"
className="inline-flex items-center text-xs font-bold uppercase tracking-wider text-ink group-hover:text-accent"
>
{t.learn_more} <ChevronRight size={16} className="ml-1" />
</Link>
</div>
</div>
</div>
</section>
{/* Process Pipeline Section */}
<section className="py-24 bg-[#1e1e1e] text-white overflow-hidden relative">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="mb-16 max-w-2xl">
<h2 className="font-sans font-bold text-xs uppercase tracking-widest text-green-400 mb-4">
{t.process_title}
</h2>
<p className="font-serif text-2xl text-gray-300">
{t.process_desc}
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{t.process_steps.map((step, idx) => (
<div key={idx} className="relative group">
<div className="w-12 h-12 rounded-full border border-gray-600 bg-gray-800 flex items-center justify-center font-mono text-sm font-bold mb-6 group-hover:border-green-400 group-hover:text-green-400 transition-colors">
{step.step}
</div>
<h3 className="font-bold text-lg mb-2">{step.title}</h3>
<p className="text-gray-400 font-serif text-sm leading-relaxed">
{step.desc}
</p>
{/* Connecting Line */}
{idx < 3 && (
<div className="hidden md:block absolute top-6 left-14 w-[calc(100%-3rem)] h-px bg-gray-800"></div>
)}
</div>
))}
</div>
</div>
</section>
{/* Featured Projects (Improved Enterprise) */}
<section className="py-24 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="mb-16 text-center max-w-3xl mx-auto">
<h2 className="font-sans font-bold text-xs uppercase tracking-widest text-subtle mb-4">
{t.projects_title}
</h2>
<p className="font-serif text-lg text-subtle">{t.projects_desc}</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
{t.projects.map((project) => (
<div
key={project.id}
onClick={() => setSelectedProject(project)}
className="border border-gray-200 rounded-sm hover:shadow-xl transition-all duration-300 p-8 bg-white flex flex-col cursor-pointer group hover:-translate-y-1"
>
<div className="mb-6 flex items-center justify-between">
<div className="flex items-center gap-3">
<div
className={`p-2 rounded-md ${project.id === "compliance" ? "bg-blue-50 text-accent" : "bg-purple-50 text-purple-600"}`}
>
{project.id === "compliance" ? (
<Lock size={24} />
) : (
<Zap size={24} />
)}
</div>
<span className="font-mono text-xs text-subtle uppercase tracking-widest">
{project.category}
</span>
</div>
<div className="opacity-0 group-hover:opacity-100 transition-opacity text-subtle">
<ArrowRight size={20} />
</div>
</div>
<h3 className="font-serif font-bold text-2xl text-ink mb-4">
{project.title}
</h3>
<p className="text-subtle font-serif text-base leading-relaxed mb-8 flex-grow">
{project.shortDesc}
</p>
<div className="grid grid-cols-3 gap-4 border-t border-gray-100 pt-6">
{project.metrics.map((metric, idx) => (
<div key={idx}>
<div className="font-mono text-lg font-bold text-ink">
{metric.value}
</div>
<div className="text-[10px] uppercase text-gray-400 font-sans font-bold">
{metric.label}
</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
</section>
{/* Project Modal */}
{selectedProject && (
<div className="fixed inset-0 z-[60] flex items-center justify-center p-4 md:p-8">
<div
className="absolute inset-0 bg-black/60 backdrop-blur-sm"
onClick={() => setSelectedProject(null)}
></div>
<div className="bg-white w-full max-w-4xl max-h-[90vh] overflow-y-auto rounded-lg shadow-2xl relative z-10 flex flex-col md:flex-row animate-in fade-in zoom-in duration-200">
{/* Modal Left: Overview */}
<div className="p-8 md:p-10 md:w-2/3">
<h2 className="font-serif text-3xl font-bold text-ink mb-2">
{selectedProject.title}
</h2>
<span className="font-mono text-xs uppercase tracking-widest text-accent mb-6 block">
{selectedProject.category}
</span>
<div className="space-y-8">
<div>
<h4 className="font-sans font-bold text-xs uppercase tracking-widest text-subtle mb-2">
{t.modal_challenge}
</h4>
<p className="font-serif text-subtle leading-relaxed">
{selectedProject.challenge}
</p>
</div>
<div>
<h4 className="font-sans font-bold text-xs uppercase tracking-widest text-subtle mb-2">
{t.modal_arch}
</h4>
<p className="font-serif text-ink leading-relaxed">
{selectedProject.architecture}
</p>
</div>
<div>
<h4 className="font-sans font-bold text-xs uppercase tracking-widest text-subtle mb-2">
{t.modal_impact}
</h4>
<div className="grid grid-cols-3 gap-4 bg-gray-50 p-4 rounded border border-gray-100">
{selectedProject.metrics.map((metric, idx) => (
<div key={idx}>
<div className="font-mono text-xl font-bold text-green-600">
{metric.value}
</div>
<div className="text-[10px] uppercase text-gray-400 font-sans font-bold">
{metric.label}
</div>
</div>
))}
</div>
</div>
</div>
</div>
{/* Modal Right: Stack */}
<div className="bg-[#1e1e1e] p-8 md:p-10 md:w-1/3 text-gray-300 border-l border-gray-800">
<button
onClick={() => setSelectedProject(null)}
className="absolute top-4 right-4 text-gray-400 hover:text-white"
>
<X size={24} />
</button>
<h3 className="font-sans font-bold text-xs uppercase tracking-widest text-gray-500 mb-6">
{t.modal_stack}
</h3>
<div className="space-y-3 font-mono text-sm">
{selectedProject.stack.map((tech, i) => (
<div
key={i}
className="flex items-center gap-3 pb-3 border-b border-gray-800 last:border-0"
>
<div className="w-1.5 h-1.5 rounded-full bg-green-500"></div>
{tech}
</div>
))}
</div>
<div className="mt-12 p-6 bg-gray-800/50 rounded border border-gray-700">
<Globe className="text-gray-500 mb-4" size={24} />
<p className="font-serif text-xs italic text-gray-400 leading-relaxed">
"Pradit delivered this system 2 weeks ahead of schedule. The
documentation was better than our internal standard."
</p>
<div className="mt-2 font-sans text-[10px] font-bold uppercase text-gray-500">
- CTO, Client Partner
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
};