# Project Directory Structure
/
├── .env.example
├── .gitignore
├── doc/
├── index.html
├── metadata.json
├── package-lock.json
├── package.json
├── tsconfig.json
├── vite.config.ts
└── src/
    ├── App.tsx
    ├── index.css
    ├── main.tsx
    ├── types.ts
    └── lib/
        └── utils.ts

---

# File: .env.example
# GEMINI_API_KEY: Required for Gemini AI API calls.
# AI Studio automatically injects this at runtime from user secrets.
# Users configure this via the Secrets panel in the AI Studio UI.
GEMINI_API_KEY="MY_GEMINI_API_KEY"

# APP_URL: The URL where this applet is hosted.
# AI Studio automatically injects this at runtime with the Cloud Run service URL.
# Used for self-referential links, OAuth callbacks, and API endpoints.
APP_URL="MY_APP_URL"

---

# File: .gitignore
node_modules/
build/
dist/
coverage/
.DS_Store
*.log
.env*
!.env.example

---

# File: index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Google AI Studio App</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

---

# File: metadata.json
{
  "name": "PentAGI 赛博作战中心",
  "description": "先进的 AI 驱动自主渗透测试与安全自动化平台，具备实时可视化功能。",
  "requestFramePermissions": []
}

---

# File: package.json
{
  "name": "react-example",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite --port=3000 --host=0.0.0.0",
    "build": "vite build",
    "preview": "vite preview",
    "clean": "rm -rf dist",
    "lint": "tsc --noEmit"
  },
  "dependencies": {
    "@google/genai": "^1.29.0",
    "@tailwindcss/vite": "^4.1.14",
    "@vitejs/plugin-react": "^5.0.4",
    "@xyflow/react": "^12.10.1",
    "clsx": "^2.1.1",
    "dotenv": "^17.2.3",
    "express": "^4.21.2",
    "lucide-react": "^0.546.0",
    "motion": "^12.38.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "recharts": "^3.8.0",
    "tailwind-merge": "^3.5.0",
    "vite": "^6.2.0"
  },
  "devDependencies": {
    "@types/express": "^4.17.21",
    "@types/node": "^22.14.0",
    "autoprefixer": "^10.4.21",
    "tailwindcss": "^4.1.14",
    "tsx": "^4.21.0",
    "typescript": "~5.8.2",
    "vite": "^6.2.0"
  }
}

---

# File: tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "experimentalDecorators": true,
    "useDefineForClassFields": false,
    "module": "ESNext",
    "lib": [
      "ES2022",
      "DOM",
      "DOM.Iterable"
    ],
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "isolatedModules": true,
    "moduleDetection": "force",
    "allowJs": true,
    "jsx": "react-jsx",
    "paths": {
      "@/*": [
        "./*"
      ]
    },
    "allowImportingTsExtensions": true,
    "noEmit": true
  }
}

---

# File: vite.config.ts
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import path from 'path';
import {defineConfig, loadEnv} from 'vite';

export default defineConfig(({mode}) => {
  const env = loadEnv(mode, '.', '');
  return {
    plugins: [react(), tailwindcss()],
    define: {
      'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY),
    },
    resolve: {
      alias: {
        '@': path.resolve(__dirname, '.'),
      },
    },
    server: {
      // HMR is disabled in AI Studio via DISABLE_HMR env var.
      // Do not modify—file watching is disabled to prevent flickering during agent edits.
      hmr: process.env.DISABLE_HMR !== 'true',
    },
  };
});

---

# File: src/index.css
@import "tailwindcss";

@theme {
  --color-cyber-bg: #050505;
  --color-cyber-panel: #0a0a0a;
  --color-cyber-accent: #00ff9f;
  --color-cyber-border: #1a1a1a;
  --color-cyber-text: #e0e0e0;
  --color-cyber-muted: #666666;
  
  --font-mono: "JetBrains Mono", "Fira Code", monospace;
}

@layer base {
  body {
    @apply bg-cyber-bg text-cyber-text font-mono overflow-hidden;
  }
}

.custom-scrollbar::-webkit-scrollbar {
  width: 4px;
  height: 4px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: transparent;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background: #1a1a1a;
  border-radius: 2px;
}

.custom-scrollbar::-webkit-scrollbar-thumb:hover {
  background: #00ff9f;
}

.neon-glow {
  text-shadow: 0 0 5px rgba(0, 255, 159, 0.5), 0 0 10px rgba(0, 255, 159, 0.3);
}

.neon-border {
  box-shadow: 0 0 5px rgba(0, 255, 159, 0.2);
  border-color: rgba(0, 255, 159, 0.3);
}

---

# File: src/main.tsx
import {StrictMode} from 'react';
import {createRoot} from 'react-dom/client';
import App from './App.tsx';
import './index.css';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
);

---

# File: src/types.ts
export interface Task {
  id: string;
  title: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  description?: string;
}

export interface Flow {
  id: string;
  name: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  progress: number;
  target: string;
  createdAt: string;
  duration?: string;
  agent?: string;
}

export interface Agent {
  id: string;
  name?: string;
  role: string;
  status: string;
  currentThought: string;
  tokenUsage: number;
}

export interface Action {
  id: string;
  timestamp: string;
  type: string;
  command: string;
  status: 'success' | 'failed' | 'running';
}

export interface Evidence {
  id: string;
  host: string;
  severity: 'Critical' | 'High' | 'Medium' | 'Low';
  cve?: string;
  poc: string;
  cvss: number;
  description?: string;
  timestamp?: string;
}

export interface Artifact {
  id: string;
  type: 'screenshot' | 'report' | 'log' | 'poc';
  url: string;
  title: string;
  timestamp: string;
  host?: string;
}

export interface Report {
  id: string;
  title: string;
  executiveSummary: string;
  recommendations: string;
  generatedAt: string;
  riskMatrix: {
    critical: number;
    high: number;
    medium: number;
    low: number;
  };
  findings: {
    id: string;
    cve?: string;
    host: string;
    severity: 'Critical' | 'High' | 'Medium' | 'Low';
    title: string;
  }[];
}

---

# File: src/lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

---

# File: src/App.tsx
import { 
  Activity, AlertTriangle, CheckCircle2, ChevronRight, 
  Clock, Cpu, Database, FileDown, FileText, 
  LayoutDashboard, List, Lock, Network, Play, 
  Search, Settings, Shield, Terminal as TerminalIcon, 
  Zap, Info, Pause, SkipForward, Upload, 
  ExternalLink, Eye, Download, Trash2, HelpCircle,
  Square, Command, User, BarChart3, Loader2, Check,
  Globe, Image as ImageIcon, Terminal
} from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import { 
  AreaChart, Area, XAxis, YAxis, CartesianGrid, 
  Tooltip as RechartsTooltip, ResponsiveContainer, 
  PieChart, Pie, Cell, Tooltip
} from 'recharts';
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { 
  Flow, Agent, Action, Evidence, Artifact, Report, Task 
} from './types';
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

// --- MOCK DATA ---
const MOCK_TASKS: Task[] = [
  { id: 't1', title: '解析拓扑结构', status: 'completed', description: '分析目标网络结构' },
  { id: 't2', title: '端口扫描 (Nmap)', status: 'completed', description: '探测开放端口与服务' },
  { id: 't3', title: 'Web 目录爆破', status: 'running', description: '寻找隐藏路径与后台' },
  { id: 't4', title: 'SQL 注入测试', status: 'pending', description: '验证输入点是否存在注入' },
  { id: 't5', title: '权限维持与提权', status: 'pending', description: '获取更高系统权限' },
];

const MOCK_FLOWS: Flow[] = [
  { id: 'F01', name: '靶机A-SQL注入实战', status: 'running', progress: 60, duration: '12m 30s', agent: 'WebSecAgent', target: '10.0.0.5', createdAt: '2026-03-20 09:00' },
  { id: 'F02', name: '公司内部网络拓扑扫描', status: 'completed', progress: 100, duration: '45m 00s', agent: 'Researcher', target: '192.168.1.0/24', createdAt: '2026-03-19 14:20' },
];

const MOCK_AGENTS: Agent[] = [
  { id: 'a1', name: 'Researcher', role: '侦察者', status: 'thinking', currentThought: '正在分析 Nmap 结果...发现 80 端口开放。', tokenUsage: 4500 },
  { id: 'a2', name: 'Executor', role: '执行者', status: 'idle', currentThought: '收到指令，正在启动 DirBuster 容器...', tokenUsage: 1200 },
  { id: 'a3', name: 'Analyzer', role: '代码分析师', status: 'idle', currentThought: '等待 Web 目录扫描结果进行深度分析。', tokenUsage: 8900 },
];

const MOCK_THOUGHTS = [
  { agent: 'Researcher', text: '思考：接下来应使用 DirBuster 探测隐藏路径，寻找后台登录入口。', timestamp: '14:23:01' },
  { agent: 'Executor', text: '收到指令，正在启动 DirBuster 容器... 目标: http://10.0.0.5/', timestamp: '14:23:05' },
  { agent: 'Researcher', text: '发现 /admin/login.php，这是一个高价值目标。', timestamp: '14:23:10' },
  { agent: 'Analyzer', text: '分析登录页面源码... 发现可能存在 SQL 注入的参数 "user"。', timestamp: '14:23:15' },
];

const MOCK_TERMINAL_LOGS = [
  'user@pentagi:~$ dirsearch -u http://10.0.0.5/ -e php',
  '[14:23:01] Starting: ',
  '[14:23:05] 200 -   12KB - /admin/login.php  <-- FOUND!',
  '[14:23:10] 200 -    5KB - /config.php',
  '[14:23:15] 403 -    1KB - /server-status',
  '[14:23:20] Task Completed.',
];

const MOCK_EVIDENCE: Evidence[] = [
  { id: 'e1', host: '10.0.0.5', severity: 'High', cvss: 8.5, description: '发现后台登录入口 /admin/login.php', poc: 'dirsearch -u http://10.0.0.5/' },
  { id: 'e2', host: '10.0.0.5', severity: 'Critical', cvss: 9.8, description: 'SQL 注入漏洞验证成功', poc: 'sqlmap -u "http://10.0.0.5/admin/login.php?user=admin"' },
];

const MOCK_ACTIONS: Action[] = [
  { id: 'a1', type: 'scan', command: 'nmap -sV 10.0.0.5', status: 'success', timestamp: '14:20:00' },
  { id: 'a2', type: 'exploit', command: 'dirsearch -u http://10.0.0.5/', status: 'success', timestamp: '14:23:01' },
  { id: 'a3', type: 'exploit', command: 'sqlmap -u "http://10.0.0.5/admin/login.php?user=admin"', status: 'running', timestamp: '14:25:10' },
];

const MOCK_ARTIFACTS: Artifact[] = [
  { id: 'art1', type: 'screenshot', url: 'https://picsum.photos/seed/pentest1/400/300', title: 'Admin Login Page', timestamp: '14:23:05' },
  { id: 'art2', type: 'log', url: '#', title: 'Nmap Scan Results', timestamp: '14:22:45' },
];

const RISK_DATA = [
  { name: '严重 (Critical)', value: 1, color: '#ff0000' },
  { name: '高危 (High)', value: 1, color: '#ff4400' },
  { name: '中危 (Medium)', value: 1, color: '#ffaa00' },
  { name: '低危 (Low)', value: 0, color: '#00ff00' },
];

const ACTIVITY_DATA = [
  { time: '09:00', actions: 12 },
  { time: '09:05', actions: 18 },
  { time: '09:10', actions: 45 },
  { time: '09:15', actions: 32 },
  { time: '09:20', actions: 67 },
  { time: '09:25', actions: 89 },
  { time: '09:30', actions: 54 },
];

const MOCK_REPORT: Report = {
  id: 'r1',
  title: '渗透测试报告 - 靶机A',
  executiveSummary: '本次测试发现目标系统存在严重 SQL 注入漏洞，可导致数据库完全泄露。系统补丁版本过低，且未开启 Web 应用防火墙。',
  riskMatrix: { critical: 1, high: 2, medium: 3, low: 5 },
  findings: [
    { id: 'f1', title: 'SQL 注入漏洞', severity: 'Critical', host: '10.0.0.5', cve: 'CVE-2024-1234' },
    { id: 'f2', title: '敏感目录泄露', severity: 'High', host: '10.0.0.5', cve: 'N/A' },
    { id: 'f3', title: 'SSH 弱口令', severity: 'Medium', host: '10.0.0.1', cve: 'N/A' },
  ],
  recommendations: '1. 修复 SQL 注入漏洞；2. 禁用不必要的服务；3. 实施强密码策略。',
  generatedAt: '2026-03-20 10:00',
};

const MOCK_REPORTS: Report[] = [
  { 
    id: 'r1', 
    title: '渗透测试报告 - 靶机A', 
    executiveSummary: '发现严重 SQL 注入漏洞...', 
    riskMatrix: { critical: 1, high: 2, medium: 3, low: 5 }, 
    generatedAt: '2026-03-20 10:00',
    findings: MOCK_REPORT.findings,
    recommendations: MOCK_REPORT.recommendations
  },
  { 
    id: 'r2', 
    title: '内部网络扫描报告', 
    executiveSummary: '网络结构分析完成，发现多处未授权访问点...', 
    riskMatrix: { critical: 0, high: 1, medium: 4, low: 12 }, 
    generatedAt: '2026-03-19 16:30',
    findings: [],
    recommendations: '建议加强网络隔离，定期进行资产盘点。'
  },
  { 
    id: 'r3', 
    title: 'Web 应用安全性评估', 
    executiveSummary: '针对核心 Web 业务的深度扫描结果...', 
    riskMatrix: { critical: 0, high: 0, medium: 2, low: 8 }, 
    generatedAt: '2026-03-18 09:15',
    findings: [],
    recommendations: '建议开启 WAF，并对敏感接口进行限流。'
  },
];

const MOCK_ASSETS = [
  { id: 'as1', ip: '10.0.0.5', hostname: 'web-server-01', os: 'Ubuntu 22.04', services: ['HTTP', 'SSH', 'MySQL'], status: 'vulnerable', lastSeen: '10分钟前' },
  { id: 'as2', ip: '10.0.0.1', hostname: 'gateway-router', os: 'Cisco IOS', services: ['SSH', 'SNMP'], status: 'secure', lastSeen: '2分钟前' },
  { id: 'as3', ip: '192.168.1.10', hostname: 'workstation-admin', os: 'Windows 11', services: ['RDP', 'SMB'], status: 'unknown', lastSeen: '1小时前' },
  { id: 'as4', ip: '10.0.0.10', hostname: 'db-master', os: 'CentOS 7', services: ['PostgreSQL', 'SSH'], status: 'secure', lastSeen: '5分钟前' },
];

const MOCK_VULNS = [
  { id: 'v1', title: 'SQL Injection in login.php', severity: 'Critical', cvss: 9.8, host: '10.0.0.5', status: 'confirmed', cve: 'CVE-2024-1234' },
  { id: 'v2', title: 'Weak SSH Password', severity: 'Medium', cvss: 5.5, host: '10.0.0.1', status: 'remediated', cve: 'N/A' },
  { id: 'v3', title: 'Outdated Apache Version', severity: 'High', cvss: 7.5, host: '10.0.0.5', status: 'confirmed', cve: 'CVE-2023-4567' },
  { id: 'v4', title: 'SMB Signing Not Required', severity: 'Low', cvss: 3.3, host: '192.168.1.10', status: 'detected', cve: 'CVE-2022-9999' },
];

// --- @xyflow/react setup ---
import { ReactFlow, Background, Controls, MiniMap, Node, Edge } from '@xyflow/react';
import '@xyflow/react/dist/style.css';

const initialNodes: Node[] = [
  { id: '1', position: { x: 0, y: 0 }, data: { label: '信息侦察 (Recon)' }, type: 'input', style: { background: '#00ff0020', color: '#00ff00', border: '1px solid #00ff00' } },
  { id: '2', position: { x: 0, y: 100 }, data: { label: '漏洞扫描 (Vuln)' }, style: { background: '#00ff0020', color: '#00ff00', border: '1px solid #00ff00' } },
  { id: '3', position: { x: -100, y: 200 }, data: { label: 'SQL 注入 (Exploit)' }, style: { background: '#ff000020', color: '#ff0000', border: '1px solid #ff0000' } },
  { id: '4', position: { x: 100, y: 200 }, data: { label: '目录爆破 (Exploit)' }, style: { background: '#00ff0020', color: '#00ff00', border: '1px solid #00ff00' } },
  { id: '5', position: { x: 0, y: 300 }, data: { label: '后渗透 (Post)' }, type: 'output', style: { background: '#333', color: '#666', border: '1px solid #333' } },
];

const initialEdges: Edge[] = [
  { id: 'e1-2', source: '1', target: '2', animated: true, style: { stroke: '#00ff00' } },
  { id: 'e2-3', source: '2', target: '3', animated: true, style: { stroke: '#ff0000' } },
  { id: 'e2-4', source: '2', target: '4', animated: true, style: { stroke: '#00ff00' } },
  { id: 'e3-5', source: '3', target: '5', style: { stroke: '#333' } },
  { id: 'e4-5', source: '4', target: '5', style: { stroke: '#333' } },
];

// --- Sub-Views ---

const DashboardView = ({ 
  activeFlow, 
  thinkingText, 
  setSelectedArtifact, 
  setExpandedActionId, 
  expandedActionId,
  sandboxStatus,
  sandboxError,
  runSandbox,
  setShowReport
}: any) => (
  <div className="flex-1 grid grid-cols-12 grid-rows-6 gap-4 overflow-hidden">
    {/* Agent Thinking & Chat */}
    <Panel title="智能体实时思考与对话" className="col-span-4 row-span-4" icon={Terminal} badge="实时">
      <div className="space-y-4 font-mono text-xs leading-relaxed">
        <div className="text-cyber-muted">[{new Date().toLocaleTimeString()}] 系统: 正在初始化多智能体编排...</div>
        <div className="text-cyber-accent whitespace-pre-wrap min-h-[3em]">
          {thinkingText}
          <span className="inline-block w-2 h-4 bg-cyber-accent animate-pulse ml-1 align-middle" />
        </div>
        
        <div className="space-y-4 pt-4 border-t border-cyber-border">
          {MOCK_THOUGHTS.map((thought, idx) => (
            <div key={idx} className="group">
              <div className="flex items-center gap-2 text-cyber-muted mb-1 group-hover:text-cyber-accent transition-colors">
                {thought.agent === 'Researcher' ? <Search size={10} /> : thought.agent === 'Executor' ? <Zap size={10} /> : <Cpu size={10} />}
                <span className="uppercase font-bold tracking-tighter text-[9px]">{thought.agent}</span>
                <span className="text-[8px] opacity-50 ml-auto">{thought.timestamp}</span>
              </div>
              <p className={cn(
                "text-cyber-text italic bg-white/5 p-2 rounded border-l-2 transition-all group-hover:bg-white/10",
                thought.agent === 'Researcher' ? "border-cyber-accent" : thought.agent === 'Executor' ? "border-red-500" : "border-blue-500"
              )}>
                {thought.text}
              </p>
            </div>
          ))}
        </div>
      </div>
    </Panel>

    {/* Attack Path Visualization */}
    <Panel title="攻击路径可视化" className="col-span-5 row-span-4" icon={Network}>
      <div className="h-full w-full bg-black/20 rounded-lg overflow-hidden border border-cyber-border/30 relative">
        <ReactFlow
          nodes={initialNodes}
          edges={initialEdges}
          fitView
          colorMode="dark"
          style={{ background: 'transparent' }}
        >
          <Background color="#00ff00" gap={20} size={1} opacity={0.1} />
          <Controls />
        </ReactFlow>
        <div className="absolute top-2 right-2 flex gap-2">
          <div className="flex items-center gap-1 text-[8px] uppercase font-bold text-emerald-500">
            <div className="w-1.5 h-1.5 rounded-full bg-emerald-500" /> 已完成
          </div>
          <div className="flex items-center gap-1 text-[8px] uppercase font-bold text-red-500">
            <div className="w-1.5 h-1.5 rounded-full bg-red-500" /> 高危
          </div>
        </div>
      </div>
    </Panel>

    {/* Risk Analysis */}
    <Panel title="风险矩阵分析" className="col-span-3 row-span-2" icon={AlertTriangle}>
      <div className="h-full flex flex-col gap-4">
        <div className="flex-1 min-h-[100px] relative">
          <ResponsiveContainer width="100%" height="100%">
            <PieChart>
              <Pie
                data={RISK_DATA}
                innerRadius={35}
                outerRadius={50}
                paddingAngle={5}
                dataKey="value"
                stroke="none"
              >
                {RISK_DATA.map((entry, index) => (
                  <Cell key={`cell-${index}`} fill={entry.color} />
                ))}
              </Pie>
              <Tooltip 
                contentStyle={{ backgroundColor: '#0a0a0a', border: '1px solid #1a1a1a', fontSize: '10px', borderRadius: '4px' }}
                itemStyle={{ color: '#fff' }}
              />
            </PieChart>
          </ResponsiveContainer>
          <div className="absolute inset-0 flex flex-col items-center justify-center pointer-events-none">
            <span className="text-xs font-bold text-white">3</span>
            <span className="text-[7px] text-cyber-muted uppercase">总漏洞</span>
          </div>
        </div>
        <div className="overflow-auto max-h-[120px] custom-scrollbar">
          <table className="w-full text-[9px] text-left border-collapse">
            <thead>
              <tr className="text-cyber-muted border-b border-cyber-border">
                <th className="pb-2 font-bold uppercase tracking-tighter">目标主机</th>
                <th className="pb-2 font-bold uppercase tracking-tighter">风险等级</th>
                <th className="pb-2 font-bold uppercase tracking-tighter text-right">CVSS</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-white/5">
              {MOCK_EVIDENCE.map((ev) => (
                <tr key={ev.id} className="hover:bg-white/5 transition-colors group">
                  <td className="py-2 font-mono text-cyber-accent group-hover:text-white transition-colors">{ev.host}</td>
                  <td className="py-2">
                    <div className="flex items-center gap-1.5">
                      <div className={cn(
                        "w-1 h-1 rounded-full",
                        ev.severity === 'Critical' ? "bg-red-500" : "bg-orange-500"
                      )} />
                      <span className={cn(
                        "font-bold",
                        ev.severity === 'Critical' ? "text-red-500" : "text-orange-500"
                      )}>{ev.severity === 'Critical' ? '严重' : '高危'}</span>
                    </div>
                  </td>
                  <td className="py-2 text-right font-mono text-cyber-muted">{ev.cvss}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </Panel>

    {/* Evidence Gallery */}
    <Panel title="证据与截图画廊" className="col-span-3 row-span-2" icon={ImageIcon}>
      <div className="flex flex-col h-full gap-3">
        <div className="flex-1 overflow-x-auto flex gap-4 pb-2 custom-scrollbar">
          {MOCK_ARTIFACTS.map((art) => (
            <div 
              key={art.id} 
              onClick={() => setSelectedArtifact(art)}
              className="group relative rounded-lg overflow-hidden border border-cyber-border w-48 shrink-0 aspect-[16/10] cursor-pointer bg-black/40"
            >
              {art.type === 'screenshot' ? (
                <img src={art.url} alt={art.title} className="w-full h-full object-cover grayscale group-hover:grayscale-0 transition-all duration-700 scale-105 group-hover:scale-100" referrerPolicy="no-referrer" />
              ) : (
                <div className="w-full h-full flex flex-col items-center justify-center bg-white/5 group-hover:bg-white/10 transition-colors">
                  {art.type === 'log' ? <TerminalIcon size={24} className="text-cyber-muted group-hover:text-cyber-accent" /> : <FileText size={24} className="text-cyber-muted group-hover:text-cyber-accent" />}
                  <span className="text-[8px] mt-2 text-cyber-muted uppercase font-bold">{art.type}</span>
                </div>
              )}
              <div className="absolute inset-0 bg-gradient-to-t from-black/95 via-black/40 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-500 flex flex-col justify-end p-3">
                <div className="text-[9px] font-bold uppercase tracking-wider text-cyber-accent mb-1 truncate">{art.title}</div>
                <div className="text-[7px] text-cyber-muted flex items-center gap-2">
                  <Globe size={8} /> {art.host || '10.0.0.5'}
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </Panel>

    {/* Activity Chart */}
    <Panel title="智能体活动频率" className="col-span-3 row-span-2" icon={BarChart3}>
      <div className="h-full flex flex-col">
        <div className="flex-1">
          <ResponsiveContainer width="100%" height="100%">
            <AreaChart data={ACTIVITY_DATA}>
              <defs>
                <linearGradient id="colorActions" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="5%" stopColor="#00ff00" stopOpacity={0.3}/>
                  <stop offset="95%" stopColor="#00ff00" stopOpacity={0}/>
                </linearGradient>
              </defs>
              <Area type="monotone" dataKey="actions" stroke="#00ff00" fillOpacity={1} fill="url(#colorActions)" />
              <Tooltip 
                contentStyle={{ backgroundColor: '#0a0a0a', border: '1px solid #1a1a1a', fontSize: '10px', borderRadius: '4px' }}
                itemStyle={{ color: '#00ff00' }}
              />
            </AreaChart>
          </ResponsiveContainer>
        </div>
      </div>
    </Panel>

    {/* Real-time Timeline (Vertical) */}
    <Panel title="实时操作流水" className="col-span-3 row-span-2" icon={Activity}>
      <div className="relative pl-4 border-l border-cyber-border space-y-4">
        {MOCK_ACTIONS.map((action) => (
          <div key={action.id} className="relative">
            <div className={cn(
              "absolute -left-[21px] top-1 w-3 h-3 rounded-full border-2 border-cyber-bg z-10",
              action.status === 'success' ? "bg-cyber-accent" : action.status === 'running' ? "bg-yellow-500 animate-pulse" : "bg-red-500"
            )} />
            <div className="flex flex-col gap-1">
              <div className="flex items-center justify-between">
                <span className="text-[10px] font-bold text-cyber-accent uppercase">{action.type}</span>
                <span className="text-[8px] text-cyber-muted font-mono">{action.timestamp}</span>
              </div>
              <div className="text-[9px] text-cyber-text font-mono truncate bg-white/5 p-1 rounded">
                $ {action.command}
              </div>
              <div className="flex items-center gap-2">
                <span className={cn(
                  "text-[7px] px-1 rounded font-bold uppercase",
                  action.status === 'success' ? "text-cyber-accent" : "text-yellow-500"
                )}>
                  {action.status === 'success' ? 'SUCCESS' : 'RUNNING'}
                </span>
              </div>
            </div>
          </div>
        ))}
      </div>
    </Panel>

    {/* PoC Sandbox & Report Card */}
    <div className="col-span-6 row-span-2 grid grid-cols-2 gap-4">
      <Panel title="PoC 验证沙箱" icon={Terminal} badge={sandboxStatus === 'idle' ? '待命' : sandboxStatus === 'running' ? '运行中' : sandboxStatus === 'success' ? '成功' : '失败'}>
        <div className="flex flex-col h-full gap-2">
          <div className="flex-1 bg-black/40 rounded border border-cyber-border p-2 font-mono text-[9px] overflow-auto">
            <div className="text-cyber-accent"># 正在验证 CVE-2024-1234</div>
            {sandboxStatus === 'running' && (
              <div className="flex items-center gap-2 mt-2 text-cyber-accent animate-pulse">
                <Loader2 size={10} className="animate-spin" />
                <span>正在执行利用脚本...</span>
              </div>
            )}
            {sandboxStatus === 'success' && (
              <div className="mt-2 text-cyber-accent flex items-center gap-1">
                <Check size={10} /> 利用成功！已获得反弹 Shell。
              </div>
            )}
            {sandboxStatus === 'failed' && (
              <div className="mt-2 text-red-500 flex items-center gap-1">
                <AlertTriangle size={10} /> {sandboxError || '利用失败。'}
              </div>
            )}
          </div>
          <div className="flex gap-2">
            <button 
              onClick={runSandbox}
              disabled={sandboxStatus === 'running'}
              className={cn(
                "flex-1 py-1.5 rounded text-[9px] font-bold flex items-center justify-center gap-1 transition-all",
                sandboxStatus === 'running' ? "bg-white/5 text-cyber-muted cursor-not-allowed" : "bg-cyber-accent text-black hover:brightness-110"
              )}
            >
              {sandboxStatus === 'running' ? <Loader2 size={10} className="animate-spin" /> : <Play size={10} fill="currentColor" />}
              {sandboxStatus === 'failed' ? '重试沙箱' : '运行沙箱'}
            </button>
          </div>
        </div>
      </Panel>

      <Panel title="渗透测试报告预览" icon={FileText}>
        <div className="flex flex-col h-full gap-2">
          <div className="flex-1 space-y-2 overflow-auto">
            <div className="text-[10px] text-cyber-text font-bold mb-1">{MOCK_REPORT.title}</div>
            <div className="grid grid-cols-4 gap-1 mb-2">
              {[
                { label: '严重', count: MOCK_REPORT.riskMatrix.critical, color: 'bg-red-500' },
                { label: '高危', count: MOCK_REPORT.riskMatrix.high, color: 'bg-orange-500' },
                { label: '中危', count: MOCK_REPORT.riskMatrix.medium, color: 'bg-yellow-500' },
                { label: '低危', count: MOCK_REPORT.riskMatrix.low, color: 'bg-emerald-500' },
              ].map((r, i) => (
                <div key={i} className="bg-black/40 p-1 rounded border border-white/5 text-center">
                  <div className={`w-1 h-1 rounded-full ${r.color} mx-auto mb-0.5`} />
                  <div className="text-[6px] text-cyber-muted uppercase">{r.label}</div>
                  <div className="text-[10px] font-bold">{r.count}</div>
                </div>
              ))}
            </div>
            <div className="text-[8px] text-cyber-muted line-clamp-2 italic">
              {MOCK_REPORT.executiveSummary}
            </div>
          </div>
          <button 
            onClick={() => setShowReport(true)}
            className="w-full py-1.5 bg-cyber-accent text-black rounded text-[9px] font-bold hover:brightness-110 transition-all flex items-center justify-center gap-2"
          >
            <FileDown size={12} /> 下载 PDF 报告
          </button>
        </div>
      </Panel>
    </div>
  </div>
);

const GraphView = ({ selectedNode, setSelectedNode, filter, setFilter }: any) => (
  <div className="flex-1 flex gap-4 overflow-hidden">
    <div className="flex-1 bg-cyber-panel/30 border border-cyber-border rounded-xl overflow-hidden relative">
      <div className="absolute top-4 left-4 z-10 flex gap-2">
        {['all', 'host', 'service', 'vuln'].map((f) => (
          <button 
            key={f}
            onClick={() => setFilter(f)}
            className={cn(
              "px-3 py-1.5 rounded-md text-[10px] font-bold uppercase tracking-widest transition-all border",
              filter === f ? "bg-cyber-accent text-black border-cyber-accent" : "bg-black/60 text-cyber-muted border-cyber-border hover:border-cyber-accent/50"
            )}
          >
            {f === 'all' ? '全部' : f === 'host' ? '主机' : f === 'service' ? '服务' : '漏洞'}
          </button>
        ))}
      </div>
      <ReactFlow
        nodes={initialNodes}
        edges={initialEdges}
        onNodeClick={(_, node) => setSelectedNode(node)}
        fitView
        colorMode="dark"
      >
        <Background color="#00ff00" gap={20} size={1} opacity={0.1} />
        <Controls />
        <MiniMap nodeColor={(n) => (n.style?.background as string) || '#333'} />
      </ReactFlow>
    </div>
    
    <AnimatePresence>
      {selectedNode && (
        <motion.div 
          initial={{ x: 300, opacity: 0 }}
          animate={{ x: 0, opacity: 1 }}
          exit={{ x: 300, opacity: 0 }}
          className="w-80 bg-cyber-panel border border-cyber-border rounded-xl p-6 flex flex-col gap-6"
        >
          <div className="flex items-center justify-between">
            <h3 className="text-lg font-bold text-cyber-accent tracking-tighter">节点详情</h3>
            <button onClick={() => setSelectedNode(null)} className="p-1 hover:bg-white/10 rounded">
              <Square size={16} className="text-cyber-muted" />
            </button>
          </div>
          
          <div className="space-y-4">
            <div>
              <div className="text-[10px] text-cyber-muted uppercase font-bold mb-1">名称</div>
              <div className="text-sm font-bold text-white">{selectedNode.data.label}</div>
            </div>
            <div>
              <div className="text-[10px] text-cyber-muted uppercase font-bold mb-1">类型</div>
              <div className="text-xs text-cyber-accent font-mono">ENTITY_NODE</div>
            </div>
            <div>
              <div className="text-[10px] text-cyber-muted uppercase font-bold mb-1">关联属性</div>
              <div className="space-y-2">
                <div className="bg-black/40 p-2 rounded border border-white/5 text-[10px]">
                  <span className="text-cyber-muted">IP:</span> <span className="text-white font-mono">10.0.0.5</span>
                </div>
                <div className="bg-black/40 p-2 rounded border border-white/5 text-[10px]">
                  <span className="text-cyber-muted">OS:</span> <span className="text-white font-mono">Ubuntu Linux</span>
                </div>
              </div>
            </div>
          </div>
          
          <div className="mt-auto">
            <button className="w-full py-2 bg-cyber-accent text-black font-bold rounded text-xs hover:brightness-110 transition-all">
              启动深度扫描
            </button>
          </div>
        </motion.div>
      )}
    </AnimatePresence>
  </div>
);

const AgentsView = ({ expandedAgentId, setExpandedAgentId }: any) => (
  <div className="flex-1 overflow-auto custom-scrollbar">
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      {MOCK_AGENTS.map((agent) => (
        <motion.div 
          key={agent.id}
          layout
          className="bg-cyber-panel border border-cyber-border rounded-xl p-6 hover:border-cyber-accent/30 transition-all group"
        >
          <div className="flex items-center justify-between mb-6">
            <div className="flex items-center gap-3">
              <div className={cn(
                "w-3 h-3 rounded-full shadow-[0_0_10px_rgba(0,0,0,0.5)]",
                agent.status === 'thinking' ? "bg-cyber-accent animate-pulse shadow-cyber-accent/50" : "bg-cyber-muted"
              )} />
              <div>
                <h3 className="font-bold text-white group-hover:text-cyber-accent transition-colors">{agent.name}</h3>
                <div className="text-[10px] text-cyber-muted uppercase font-bold tracking-widest">{agent.role}</div>
              </div>
            </div>
            <div className="text-right">
              <div className="text-[9px] text-cyber-muted uppercase font-bold">Token</div>
              <div className="text-xs font-mono text-cyber-accent">{agent.tokenUsage.toLocaleString()}</div>
            </div>
          </div>
          
          <div className="space-y-4">
            <div className="bg-black/40 p-3 rounded-lg border border-white/5 italic text-xs text-cyber-text leading-relaxed">
              "{agent.currentThought}"
            </div>
            
            <div>
              <div className="flex justify-between text-[9px] text-cyber-muted mb-1 uppercase font-bold">
                <span>任务进度</span>
                <span>75%</span>
              </div>
              <div className="h-1.5 w-full bg-white/5 rounded-full overflow-hidden">
                <div className="h-full bg-cyber-accent w-3/4 shadow-[0_0_10px_#00ff00]" />
              </div>
            </div>
            
            <button 
              onClick={() => setExpandedAgentId(expandedAgentId === agent.id ? null : agent.id)}
              className="w-full py-2 bg-white/5 border border-cyber-border rounded-lg text-[10px] font-bold text-cyber-muted hover:text-cyber-accent hover:border-cyber-accent/50 transition-all flex items-center justify-center gap-2"
            >
              <Terminal size={12} /> {expandedAgentId === agent.id ? '隐藏日志' : '查看详细日志'}
            </button>
            
            <AnimatePresence>
              {expandedAgentId === agent.id && (
                <motion.div 
                  initial={{ height: 0, opacity: 0 }}
                  animate={{ height: 'auto', opacity: 1 }}
                  exit={{ height: 0, opacity: 0 }}
                  className="overflow-hidden"
                >
                  <div className="mt-4 bg-black/60 p-4 rounded-lg border border-cyber-border/50 font-mono text-[10px] text-cyber-muted space-y-2 max-h-48 overflow-auto custom-scrollbar">
                    <div>[14:20:05] 初始化连接至目标: 10.0.0.5</div>
                    <div>[14:21:12] 正在执行 Nmap 扫描...</div>
                    <div className="text-cyber-accent">[14:22:45] 扫描完成。发现 3 个开放端口。</div>
                    <div>[14:23:01] 正在启动 Web 目录爆破...</div>
                    <div className="text-red-500">[14:23:05] 发现敏感路径: /admin/login.php</div>
                    <div>[14:23:10] 正在分析登录页面源码...</div>
                  </div>
                </motion.div>
              )}
            </AnimatePresence>
          </div>
        </motion.div>
      ))}
    </div>
  </div>
);

const ReportsView = ({ setShowReport }: any) => (
  <div className="flex-1 overflow-auto custom-scrollbar">
    <div className="grid grid-cols-1 gap-4">
      {MOCK_REPORTS.map((report) => (
        <div key={report.id} className="bg-cyber-panel border border-cyber-border rounded-xl p-6 hover:border-cyber-accent/30 transition-all group flex items-center justify-between">
          <div className="flex items-center gap-4">
            <div className="w-12 h-12 rounded-lg bg-cyber-accent/10 flex items-center justify-center text-cyber-accent">
              <FileText size={24} />
            </div>
            <div>
              <h3 className="font-bold text-white group-hover:text-cyber-accent transition-colors">{report.title}</h3>
              <div className="text-[10px] text-cyber-muted uppercase font-bold tracking-widest mt-1">生成时间: {report.generatedAt}</div>
            </div>
          </div>
          <div className="flex items-center gap-8">
            <div className="flex gap-2">
              <div className="text-center px-3">
                <div className="text-[8px] text-red-500 font-bold uppercase">严重</div>
                <div className="text-sm font-mono">{report.riskMatrix.critical}</div>
              </div>
              <div className="text-center px-3 border-l border-white/5">
                <div className="text-[8px] text-orange-500 font-bold uppercase">高危</div>
                <div className="text-sm font-mono">{report.riskMatrix.high}</div>
              </div>
            </div>
            <div className="flex gap-2">
              <button 
                onClick={() => setShowReport(true)}
                className="px-4 py-2 bg-white/5 border border-cyber-border rounded text-[10px] font-bold text-cyber-muted hover:text-cyber-accent hover:border-cyber-accent/50 transition-all flex items-center gap-2"
              >
                <Eye size={14} /> 预览
              </button>
              <button className="px-4 py-2 bg-cyber-accent text-black rounded text-[10px] font-bold hover:brightness-110 transition-all flex items-center gap-2">
                <Download size={14} /> 下载
              </button>
            </div>
          </div>
        </div>
      ))}
    </div>
  </div>
);

const AssetsView = () => (
  <div className="flex-1 overflow-auto custom-scrollbar bg-cyber-panel/30 border border-cyber-border rounded-xl">
    <table className="w-full text-left border-collapse">
      <thead>
        <tr className="text-cyber-muted border-b border-cyber-border bg-white/5">
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">IP 地址</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">主机名</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">操作系统</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">开放服务</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">安全状态</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">最后在线</th>
        </tr>
      </thead>
      <tbody className="divide-y divide-white/5">
        {MOCK_ASSETS.map((asset) => (
          <tr key={asset.id} className="hover:bg-white/5 transition-colors group">
            <td className="p-4 font-mono text-cyber-accent text-xs">{asset.ip}</td>
            <td className="p-4 text-xs font-bold text-white">{asset.hostname}</td>
            <td className="p-4 text-xs text-cyber-muted">{asset.os}</td>
            <td className="p-4">
              <div className="flex gap-1 flex-wrap">
                {asset.services.map(s => (
                  <span key={s} className="px-1.5 py-0.5 rounded bg-white/5 border border-white/10 text-[8px] text-cyber-muted">{s}</span>
                ))}
              </div>
            </td>
            <td className="p-4">
              <div className="flex items-center gap-2">
                <div className={cn(
                  "w-1.5 h-1.5 rounded-full",
                  asset.status === 'vulnerable' ? "bg-red-500 shadow-[0_0_5px_#ef4444]" : 
                  asset.status === 'secure' ? "bg-emerald-500 shadow-[0_0_5px_#10b981]" : "bg-cyber-muted"
                )} />
                <span className={cn(
                  "text-[10px] font-bold uppercase",
                  asset.status === 'vulnerable' ? "text-red-500" : 
                  asset.status === 'secure' ? "text-emerald-500" : "text-cyber-muted"
                )}>
                  {asset.status === 'vulnerable' ? '存在漏洞' : asset.status === 'secure' ? '安全' : '未知'}
                </span>
              </div>
            </td>
            <td className="p-4 text-[10px] text-cyber-muted font-mono">{asset.lastSeen}</td>
          </tr>
        ))}
      </tbody>
    </table>
  </div>
);

const VulnerabilitiesView = () => (
  <div className="flex-1 overflow-auto custom-scrollbar bg-cyber-panel/30 border border-cyber-border rounded-xl">
    <table className="w-full text-left border-collapse">
      <thead>
        <tr className="text-cyber-muted border-b border-cyber-border bg-white/5">
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">漏洞名称</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">危险等级</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">CVSS</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">受影响主机</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">CVE 编号</th>
          <th className="p-4 text-[10px] font-bold uppercase tracking-widest">状态</th>
        </tr>
      </thead>
      <tbody className="divide-y divide-white/5">
        {MOCK_VULNS.map((vuln) => (
          <tr key={vuln.id} className="hover:bg-white/5 transition-colors group">
            <td className="p-4 text-xs font-bold text-white group-hover:text-cyber-accent transition-colors">{vuln.title}</td>
            <td className="p-4">
              <div className="flex items-center gap-2">
                <div className={cn(
                  "w-1.5 h-1.5 rounded-full",
                  vuln.severity === 'Critical' ? "bg-red-500" : 
                  vuln.severity === 'High' ? "bg-orange-500" : "bg-yellow-500"
                )} />
                <span className={cn(
                  "text-[10px] font-bold uppercase",
                  vuln.severity === 'Critical' ? "text-red-500" : 
                  vuln.severity === 'High' ? "text-orange-500" : "text-yellow-500"
                )}>
                  {vuln.severity === 'Critical' ? '严重' : vuln.severity === 'High' ? '高危' : '中危'}
                </span>
              </div>
            </td>
            <td className="p-4 font-mono text-xs">{vuln.cvss}</td>
            <td className="p-4 font-mono text-xs text-cyber-muted">{vuln.host}</td>
            <td className="p-4 font-mono text-xs text-cyber-muted">{vuln.cve}</td>
            <td className="p-4">
              <span className={cn(
                "px-2 py-0.5 rounded text-[8px] font-bold uppercase border",
                vuln.status === 'confirmed' ? "bg-red-500/10 border-red-500/30 text-red-500" : 
                vuln.status === 'remediated' ? "bg-emerald-500/10 border-emerald-500/30 text-emerald-500" : "bg-white/5 border-white/10 text-cyber-muted"
              )}>
                {vuln.status === 'confirmed' ? '已确认' : vuln.status === 'remediated' ? '已修复' : '已探测'}
              </span>
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  </div>
);

const Panel = ({ title, children, className, icon: Icon, badge }: any) => (
  <div className={cn("bg-cyber-panel/50 border border-cyber-border rounded-xl flex flex-col overflow-hidden backdrop-blur-sm group hover:border-cyber-accent/30 transition-all", className)}>
    <div className="px-4 py-3 border-b border-cyber-border flex items-center justify-between bg-white/5">
      <div className="flex items-center gap-2">
        {Icon && <Icon size={14} className="text-cyber-accent group-hover:scale-110 transition-transform" />}
        <h3 className="text-[10px] font-bold uppercase tracking-widest text-cyber-muted group-hover:text-cyber-accent transition-colors">{title}</h3>
      </div>
      {badge && (
        <span className="px-1.5 py-0.5 rounded bg-cyber-accent/10 text-cyber-accent text-[8px] font-black uppercase tracking-tighter border border-cyber-accent/20">
          {badge}
        </span>
      )}
    </div>
    <div className="flex-1 p-4 overflow-auto custom-scrollbar">
      {children}
    </div>
  </div>
);

const ConceptTooltip = ({ concept, explanation, text }: { concept: string; explanation: string; text: string }) => {
  const [show, setShow] = useState(false);
  return (
    <span className="relative inline-block">
      <span 
        className="underline decoration-cyber-accent/30 decoration-dotted cursor-help hover:text-cyber-accent transition-colors"
        onMouseEnter={() => setShow(true)}
        onMouseLeave={() => setShow(false)}
      >
        {text}
      </span>
      <AnimatePresence>
        {show && (
          <motion.div 
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: 10 }}
            className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-48 p-2 bg-zinc-900 border border-cyber-accent rounded text-[10px] z-50 shadow-xl"
          >
            <div className="font-bold text-cyber-accent mb-1">{concept}</div>
            <div className="text-cyber-muted leading-relaxed">{explanation}</div>
          </motion.div>
        )}
      </AnimatePresence>
    </span>
  );
};

export default function App() {
  const [command, setCommand] = useState('');
  const [activeView, setActiveView] = useState<'dashboard' | 'graph' | 'agents' | 'reports' | 'assets' | 'vulns' | 'settings'>('dashboard');
  const [isSidebarExpanded, setIsSidebarExpanded] = useState(true);
  const [teachingMode, setTeachingMode] = useState(true);
  const [selectedArtifact, setSelectedArtifact] = useState<Artifact | null>(null);
  const [expandedActionId, setExpandedActionId] = useState<string | null>(null);
  const [sandboxStatus, setSandboxStatus] = useState<'idle' | 'running' | 'success' | 'failed'>('idle');
  const [sandboxError, setSandboxError] = useState<string | null>(null);
  const [showReport, setShowReport] = useState(false);
  const [activeFlow, setActiveFlow] = useState(MOCK_FLOWS[0]);
  const [thinkingText, setThinkingText] = useState('');
  const [fullThinkingText, setFullThinkingText] = useState('正在分析目标系统的网络拓扑结构...');
  const [notifications, setNotifications] = useState<{ id: string; text: string; type: 'info' | 'success' | 'error' }[]>([]);
  const [selectedNode, setSelectedNode] = useState<any>(null);
  const [graphFilter, setGraphFilter] = useState<'all' | 'host' | 'service' | 'vuln'>('all');
  const [expandedAgentId, setExpandedAgentId] = useState<string | null>(null);

  const addNotification = (text: string, type: 'info' | 'success' | 'error' = 'info') => {
    const id = Math.random().toString(36).substring(7);
    setNotifications(prev => [...prev, { id, text, type }]);
    setTimeout(() => {
      setNotifications(prev => prev.filter(n => n.id !== id));
    }, 5000);
  };

  const runSandbox = () => {
    setSandboxStatus('running');
    setSandboxError(null);
    addNotification('正在启动沙箱环境...', 'info');
    
    // Simulate potential failure
    const shouldFail = Math.random() > 0.8;
    
    setTimeout(() => {
      if (shouldFail) {
        setSandboxStatus('failed');
        setSandboxError('利用脚本执行超时或目标防御机制拦截。');
        addNotification('沙箱验证失败！', 'error');
      } else {
        setSandboxStatus('success');
        setShowReport(true);
        addNotification('PoC 验证通过！漏洞已确认。', 'success');
      }
    }, 3000);
  };

  const handleCommand = (e: React.FormEvent) => {
    e.preventDefault();
    if (!command.trim()) return;
    
    addNotification(`正在解析指令: "${command}"`, 'info');
    
    if (command.includes('扫描') || command.includes('scan')) {
      addNotification('已启动新扫描流程', 'success');
    } else if (command.includes('报告') || command.includes('report')) {
      setShowReport(true);
      addNotification('正在生成最新报告...', 'info');
    }
    
    setCommand('');
  };

  useEffect(() => {
    const texts = [
      '正在扫描开放端口...',
      '发现 80/tcp 端口开放，正在识别服务版本...',
      '识别到 Apache/2.4.41 (Ubuntu)...',
      '正在启动目录爆破工具...',
      '发现敏感目录 /admin/login.php...',
      '正在尝试 SQL 注入攻击向量...',
    ];
    let i = 0;
    const interval = setInterval(() => {
      setFullThinkingText(texts[i % texts.length]);
      i++;
    }, 4000);
    return () => clearInterval(interval);
  }, []);

  useEffect(() => {
    let currentText = '';
    let i = 0;
    const typingInterval = setInterval(() => {
      if (i < fullThinkingText.length) {
        currentText += fullThinkingText[i];
        setThinkingText(currentText);
        i++;
      } else {
        clearInterval(typingInterval);
      }
    }, 50);
    return () => clearInterval(typingInterval);
  }, [fullThinkingText]);

  return (
    <div className="h-screen w-screen flex flex-col bg-cyber-bg text-cyber-text selection:bg-cyber-accent selection:text-black">
      {/* Top Bar */}
      <header className="h-14 border-b border-cyber-border flex items-center px-6 justify-between bg-cyber-panel/50 backdrop-blur-md z-50">
        <div className="flex items-center gap-4">
          <div className="flex items-center gap-2">
            <div className="w-8 h-8 bg-cyber-accent rounded flex items-center justify-center text-black font-black italic shadow-[0_0_15px_rgba(0,255,0,0.4)]">P</div>
            <span className="font-bold tracking-tighter text-xl neon-glow">PentAGI</span>
          </div>
          <div className="h-4 w-[1px] bg-cyber-border mx-2" />
          <div className="flex items-center gap-3 text-[10px] text-cyber-muted uppercase tracking-widest">
            <div className="flex items-center gap-1.5">
              <Activity size={12} className="text-cyber-accent animate-pulse" />
              <span>5 个智能体活跃</span>
            </div>
            <span className="opacity-30">|</span>
            <div className="flex items-center gap-1.5">
              <Cpu size={12} />
              <span>Qwen2.5-32B</span>
            </div>
          </div>
        </div>

        <form onSubmit={handleCommand} className="flex-1 max-w-2xl mx-8 flex gap-2 relative group">
          <div className="relative flex-1">
            <Command className="absolute left-3 top-1/2 -translate-y-1/2 text-cyber-muted group-focus-within:text-cyber-accent transition-colors" size={16} />
            <input 
              type="text"
              placeholder="Cmd+K: '对 192.168.1.0/24 进行全面渗透测试'..."
              className="w-full bg-white/5 border border-cyber-border rounded-md py-2 pl-10 pr-4 text-sm focus:outline-none focus:border-cyber-accent/50 focus:ring-1 focus:ring-cyber-accent/20 transition-all placeholder:text-cyber-muted/50"
              value={command}
              onChange={(e) => setCommand(e.target.value)}
            />
            <div className="absolute right-3 top-1/2 -translate-y-1/2 flex gap-1">
              <kbd className="px-1.5 py-0.5 rounded bg-white/10 text-[10px] text-cyber-muted border border-white/10">⌘</kbd>
              <kbd className="px-1.5 py-0.5 rounded bg-white/10 text-[10px] text-cyber-muted border border-white/10">K</kbd>
            </div>
          </div>
          <button type="button" className="px-3 py-2 bg-white/5 border border-cyber-border rounded-md text-cyber-muted hover:text-cyber-accent hover:border-cyber-accent/50 transition-all flex items-center gap-2 text-xs font-bold">
            <Upload size={14} />
            <span>上传文档</span>
          </button>
        </form>

        <div className="flex items-center gap-6">
          <div className="flex items-center gap-3 bg-white/5 border border-cyber-border rounded-full px-3 py-1">
            <span className="text-[9px] text-cyber-muted uppercase font-bold tracking-tighter">教学模式</span>
            <button 
              onClick={() => setTeachingMode(!teachingMode)}
              className={cn(
                "w-8 h-4 rounded-full relative transition-all duration-300",
                teachingMode ? "bg-cyber-accent" : "bg-white/10"
              )}
            >
              <motion.div 
                animate={{ x: teachingMode ? 16 : 2 }}
                className="absolute top-1 w-2 h-2 rounded-full bg-black shadow-sm"
              />
            </button>
          </div>
          <div className="flex gap-4">
            <div className="text-right">
              <div className="text-[9px] text-cyber-muted uppercase font-bold">总 Token 消耗</div>
              <div className="text-sm font-mono text-cyber-accent leading-none">18,742</div>
            </div>
            <div className="text-right">
              <div className="text-[9px] text-cyber-muted uppercase font-bold">已发现漏洞</div>
              <div className="text-sm font-mono text-red-500 leading-none">27</div>
            </div>
          </div>
          <button className="p-2 hover:bg-white/5 rounded-full transition-colors">
            <Settings size={20} className="text-cyber-muted" />
          </button>
          <div className="w-8 h-8 rounded-full bg-gradient-to-br from-cyber-accent to-emerald-900 border border-cyber-accent/50 flex items-center justify-center text-[10px] font-bold text-black">AD</div>
        </div>
      </header>

      <main className="flex-1 flex overflow-hidden relative">
        {/* Sidebar */}
        <motion.nav 
          initial={false}
          animate={{ width: isSidebarExpanded ? 220 : 64 }}
          onMouseEnter={() => setIsSidebarExpanded(true)}
          onMouseLeave={() => setIsSidebarExpanded(false)}
          className="hidden md:flex border-r border-cyber-border flex-col items-start py-6 gap-4 bg-cyber-panel/30 transition-all duration-300 overflow-hidden z-40"
        >
          {[
            { id: 'dashboard', icon: LayoutDashboard, label: '仪表盘' },
            { id: 'graph', icon: Network, label: '知识图谱' },
            { id: 'agents', icon: Shield, label: '智能体' },
            { id: 'reports', icon: FileText, label: '报告中心' },
            { id: 'assets', icon: Globe, label: '资产清单' },
            { id: 'vulns', icon: Database, label: '漏洞库' },
            { id: 'settings', icon: Settings, label: '设置' },
          ].map((item) => (
            <button 
              key={item.id} 
              onClick={() => setActiveView(item.id as any)}
              className={cn(
                "w-full px-4 py-3 flex items-center gap-4 transition-all group relative",
                activeView === item.id ? "text-cyber-accent" : "text-cyber-muted hover:text-cyber-text"
              )}
            >
              <div className={cn(
                "p-1 rounded-lg transition-all",
                activeView === item.id ? "bg-cyber-accent/10" : "group-hover:bg-white/5"
              )}>
                <item.icon size={22} />
              </div>
              <motion.span 
                initial={false}
                animate={{ opacity: isSidebarExpanded ? 1 : 0, x: isSidebarExpanded ? 0 : -10 }}
                className="text-xs font-bold whitespace-nowrap"
              >
                {item.label}
              </motion.span>
              {activeView === item.id && <div className="absolute left-0 top-1/4 bottom-1/4 w-1 bg-cyber-accent rounded-r shadow-[0_0_10px_#00ff00]" />}
            </button>
          ))}
        </motion.nav>

        {/* Mobile Bottom Tab Bar */}
        <nav className="md:hidden fixed bottom-0 left-0 right-0 h-16 bg-cyber-panel/90 backdrop-blur-md border-t border-cyber-border flex items-center justify-around z-50 px-2">
          {[
            { icon: LayoutDashboard, active: true },
            { icon: Network },
            { icon: Shield },
            { icon: Globe },
            { icon: Database },
          ].map((item, idx) => (
            <button key={idx} className={cn(
              "p-2 rounded-lg transition-all",
              item.active ? "text-cyber-accent bg-cyber-accent/10" : "text-cyber-muted"
            )}>
              <item.icon size={20} />
            </button>
          ))}
        </nav>

        {/* Content Area */}
        <div className="flex-1 flex flex-col p-4 gap-4 overflow-hidden">
          {/* Top Row: Flow Info & Controls */}
          <div className="flex items-center justify-between bg-cyber-panel/50 border border-cyber-border p-4 rounded-lg backdrop-blur-sm relative overflow-hidden">
            <div className="absolute top-0 left-0 w-1 h-full bg-cyber-accent shadow-[0_0_10px_#00ff00]" />
            <div className="flex items-center gap-4">
              <div>
                <div className="text-[10px] text-cyber-muted uppercase font-bold tracking-widest">当前任务流程</div>
                <div className="text-lg font-bold flex items-center gap-2">
                  {activeFlow.name}
                  <span className="px-2 py-0.5 rounded bg-cyber-accent/20 text-cyber-accent text-[10px] uppercase font-bold border border-cyber-accent/30 animate-pulse">
                    正在运行
                  </span>
                </div>
              </div>
              <div className="h-8 w-[1px] bg-cyber-border mx-4" />
              <div className="w-64">
                <div className="flex justify-between text-[10px] text-cyber-muted mb-1">
                  <span>执行进度: {MOCK_TASKS.find(t => t.status === 'running')?.title || '正在分析'}</span>
                  <span className="text-cyber-accent">{activeFlow.progress}%</span>
                </div>
                <div className="h-1.5 w-full bg-white/5 rounded-full overflow-hidden">
                  <motion.div 
                    initial={{ width: 0 }}
                    animate={{ width: `${activeFlow.progress}%` }}
                    transition={{ duration: 1, ease: "easeOut" }}
                    className="h-full bg-cyber-accent shadow-[0_0_10px_#00ff00]"
                  />
                </div>
              </div>
              <div className="h-8 w-[1px] bg-cyber-border mx-4" />
              <div className="flex gap-6">
                <div>
                  <div className="text-[9px] text-cyber-muted uppercase font-bold">目标资产</div>
                  <div className="text-xs font-mono text-cyber-accent">{activeFlow.target}</div>
                </div>
                <div>
                  <div className="text-[9px] text-cyber-muted uppercase font-bold">已用时间</div>
                  <div className="text-xs font-mono">01:42:05</div>
                </div>
              </div>
            </div>
            <div className="flex gap-2">
              <button className="flex items-center gap-2 px-4 py-2 bg-cyber-accent text-black font-bold rounded hover:brightness-110 transition-all text-xs shadow-[0_0_15px_rgba(0,255,0,0.3)]">
                <Square size={14} fill="currentColor" /> 停止全部
              </button>
              <button className="flex items-center gap-2 px-4 py-2 bg-white/5 border border-cyber-border text-cyber-text font-bold rounded hover:bg-white/10 transition-all text-xs">
                <Download size={14} /> 导出追踪
              </button>
            </div>
          </div>

          {/* Conditional View Rendering */}
          <AnimatePresence mode="wait">
            <motion.div
              key={activeView}
              initial={{ opacity: 0, y: 10 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -10 }}
              transition={{ duration: 0.2 }}
              className="flex-1 flex flex-col overflow-hidden"
            >
              {activeView === 'dashboard' && (
                <DashboardView 
                  activeFlow={activeFlow}
                  thinkingText={thinkingText}
                  setSelectedArtifact={setSelectedArtifact}
                  setExpandedActionId={setExpandedActionId}
                  expandedActionId={expandedActionId}
                  sandboxStatus={sandboxStatus}
                  sandboxError={sandboxError}
                  runSandbox={runSandbox}
                  setShowReport={setShowReport}
                />
              )}
              {activeView === 'graph' && (
                <GraphView 
                  selectedNode={selectedNode}
                  setSelectedNode={setSelectedNode}
                  filter={graphFilter}
                  setFilter={setGraphFilter}
                />
              )}
              {activeView === 'agents' && (
                <AgentsView 
                  expandedAgentId={expandedAgentId}
                  setExpandedAgentId={setExpandedAgentId}
                />
              )}
              {activeView === 'reports' && (
                <ReportsView setShowReport={setShowReport} />
              )}
              {activeView === 'assets' && (
                <AssetsView />
              )}
              {activeView === 'vulns' && (
                <VulnerabilitiesView />
              )}
              {activeView === 'settings' && (
                <div className="flex-1 flex items-center justify-center bg-black/20 border border-cyber-border rounded-xl border-dashed">
                  <div className="text-center">
                    <div className="text-cyber-accent text-4xl font-black italic mb-2 opacity-20">PENTAGI</div>
                    <div className="text-cyber-muted text-xs uppercase tracking-widest font-bold">设置模块正在开发中...</div>
                  </div>
                </div>
              )}
            </motion.div>
          </AnimatePresence>

          {/* Full Report Overlay/Section */}
          <AnimatePresence>
            {showReport && (
              <motion.div 
                initial={{ opacity: 0, scale: 0.95 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.95 }}
                className="fixed inset-0 z-[100] flex items-center justify-center p-8 bg-black/80 backdrop-blur-xl"
              >
                <div className="w-full max-w-5xl max-h-[90vh] bg-cyber-panel border border-cyber-accent/50 rounded-xl flex flex-col overflow-hidden shadow-[0_0_50px_rgba(0,255,0,0.2)]">
                  <div className="px-6 py-4 border-b border-cyber-border flex items-center justify-between bg-cyber-accent/10">
                    <div className="flex items-center gap-3">
                      <FileText className="text-cyber-accent" />
                      <h2 className="text-xl font-bold tracking-tighter neon-glow">{MOCK_REPORT.title}</h2>
                    </div>
                    <button onClick={() => setShowReport(false)} className="p-2 hover:bg-white/10 rounded-full transition-colors">
                      <Square size={20} className="text-cyber-muted" />
                    </button>
                  </div>
                  
                  <div className="flex-1 overflow-auto p-8 space-y-8 custom-scrollbar">
                    {/* Executive Summary */}
                    <section>
                      <h3 className="text-cyber-accent font-bold uppercase tracking-widest text-xs mb-4 flex items-center gap-2">
                        <Info size={14} /> 执行摘要
                      </h3>
                      <p className="text-cyber-text leading-relaxed bg-white/5 p-4 rounded border-l-4 border-cyber-accent">
                        {MOCK_REPORT.executiveSummary}
                      </p>
                    </section>
                    
                    {/* Risk Matrix */}
                    <section className="grid grid-cols-4 gap-4">
                      {[
                        { label: '严重 (Critical)', count: MOCK_REPORT.riskMatrix?.critical, color: 'bg-red-600' },
                        { label: '高危 (High)', count: MOCK_REPORT.riskMatrix?.high, color: 'bg-orange-600' },
                        { label: '中危 (Medium)', count: MOCK_REPORT.riskMatrix?.medium, color: 'bg-yellow-600' },
                        { label: '低危 (Low)', count: MOCK_REPORT.riskMatrix?.low, color: 'bg-emerald-600' },
                      ].map((item, idx) => (
                        <div key={idx} className="bg-white/5 border border-cyber-border p-4 rounded-lg text-center group hover:border-cyber-accent/50 transition-all">
                          <div className={cn("w-2 h-2 rounded-full mx-auto mb-2", item.color)} />
                          <div className="text-[10px] text-cyber-muted uppercase font-bold mb-1">{item.label}</div>
                          <div className="text-3xl font-mono font-bold text-white group-hover:text-cyber-accent transition-colors">{item.count}</div>
                        </div>
                      ))}
                    </section>
                    
                    {/* Key Findings */}
                    <section>
                      <h3 className="text-cyber-accent font-bold uppercase tracking-widest text-xs mb-4 flex items-center gap-2">
                        <List size={14} /> 关键发现
                      </h3>
                      <div className="space-y-4">
                        {MOCK_REPORT.findings?.map((finding) => (
                          <div key={finding.id} className="bg-white/5 border border-cyber-border p-4 rounded-lg flex items-center justify-between group hover:bg-white/10 transition-all">
                            <div className="flex items-center gap-4">
                              <div className={cn(
                                "w-10 h-10 rounded-lg flex items-center justify-center font-bold text-xs",
                                finding.severity === 'Critical' ? "bg-red-500/20 text-red-500" : "bg-orange-500/20 text-orange-500"
                              )}>
                                {finding.severity[0]}
                              </div>
                              <div>
                                <div className="font-bold text-cyber-text">{finding.title}</div>
                                <div className="text-[10px] text-cyber-muted font-mono">{finding.host} • {finding.cve}</div>
                              </div>
                            </div>
                            <button className="p-2 text-cyber-muted hover:text-cyber-accent transition-colors">
                              <ChevronRight size={20} />
                            </button>
                          </div>
                        ))}
                      </div>
                    </section>
                    
                    {/* Recommendations */}
                    <section>
                      <h3 className="text-cyber-accent font-bold uppercase tracking-widest text-xs mb-4 flex items-center gap-2">
                        <Shield size={14} /> 修复建议
                      </h3>
                      <div className="bg-blue-500/10 border border-blue-500/30 p-4 rounded-lg text-blue-400 text-sm leading-relaxed">
                        {MOCK_REPORT.recommendations}
                      </div>
                    </section>
                  </div>
                  
                  <div className="px-6 py-4 border-t border-cyber-border bg-black/40 flex justify-end gap-3">
                    <button className="px-6 py-2 bg-white/5 border border-cyber-border rounded font-bold text-xs hover:bg-white/10 transition-all">
                      取消
                    </button>
                    <button className="px-6 py-2 bg-cyber-accent text-black font-bold rounded flex items-center gap-2 text-xs shadow-[0_0_15px_rgba(0,255,0,0.3)] hover:brightness-110 transition-all">
                      <FileDown size={14} /> 下载 PDF 报告
                    </button>
                  </div>
                </div>
              </motion.div>
            )}
          </AnimatePresence>

          {/* Footer Status Bar */}
          <footer className="h-8 border-t border-cyber-border flex items-center px-4 justify-between bg-cyber-panel/50 text-[9px] font-mono text-cyber-muted uppercase tracking-tighter">
            <div className="flex items-center gap-6">
              <div className="flex items-center gap-1.5">
                <div className="w-1.5 h-1.5 rounded-full bg-cyber-accent shadow-[0_0_5px_#00ff00]" />
                <span>Neo4j 同步: 正常</span>
              </div>
              <div className="flex items-center gap-1.5">
                <Database size={10} />
                <span>数据库延迟: 12ms</span>
              </div>
              <div className="flex items-center gap-1.5">
                <Cpu size={10} />
                <span>GPU 负载: 42%</span>
              </div>
            </div>
            <div className="flex items-center gap-6">
              <span>系统版本: v2.4.0-stable</span>
              <span className="text-cyber-accent">© 2026 PENTAGI CYBER OPS</span>
            </div>
          </footer>
        </div>
      </main>

      {/* Artifact Detail Modal */}
      <AnimatePresence>
        {selectedArtifact && (
          <motion.div 
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-[110] flex items-center justify-center p-8 bg-black/90 backdrop-blur-md"
            onClick={() => setSelectedArtifact(null)}
          >
            <motion.div 
              initial={{ scale: 0.9, y: 20 }}
              animate={{ scale: 1, y: 0 }}
              exit={{ scale: 0.9, y: 20 }}
              className="max-w-4xl w-full bg-cyber-panel border border-cyber-accent/30 rounded-xl overflow-hidden shadow-[0_0_50px_rgba(0,255,0,0.1)]"
              onClick={(e) => e.stopPropagation()}
            >
              <div className="px-6 py-4 border-b border-cyber-border flex items-center justify-between">
                <div className="flex items-center gap-3">
                  <ImageIcon className="text-cyber-accent" size={18} />
                  <h3 className="font-bold text-cyber-text">{selectedArtifact.title}</h3>
                </div>
                <button onClick={() => setSelectedArtifact(null)} className="p-2 hover:bg-white/10 rounded-full transition-colors">
                  <Square size={18} className="text-cyber-muted" />
                </button>
              </div>
              <div className="p-6">
                {selectedArtifact.type === 'screenshot' ? (
                  <img src={selectedArtifact.url} alt={selectedArtifact.title} className="w-full rounded-lg border border-cyber-border shadow-2xl" referrerPolicy="no-referrer" />
                ) : (
                  <div className="bg-black/40 p-6 rounded-lg border border-cyber-border font-mono text-xs text-cyber-muted leading-relaxed max-h-[50vh] overflow-auto custom-scrollbar">
                    <div className="text-cyber-accent mb-4">--- {selectedArtifact.type.toUpperCase()} 内容 ---</div>
                    <pre>{`[2026-03-20 14:22:45] INFO: Starting Nmap 7.80 ( https://nmap.org ) at 2026-03-20 14:22 UTC
1322: Nmap scan report for 10.0.0.5
1323: Host is up (0.00045s latency).
1324: Not shown: 997 closed ports
1325: PORT     STATE SERVICE VERSION
1326: 22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
1327: 80/tcp   open  http    Apache httpd 2.4.41 ((Ubuntu))
1328: 3306/tcp open  mysql   MySQL 8.0.19-0ubuntu5

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.52 seconds`}</pre>
                  </div>
                )}
                <div className="mt-6 flex items-center justify-between">
                  <div className="flex gap-6 text-[10px] text-cyber-muted uppercase font-bold tracking-widest">
                    <div className="flex flex-col">
                      <span className="opacity-50">类型</span>
                      <span className="text-cyber-accent">{selectedArtifact.type}</span>
                    </div>
                    <div className="flex flex-col">
                      <span className="opacity-50">主机</span>
                      <span className="text-cyber-accent">{selectedArtifact.host || '10.0.0.5'}</span>
                    </div>
                    <div className="flex flex-col">
                      <span className="opacity-50">时间戳</span>
                      <span className="text-cyber-accent">{selectedArtifact.timestamp}</span>
                    </div>
                  </div>
                  <div className="flex gap-3">
                    <button className="px-4 py-2 bg-white/5 border border-cyber-border rounded text-xs font-bold hover:bg-white/10 transition-all flex items-center gap-2">
                      <Trash2 size={14} /> 删除
                    </button>
                    <button className="px-6 py-2 bg-cyber-accent text-black font-bold rounded text-xs shadow-[0_0_15px_rgba(0,255,0,0.3)] hover:brightness-110 transition-all flex items-center gap-2">
                      <Download size={14} /> 下载原始文件
                    </button>
                  </div>
                </div>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>

      {/* Notifications */}
      <div className="fixed bottom-12 right-6 z-[120] flex flex-col gap-2 pointer-events-none">
        <AnimatePresence>
          {notifications.map(n => (
            <motion.div
              key={n.id}
              initial={{ opacity: 0, x: 50 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: 50 }}
              className={cn(
                "px-4 py-3 rounded-lg border shadow-xl flex items-center gap-3 min-w-[240px] pointer-events-auto",
                n.type === 'success' ? "bg-emerald-900/80 border-emerald-500/50 text-emerald-100" :
                n.type === 'error' ? "bg-red-900/80 border-red-500/50 text-red-100" :
                "bg-zinc-900/80 border-cyber-accent/50 text-cyber-accent"
              )}
            >
              {n.type === 'success' ? <CheckCircle2 size={16} /> : n.type === 'error' ? <AlertTriangle size={16} /> : <Info size={16} />}
              <span className="text-xs font-bold">{n.text}</span>
            </motion.div>
          ))}
        </AnimatePresence>
      </div>
    </div>
  );
}


