/**
 * Edos AI - 统一CSS变量系统 v1.0.0
 * 消除styles_modern.css和styles_enhanced.css的变量冲突
 * 设计原则：单一来源、语义清晰、向后兼容
 */

:root {
  /* ============================================================
     主色调 (Primary Colors)
     ============================================================ */
  --edos-primary: #00d4ff;
  --edos-primary-dark: #0099cc;
  --edos-primary-light: #66e0ff;
  --edos-accent: #a855f7;
  --edos-accent-dark: #7c3aed;
  --edos-accent-light: #c084fc;
  
  /* 功能色 (Functional Colors) */
  --edos-success: #22c55e;
  --edos-warning: #f59e0b;
  --edos-error: #ef4444;
  --edos-info: #3b82f6;
  
  /* 语义色 (Semantic Colors) */
  --edos-cyan: #38bdf8;
  --edos-purple: #a78bfa;
  --edos-pink: #f472b6;
  --edos-green: #4ade80;
  --edos-red: #f87171;
  --edos-orange: #fb923c;

  /* ============================================================
     背景色 (Background Colors) - 亮色主题为默认
     ============================================================ */
  --edos-bg-primary: #ffffff;
  --edos-bg-secondary: #f8fafc;
  --edos-bg-tertiary: #f1f5f9;
  --edos-bg-card: rgba(255, 255, 255, 0.92);
  --edos-bg-elevated: rgba(255, 255, 255, 0.98);
  --edos-bg-hover: rgba(0, 0, 0, 0.06);
  --edos-bg-glass: rgba(255, 255, 255, 0.85);
  --edos-bg-subtle: rgba(0, 0, 0, 0.03);
  --edos-bg-pressed: rgba(0, 0, 0, 0.1);
  --edos-input-bg: rgba(255, 255, 255, 0.95);
  --edos-overlay-dark: rgba(0, 0, 0, 0.55);
  
  /* ============================================================
     文字色 (Text Colors) - 符合WCAG AA对比度标准(4.5:1+)
     ============================================================ */
  --edos-text-primary: #111827;
  --edos-text-secondary: #4b5563;
  --edos-text-tertiary: #6b7280;
  --edos-text-dim: #9ca3af;
  --edos-text-main: #111827;
  --edos-text-muted: #9ca3af;

  /* ============================================================
     边框色 (Border Colors)
     ============================================================ */
  --edos-border-default: rgba(0, 0, 0, 0.08);
  --edos-border-hover: rgba(0, 0, 0, 0.15);
  --edos-border-active: rgba(56, 189, 248, 0.5);
  --edos-border-glow: rgba(56, 189, 248, 0.15);
  --edos-border-subtle: rgba(0, 0, 0, 0.06);

  /* ============================================================
     阴影 (Shadows)
     ============================================================ */
  --edos-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --edos-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --edos-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
  --edos-shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
  --edos-shadow-glow-accent: 0 0 20px rgba(167, 139, 250, 0.1);

  /* ============================================================
     渐变 (Gradients)
     ============================================================ */
  --edos-grad-cyan: linear-gradient(135deg, #38bdf8, #818cf8);
  --edos-grad-hero: linear-gradient(135deg, #38bdf8 0%, #a78bfa 40%, #f472b6 80%);
  --edos-grad-card: linear-gradient(135deg, rgba(56, 189, 248, 0.04), rgba(167, 139, 250, 0.04));
  --edos-grad-primary: linear-gradient(135deg, var(--edos-primary), var(--edos-accent));

  /* ============================================================
     间距 (Spacing)
     ============================================================ */
  --edos-spacing-xs: 4px;
  --edos-spacing-sm: 8px;
  --edos-spacing-md: 16px;
  --edos-spacing-lg: 24px;
  --edos-spacing-xl: 32px;
  --edos-spacing-2xl: 48px;

  /* ============================================================
     圆角 (Border Radius)
     ============================================================ */
  --edos-radius-sm: 6px;
  --edos-radius-md: 10px;
  --edos-radius-lg: 16px;
  --edos-radius-xl: 24px;
  --edos-radius-full: 9999px;

  /* ============================================================
     字体 (Typography)
     ============================================================ */
  --edos-font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
  --edos-font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;

  /* ============================================================
     动画 (Animation)
     ============================================================ */
  --edos-transition-fast: 150ms ease;
  --edos-transition-normal: 300ms ease;
  --edos-transition-slow: 500ms ease;

  /* ============================================================
     布局 (Layout)
     ============================================================ */
  --edos-sidebar-width: 260px;
  --edos-sidebar-collapsed-width: 70px;
  --edos-header-height: 60px;
  --edos-navbar-height: 72px;
  --edos-content-max-width: 1400px;
  --edos-container-max: 1400px;

  /* ============================================================
     向后兼容变量 (Backward Compatibility)
     ============================================================ */
  
  /* styles_modern.css 兼容 */
  --primary: var(--edos-primary);
  --primary-dark: var(--edos-primary-dark);
  --primary-light: var(--edos-primary-light);
  --accent: var(--edos-accent);
  --accent-dark: var(--edos-accent-dark);
  --accent-light: var(--edos-accent-light);
  --success: var(--edos-success);
  --warning: var(--edos-warning);
  --error: var(--edos-error);
  --info: var(--edos-info);
  --bg-primary: var(--edos-bg-primary);
  --bg-secondary: var(--edos-bg-secondary);
  --bg-tertiary: var(--edos-bg-tertiary);
  --bg-card: var(--edos-bg-card);
  --bg-elevated: var(--edos-bg-elevated);
  --bg-hover: var(--edos-bg-hover);
  --text-primary: var(--edos-text-primary);
  --text-secondary: var(--edos-text-secondary);
  --text-tertiary: var(--edos-text-tertiary);
  --text-dim: var(--edos-text-dim);
  --border-default: var(--edos-border-default);
  --border-hover: var(--edos-border-hover);
  --border-active: var(--edos-border-active);
  --border-glow: var(--edos-border-glow);
  --shadow-sm: var(--edos-shadow-sm);
  --shadow-md: var(--edos-shadow-md);
  --shadow-lg: var(--edos-shadow-lg);
  --shadow-glow: var(--edos-shadow-glow);
  --shadow-glow-accent: var(--edos-shadow-glow-accent);
  --spacing-xs: var(--edos-spacing-xs);
  --spacing-sm: var(--edos-spacing-sm);
  --spacing-md: var(--edos-spacing-md);
  --spacing-lg: var(--edos-spacing-lg);
  --spacing-xl: var(--edos-spacing-xl);
  --spacing-2xl: var(--edos-spacing-2xl);
  --radius-sm: var(--edos-radius-sm);
  --radius-md: var(--edos-radius-md);
  --radius-lg: var(--edos-radius-lg);
  --radius-xl: var(--edos-radius-xl);
  --radius-full: var(--edos-radius-full);
  --font-sans: var(--edos-font-sans);
  --font-mono: var(--edos-font-mono);
  --transition-fast: var(--edos-transition-fast);
  --transition-normal: var(--edos-transition-normal);
  --transition-slow: var(--edos-transition-slow);
  --sidebar-width: var(--edos-sidebar-width);
  --sidebar-collapsed-width: var(--edos-sidebar-collapsed-width);
  --header-height: var(--edos-header-height);
  --content-max-width: var(--edos-content-max-width);
  
  /* styles_enhanced.css 兼容 */
  --cyan: var(--edos-cyan);
  --purple: var(--edos-purple);
  --pink: var(--edos-pink);
  --green: var(--edos-green);
  --red: var(--edos-red);
  --orange: var(--edos-orange);
  --bg-deep: var(--edos-bg-primary);
  --bg-surface: var(--edos-bg-secondary);
  --bg-glass: var(--edos-bg-glass);
  --bg-subtle: var(--edos-bg-subtle);
  --bg-pressed: var(--edos-bg-pressed);
  --input-bg: var(--edos-input-bg);
  --overlay-dark: var(--edos-overlay-dark);
  --text-main: var(--edos-text-main);
  --text-muted: var(--edos-text-muted);
  --border-subtle: var(--edos-border-subtle);
  --grad-cyan: var(--edos-grad-cyan);
  --grad-hero: var(--edos-grad-hero);
  --grad-card: var(--edos-grad-card);
  --radius-sm: var(--edos-radius-sm);
  --radius-md: var(--edos-radius-md);
  --radius-lg: var(--edos-radius-lg);
  --radius-xl: var(--edos-radius-xl);
  --transition-base: var(--edos-transition-normal);
  --navbar-height: var(--edos-navbar-height);
  --container-max: var(--edos-container-max);
}

/* ============================================================
   暗色主题 (Dark Theme) - 系统偏好暗色时切换
   ============================================================ */
@media (prefers-color-scheme: dark) {
  :root {
    --edos-bg-primary: #ffffff;
    --edos-bg-secondary: #f8fafc;
    --edos-bg-tertiary: #f1f5f9;
    --edos-bg-card: rgba(255, 255, 255, 0.92);
    --edos-bg-elevated: rgba(255, 255, 255, 0.98);
    --edos-bg-hover: rgba(0, 0, 0, 0.06);
    --edos-bg-glass: rgba(255, 255, 255, 0.85);
    --edos-bg-subtle: rgba(0, 0, 0, 0.03);
    --edos-bg-pressed: rgba(0, 0, 0, 0.1);
    --edos-input-bg: rgba(255, 255, 255, 0.95);
    --edos-overlay-dark: rgba(0, 0, 0, 0.55);
    
    --edos-text-primary: #111827;
    --edos-text-secondary: #4b5563;
    --edos-text-tertiary: #6b7280;
    --edos-text-dim: #9ca3af;
    --edos-text-main: #111827;
    --edos-text-muted: #9ca3af;
    
    --edos-border-default: rgba(0, 0, 0, 0.08);
    --edos-border-hover: rgba(0, 0, 0, 0.15);
    --edos-border-active: rgba(56, 189, 248, 0.5);
    --edos-border-glow: rgba(56, 189, 248, 0.15);
    --edos-border-subtle: rgba(0, 0, 0, 0.06);
    
    --edos-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
    --edos-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
    --edos-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
    --edos-shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
    --edos-shadow-glow-accent: 0 0 20px rgba(167, 139, 250, 0.1);
  }
}

/* ============================================================
   暗色主题强制类 (Dark Mode Force)
   ============================================================ */
[data-theme="dark"] {
  --edos-bg-primary: #ffffff;
  --edos-bg-secondary: #f8fafc;
  --edos-bg-tertiary: #f1f5f9;
  --edos-bg-card: rgba(255, 255, 255, 0.92);
  --edos-bg-elevated: rgba(255, 255, 255, 0.98);
  --edos-bg-hover: rgba(0, 0, 0, 0.06);
  --edos-bg-glass: rgba(255, 255, 255, 0.85);
  --edos-bg-subtle: rgba(0, 0, 0, 0.03);
  --edos-bg-pressed: rgba(0, 0, 0, 0.1);
  --edos-input-bg: rgba(255, 255, 255, 0.95);
  --edos-overlay-dark: rgba(0, 0, 0, 0.55);
  
  --edos-text-primary: #111827;
  --edos-text-secondary: #4b5563;
  --edos-text-tertiary: #6b7280;
  --edos-text-dim: #9ca3af;
  --edos-text-main: #111827;
  --edos-text-muted: #9ca3af;
  
  --edos-border-default: rgba(0, 0, 0, 0.08);
  --edos-border-hover: rgba(0, 0, 0, 0.15);
  --edos-border-active: rgba(56, 189, 248, 0.5);
  --edos-border-glow: rgba(56, 189, 248, 0.15);
  --edos-border-subtle: rgba(0, 0, 0, 0.06);
  
  --edos-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --edos-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --edos-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
  --edos-shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
  --edos-shadow-glow-accent: 0 0 20px rgba(167, 139, 250, 0.1);
}

/* ============================================================
   亮色主题强制类 (Light Mode Force)
   ============================================================ */
[data-theme="light"] {
  --edos-bg-primary: #ffffff;
  --edos-bg-secondary: #f8fafc;
  --edos-bg-tertiary: #f1f5f9;
  --edos-bg-card: rgba(255, 255, 255, 0.92);
  --edos-bg-elevated: rgba(255, 255, 255, 0.98);
  --edos-bg-hover: rgba(0, 0, 0, 0.06);
  --edos-bg-glass: rgba(255, 255, 255, 0.85);
  --edos-bg-subtle: rgba(0, 0, 0, 0.03);
  --edos-bg-pressed: rgba(0, 0, 0, 0.1);
  --edos-input-bg: rgba(255, 255, 255, 0.95);
  --edos-overlay-dark: rgba(0, 0, 0, 0.55);
  
  --edos-text-primary: #111827;
  --edos-text-secondary: #4b5563;
  --edos-text-tertiary: #6b7280;
  --edos-text-dim: #9ca3af;
  --edos-text-main: #111827;
  --edos-text-muted: #9ca3af;
  
  --edos-border-default: rgba(0, 0, 0, 0.08);
  --edos-border-hover: rgba(0, 0, 0, 0.15);
  --edos-border-active: rgba(56, 189, 248, 0.5);
  --edos-border-glow: rgba(56, 189, 248, 0.15);
  --edos-border-subtle: rgba(0, 0, 0, 0.06);
  
  --edos-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --edos-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --edos-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
  --edos-shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
  --edos-shadow-glow-accent: 0 0 20px rgba(167, 139, 250, 0.1);
}
/**
 * Edos AI - 现代化设计系统 v1.0.0
 * 基于2024-2025年主流设计趋势
 * 特性：CSS变量、现代化配色、流畅动画、响应式设计
 */

/* ============================================================
   1. 设计令牌 (Design Tokens)
   ============================================================ */

:root {
  /* 主色调 - 现代化渐变配色 */
  --primary: #00d4ff;
  --primary-dark: #0099cc;
  --primary-light: #66e0ff;
  --accent: #a855f7;
  --accent-dark: #7c3aed;
  --accent-light: #c084fc;
  
  /* 功能色 */
  --success: #22c55e;
  --warning: #f59e0b;
  --error: #ef4444;
  --info: #3b82f6;
  
  /* 中性色 - 亮色主题为默认 */
  --bg-primary: #ffffff;
  --bg-secondary: #f8fafc;
  --bg-tertiary: #f1f5f9;
  --bg-card: rgba(255, 255, 255, 0.92);
  --bg-elevated: rgba(255, 255, 255, 0.98);
  --bg-hover: rgba(0, 0, 0, 0.06);
  --bg-surface: #f8fafc;
  
  /* 文字色 */
  --text-primary: #111827;
  --text-secondary: #4b5563;
  --text-tertiary: #6b7280;
  --text-dim: #9ca3af;
  --text-main: #111827;
  
  /* 边框色 */
  --border-default: rgba(0, 0, 0, 0.08);
  --border-hover: rgba(0, 0, 0, 0.15);
  --border-active: rgba(56, 189, 248, 0.5);
  --border-glow: rgba(56, 189, 248, 0.15);
  --border-subtle: rgba(0, 0, 0, 0.06);
  
  /* JS 中常用的语义色 */
  --cyan: #38bdf8;
  --emerald: #10b981;
  --purple: #a78bfa;
  --pink: #f472b6;
  --red: #ef4444;
  --grad-cyan: linear-gradient(135deg, #38bdf8, #818cf8);
  
  /* 阴影 */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
  --shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
  --shadow-glow-accent: 0 0 20px rgba(167, 139, 250, 0.1);
  
  /* 间距 */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  --spacing-2xl: 48px;
  
  /* 圆角 */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-full: 9999px;
  
  /* 字体 */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
  --font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;
  
  /* 动画 */
  --transition-fast: 150ms ease;
  --transition-normal: 300ms ease;
  --transition-slow: 500ms ease;
  
  /* 布局 */
  --sidebar-width: 260px;
  --sidebar-collapsed-width: 70px;
  --header-height: 60px;
  --content-max-width: 1400px;
}

/* ============================================================
   2. 基础重置与全局样式
   ============================================================ */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-sans);
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  overflow-x: hidden;
}

a {
  color: var(--primary);
  text-decoration: none;
  transition: color var(--transition-fast);
}

a:hover {
  color: var(--primary-light);
}

/* ============================================================
   3. 布局系统
   ============================================================ */

/* 主布局容器 */
.edos-layout {
  display: flex;
  min-height: 100vh;
  transition: all var(--transition-normal);
}

/* 侧边栏 */
.edos-sidebar {
  width: var(--sidebar-width);
  height: 100vh;
  position: fixed;
  left: 0;
  top: 0;
  background: var(--bg-secondary, #f8fafc);
  border-right: 1px solid var(--border-default, rgba(0,212,255,0.15));
  display: flex;
  flex-direction: column;
  z-index: 1000;
  transition: width var(--transition-normal), transform var(--transition-normal);
  overflow-x: hidden;
  overflow-y: auto;
}

.edos-sidebar.collapsed {
  width: var(--sidebar-collapsed-width);
}

/* 侧边栏头部 */
.sidebar-header {
  padding: var(--spacing-lg);
  border-bottom: 1px solid var(--border-default, rgba(0,212,255,0.15));
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  min-height: 80px;
  background: linear-gradient(180deg, rgba(0, 212, 255, 0.05), transparent);
}

.sidebar-logo {
  width: 48px;
  height: 48px;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  font-weight: 900;
  color: #ffffff;
  flex-shrink: 0;
  box-shadow: 0 4px 12px rgba(0, 212, 255, 0.3);
}

.sidebar-brand {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--text-primary, #ffffff);
  white-space: nowrap;
  opacity: 1;
  transition: opacity var(--transition-fast);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
  letter-spacing: 0.02em;
}

.edos-sidebar.collapsed .sidebar-brand {
  opacity: 0;
  pointer-events: none;
}

/* 侧边栏导航 */
.sidebar-nav {
  flex: 1;
  padding: var(--spacing-md);
  overflow-y: auto;
}

.nav-section {
  margin-bottom: var(--spacing-lg);
}

.nav-section-title {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary, #c0c0e0);
  letter-spacing: 0.08em;
  padding: var(--spacing-sm) var(--spacing-md);
  margin-bottom: var(--spacing-xs);
  white-space: nowrap;
  opacity: 1;
  transition: opacity var(--transition-fast);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.edos-sidebar.collapsed .nav-section-title {
  opacity: 0;
  pointer-events: none;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  padding: var(--spacing-md);
  border-radius: var(--radius-md);
  color: var(--text-secondary, #c0c0e0);
  cursor: pointer;
  transition: all var(--transition-fast);
  white-space: nowrap;
  position: relative;
  margin-bottom: var(--spacing-xs);
  font-size: 0.95rem;
  font-weight: 500;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
}

.nav-item:hover {
  background: var(--bg-hover, #2a2a5a);
  color: var(--text-primary, #ffffff);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.nav-item.active {
  background: linear-gradient(135deg, rgba(0, 212, 255, 0.15), rgba(168, 85, 247, 0.15));
  color: #ffffff;
  border: 1px solid var(--border-glow, rgba(0,212,255,0.25));
  font-weight: 600;
  text-shadow: 0 1px 3px rgba(0, 212, 255, 0.3);
  box-shadow: 0 0 20px rgba(0, 212, 255, 0.15);
}

.nav-item-icon {
  font-size: 1.25rem;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.nav-item-text {
  flex: 1;
  opacity: 1;
  transition: opacity var(--transition-fast);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
}

.edos-sidebar.collapsed .nav-item-text {
  opacity: 0;
  pointer-events: none;
}

.nav-item-badge {
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: 0.75rem;
  font-weight: 700;
  background: linear-gradient(135deg, #00d4ff, #a855f7);
  color: #ffffff;
  opacity: 1;
  transition: opacity var(--transition-fast);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  box-shadow: 0 1px 6px rgba(168, 85, 247, 0.3);
}

.edos-sidebar.collapsed .nav-item-badge {
  opacity: 0;
  pointer-events: none;
}

/* 侧边栏底部 */
.sidebar-footer {
  padding: var(--spacing-md);
  border-top: 1px solid var(--border-default, rgba(0,212,255,0.15));
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  background: linear-gradient(0deg, rgba(168, 85, 247, 0.03), transparent);
}

.sidebar-user-avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: linear-gradient(135deg, var(--primary), var(--accent));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.sidebar-user-info {
  flex: 1;
  white-space: nowrap;
  opacity: 1;
  transition: opacity var(--transition-fast);
}

.edos-sidebar.collapsed .sidebar-user-info {
  opacity: 0;
  pointer-events: none;
}

.sidebar-user-name {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-primary, #ffffff);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.sidebar-user-role {
  font-size: 0.8rem;
  color: var(--text-secondary, #c0c0e0);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
}

/* 主内容区域 */
.edos-main {
  flex: 1;
  margin-left: var(--sidebar-width);
  min-height: 100vh;
  transition: margin-left var(--transition-normal);
  display: flex;
  flex-direction: column;
}

.edos-sidebar.collapsed ~ .edos-main {
  margin-left: var(--sidebar-collapsed-width);
}

/* 顶部栏 */
.edos-header {
  height: var(--header-height);
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--spacing-lg);
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(10px);
  background: rgba(18, 18, 42, 0.8);
}

.header-left {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
}

.header-center {
  display: flex;
  flex: 1;
  justify-content: center;
  align-items: center;
}

.header-search {
  display: flex;
  width: 100%;
  max-width: 400px;
}

.header-search input {
  flex: 1;
  padding: 10px 16px;
  border: none;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--text-primary);
  font-size: 14px;
  outline: none;
  transition: all var(--transition-fast);
}

.header-search input:focus {
  background: rgba(255, 255, 255, 0.12);
  box-shadow: 0 0 0 2px var(--accent);
}

.header-search input::placeholder {
  color: var(--text-tertiary);
}

.header-right {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
}

/* 内容区域 */
.edos-content {
  flex: 1;
  padding: var(--spacing-lg);
  max-width: var(--content-max-width);
  width: 100%;
  margin: 0 auto;
}

/* ============================================================
   4. 组件样式
   ============================================================ */

/* 按钮 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-sm);
  padding: var(--spacing-sm) var(--spacing-md);
  border: none;
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition-fast);
  white-space: nowrap;
}

.btn-primary {
  background: linear-gradient(135deg, var(--primary), var(--accent));
  color: #ffffff;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.btn-primary:hover {
  opacity: 0.9;
  transform: translateY(-1px);
  box-shadow: var(--shadow-glow);
}

.btn-outline {
  background: transparent;
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
}

.btn-outline:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: rgba(0, 212, 255, 0.05);
}

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
}

.btn-ghost:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.btn-sm {
  padding: var(--spacing-xs) var(--spacing-sm);
  font-size: 0.75rem;
}

.btn-lg {
  padding: var(--spacing-md) var(--spacing-lg);
  font-size: 1rem;
}

/* 卡片 */
.card {
  background: var(--bg-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  padding: var(--spacing-lg);
  transition: all var(--transition-normal);
}

.card:hover {
  border-color: var(--border-hover);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.card-header {
  margin-bottom: var(--spacing-md);
}

.card-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: var(--spacing-xs);
}

.card-description {
  font-size: 0.875rem;
  color: var(--text-secondary);
}

/* 输入框 */
.input {
  width: 100%;
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: 0.875rem;
  transition: all var(--transition-fast);
}

.input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.1);
}

.input::placeholder {
  color: var(--text-tertiary);
}

/* 标签 */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
  padding: var(--spacing-xs) var(--spacing-sm);
  border-radius: var(--radius-full);
  font-size: 0.75rem;
  font-weight: 600;
}

.badge-primary {
  background: rgba(0, 212, 255, 0.1);
  color: var(--primary);
}

.badge-accent {
  background: rgba(168, 85, 247, 0.1);
  color: var(--accent);
}

.badge-success {
  background: rgba(34, 197, 94, 0.1);
  color: var(--success);
}

.badge-warning {
  background: rgba(245, 158, 11, 0.1);
  color: var(--warning);
}

.badge-error {
  background: rgba(239, 68, 68, 0.1);
  color: var(--error);
}

.badge-danger {
  background: rgba(239, 68, 68, 0.1);
  color: var(--error);
}

.badge-info {
  background: rgba(59, 130, 246, 0.1);
  color: var(--info);
}

/* ============================================================
   JS动态生成元素样式 (确保深色背景上文字可见)
   ============================================================ */

/* ROI 比较表格 */
.roi-compare-table-wrap {
  overflow-x: auto;
  margin: 20px 0;
  border-radius: 16px;
  border: 1px solid var(--border-glow, rgba(0, 212, 255, 0.15));
  background: var(--bg-card, rgba(255, 255, 255, 0.92));
}

.roi-compare-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.roi-compare-table thead th {
  background: rgba(0, 212, 255, 0.08);
  color: var(--cyan, #38bdf8);
  padding: 12px 14px;
  text-align: left;
  font-weight: 600;
  border-bottom: 2px solid var(--border-glow, rgba(0, 212, 255, 0.15));
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
}

.roi-compare-table tbody td {
  padding: 12px 14px;
  color: var(--text-primary, #f5f5ff);
  border-bottom: 1px solid var(--border-default, rgba(0, 212, 255, 0.1));
}

.roi-compare-table tbody tr:last-child td {
  border-bottom: none;
}

.roi-compare-table tbody tr:hover {
  background: rgba(0, 212, 255, 0.04);
}

.roi-row-edos {
  background: linear-gradient(90deg, rgba(16, 185, 129, 0.08), rgba(56, 189, 248, 0.04));
}

.roi-row-edos td {
  color: var(--text-primary, #f5f5ff);
  font-weight: 500;
}

.roi-row-edos td:first-child {
  border-left: 3px solid var(--emerald, #10b981);
}

.roi-row-new td {
  color: var(--text-primary, #f5f5ff);
}

/* ROI insight 卡片 */
.roi-insight-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
  margin: 24px 0;
}

.roi-insight-card {
  background: var(--bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--border-default, rgba(0, 212, 255, 0.15));
  border-radius: 16px;
  padding: 20px;
  transition: all 0.2s ease;
}

.roi-insight-card:hover {
  border-color: var(--border-hover, rgba(0, 212, 255, 0.35));
  transform: translateY(-2px);
  box-shadow: var(--shadow-md, 0 4px 16px rgba(0, 0, 0, 0.5));
}

.roi-icon {
  font-size: 2rem;
  margin-bottom: 12px;
}

.roi-insight-card h4 {
  color: var(--text-primary, #f5f5ff);
  font-size: 1.05rem;
  font-weight: 600;
  margin-bottom: 8px;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
}

.roi-insight-card p {
  color: var(--text-secondary, #c0c0e0);
  font-size: 0.85rem;
  line-height: 1.6;
}

.roi-insight-card p strong {
  color: var(--cyan, #38bdf8);
  font-weight: 600;
}

/* 定价推荐徽章 */
.pricing-recommend-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 10px;
  font-size: 0.75rem;
  font-weight: 600;
  background: linear-gradient(135deg, var(--primary, #00d4ff), var(--accent, #a855f7));
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  box-shadow: 0 2px 8px rgba(0, 212, 255, 0.25);
}

/* 超额计费信息 */
.overage-info {
  margin-top: 20px;
  background: var(--bg-card, rgba(255, 255, 255, 0.92));
  border-radius: 16px;
  padding: 20px 24px;
  border: 1px solid var(--border-glow, rgba(0, 212, 255, 0.15));
  text-align: center;
}

.overage-info h4 {
  color: var(--text-primary, #f5f5ff);
  margin: 0 0 10px;
  font-size: 0.95rem;
  font-weight: 600;
}

.overage-info p {
  color: var(--text-secondary, #c0c0e0);
  font-size: 0.85rem;
  margin-top: 8px;
}

.overage-info strong {
  color: var(--cyan, #38bdf8);
  font-weight: 700;
}

/* 升级提示 Toast */
.upgrade-nudge-toast {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 20px;
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(10, 16, 40, 0.95), rgba(20, 30, 60, 0.95));
  border: 1px solid var(--border-glow, rgba(0, 212, 255, 0.2));
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 20px rgba(0, 212, 255, 0.1);
  z-index: 10000;
  max-width: 420px;
  animation: fadeInUp 0.4s ease;
}

.upgrade-nudge-toast span {
  color: var(--text-primary, #f5f5ff);
  font-size: 0.85rem;
  font-weight: 500;
}

.upgrade-nudge-btn {
  padding: 6px 14px;
  border: none;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--primary, #00d4ff), var(--accent, #a855f7));
  color: #ffffff;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  transition: opacity 0.2s;
}

.upgrade-nudge-btn:hover {
  opacity: 0.9;
}

.upgrade-nudge-close {
  background: none;
  border: none;
  color: var(--text-dim, #a0a0cc);
  font-size: 1.1rem;
  cursor: pointer;
  padding: 4px;
  transition: color 0.2s;
}

.upgrade-nudge-close:hover {
  color: var(--text-primary, #f5f5ff);
}

/* 专业版试用横幅 */
.pro-trial-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 24px;
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(0, 212, 255, 0.08), rgba(168, 85, 247, 0.08));
  border: 1px solid var(--border-glow, rgba(0, 212, 255, 0.2));
  margin: 16px 0;
  flex-wrap: wrap;
}

.pro-trial-banner span {
  color: var(--text-primary, #f5f5ff);
  font-size: 0.9rem;
  line-height: 1.5;
}

.pro-trial-banner strong {
  color: var(--cyan, #38bdf8);
  font-weight: 700;
}

.pro-trial-btn {
  padding: 8px 18px;
  border: none;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--primary, #00d4ff), var(--accent, #a855f7));
  color: #ffffff;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  transition: opacity 0.2s;
}

.pro-trial-btn:hover {
  opacity: 0.9;
}

/* ============================================================
   5. 动画
   ============================================================ */

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideInLeft {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

.animate-fade-in {
  animation: fadeIn var(--transition-normal) ease;
}

.animate-fade-in-up {
  animation: fadeInUp var(--transition-normal) ease;
}

.animate-slide-in-left {
  animation: slideInLeft var(--transition-normal) ease;
}

/* 打字机效果 */
.typing-dots {
  display: inline-block;
  animation: typing 1.4s infinite ease-in-out both;
}

.typing-dots::after {
  content: '';
  animation: dots 1.4s infinite ease-in-out both;
}

@keyframes dots {
  0%, 20% { content: '.'; }
  40% { content: '..'; }
  60%, 100% { content: '...'; }
}

/* ============================================================
   5.5 页面切换系统
   ============================================================ */
.page {
  display: none;
}
.page.active {
  display: block;
  animation: fadeInUp 0.3s ease;
}

/* ============================================================
   6. 响应式设计
   ============================================================ */

@media (max-width: 1024px) {
  .edos-sidebar {
    transform: translateX(-100%);
    width: 85% !important;
    max-width: 340px;
    box-shadow: 4px 0 20px rgba(0,0,0,0.15);
  }
  
  .edos-sidebar.mobile-open {
    transform: translateX(0);
  }
  
  .edos-main {
    margin-left: 0 !important;
  }
  
  .mobile-menu-btn {
    display: flex !important;
  }
  
  .edos-header .btn-ghost:not(.mobile-menu-btn) {
    display: none !important;
  }
  
  .header-search {
    display: none !important;
  }
  
  .mobile-tab-bar {
    display: flex !important;
  }
  
  .edos-header {
    padding: 0 var(--spacing-sm);
  }
  
  .edos-content {
    padding: var(--spacing-sm);
  }
}

@media (max-width: 768px) {
  .edos-content {
    padding: var(--spacing-md);
  }
  
  :root {
    --sidebar-width: 100%;
  }
}

/* 移动端横排导航栏 */
.mobile-tab-bar {
  display: flex;
  background: var(--bg-secondary, #f8fafc);
  border-radius: var(--radius-lg);
  padding: 6px;
  gap: 4px;
  border: 1px solid var(--border-default, rgba(0,212,255,0.15));
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.mobile-tab-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 10px 12px;
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  color: var(--text-secondary, #c0c0e0);
  cursor: pointer;
  transition: all var(--transition-fast);
  min-width: 56px;
  font-size: 0.8rem;
  font-weight: 500;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.mobile-tab-item:hover {
  background: rgba(0, 212, 255, 0.1);
  color: var(--text-primary, #ffffff);
}

.mobile-tab-item.active {
  background: linear-gradient(135deg, #00d4ff, #a855f7);
  color: #ffffff;
  font-weight: 700;
  box-shadow: 0 2px 10px rgba(0, 212, 255, 0.3);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.mobile-tab-icon {
  font-size: 1.2rem;
  margin-bottom: 2px;
}

.mobile-tab-text {
  font-size: 0.75rem;
  font-weight: 500;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
}

.mobile-tab-item.active .mobile-tab-text {
  font-weight: 700;
}

/* ============================================================
   7. 聊天输入区域响应式样式
   ============================================================ */
.chat-input-area {
  padding: 12px 16px;
  display: flex;
  gap: 10px;
  flex-shrink: 0;
  align-items: flex-end;
  position: relative;
}

.chat-input-area textarea {
  flex: 1;
  min-height: 48px;
  max-height: 200px;
  resize: none;
  box-sizing: border-box;
  line-height: 1.5;
}

.chat-input-area button {
  white-space: nowrap;
}

@media (max-width: 640px) {
  .chat-input-area {
    padding: 8px 12px;
    gap: 8px;
  }
  
  .chat-input-area textarea {
    font-size: 14px;
    padding: 10px 14px;
    min-height: 44px;
  }
  
  .chat-input-area button {
    padding: 10px 18px !important;
    font-size: 13px !important;
    min-width: 60px !important;
  }
}

@media (max-width: 480px) {
  .chat-input-area {
    flex-wrap: wrap;
  }
  
  .chat-input-area textarea {
    min-width: 100%;
  }
  
  .chat-input-area > div:last-child {
    width: 100%;
    flex-direction: row !important;
    justify-content: flex-end;
    gap: 8px;
  }
}

/* 移动端菜单按钮 */
.mobile-menu-btn {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  background: var(--bg-tertiary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  cursor: pointer;
  font-size: 1.3rem;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: all var(--transition-fast);
}

.mobile-menu-btn:hover {
  background: var(--bg-hover);
  border-color: var(--accent);
}

.mobile-menu-btn:active {
  transform: scale(0.95);
}

/* ============================================================
   7. 工具类
   ============================================================ */

.text-center { text-align: center; }
.text-left { text-align: left; }
.text-right { text-align: right; }

.mt-sm { margin-top: var(--spacing-sm); }
.mt-md { margin-top: var(--spacing-md); }
.mt-lg { margin-top: var(--spacing-lg); }
.mb-sm { margin-bottom: var(--spacing-sm); }
.mb-md { margin-bottom: var(--spacing-md); }
.mb-lg { margin-bottom: var(--spacing-lg); }

.p-sm { padding: var(--spacing-sm); }
.p-md { padding: var(--spacing-md); }
.p-lg { padding: var(--spacing-lg); }

.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.gap-sm { gap: var(--spacing-sm); }
.gap-md { gap: var(--spacing-md); }
.gap-lg { gap: var(--spacing-lg); }

/* 滚动条美化 */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: var(--bg-primary);
}

::-webkit-scrollbar-thumb {
  background: var(--bg-elevated);
  border-radius: var(--radius-sm);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-tertiary);
}

/* ============================================================
   8. 页面特定样式
   ============================================================ */

/* 首页英雄区 */
.hero {
  text-align: center;
  padding: var(--spacing-2xl) var(--spacing-md);
  animation: fadeInUp var(--transition-slow) ease;
}

.hero h1 {
  font-size: 3rem;
  font-weight: 800;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-bottom: var(--spacing-md);
}

.hero p {
  font-size: 1.125rem;
  color: var(--text-secondary);
  max-width: 600px;
  margin: 0 auto;
}

/* 页面标题 */
.page-title {
  font-size: 2rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: var(--spacing-lg);
  animation: fadeInUp var(--transition-normal) ease;
}

/* 空状态 */
.empty-state {
  text-align: center;
  padding: var(--spacing-2xl);
  color: var(--text-tertiary);
  animation: fadeIn var(--transition-normal) ease;
}

.empty-state-icon {
  font-size: 3rem;
  margin-bottom: var(--spacing-md);
}

/* 加载状态 */
.loading-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-2xl);
  color: var(--text-tertiary);
}

.loading-spinner::after {
  content: '';
  width: 24px;
  height: 24px;
  border: 2px solid var(--border-default);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  margin-left: var(--spacing-sm);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Toast通知 */
.toast {
  position: fixed;
  bottom: var(--spacing-lg);
  right: var(--spacing-lg);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: 10000;
  animation: slideInRight var(--transition-normal) ease;
}

@keyframes slideInRight {
  from {
    opacity: 0;
    transform: translateX(100px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.toast-success {
  border-color: var(--success);
}

.toast-error {
  border-color: var(--error);
}

.toast-info {
  border-color: var(--info);
}

/* ============================================================
   6. 聊天消息气泡 v2 (EdosChatV2)
   ============================================================ */

/* 消息气泡外层容器 */
.msg-bubble-v2 {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
  animation: fadeInUp 0.3s ease;
  max-width: 100%;
}

/* 用户消息 - 靠右对齐 */
.msg-bubble-v2.msg-user {
  flex-direction: row-reverse;
}

/* AI回复消息 - 靠左对齐 */
.msg-bubble-v2.msg-assistant {
  flex-direction: row;
}

/* AI 头像 */
.msg-avatar-v2 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, #00d4ff, #a855f7);
  color: #ffffff;
  font-size: 14px;
  font-weight: 700;
  box-shadow: 0 2px 8px rgba(0, 212, 255, 0.3), 0 0 0 2px rgba(0, 212, 255, 0.15);
  flex-shrink: 0;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

/* 消息内容包装器 */
.msg-content-wrapper-v2 {
  display: flex;
  flex-direction: column;
  max-width: 100%;
  flex: 1;
  min-width: 0;
}

.msg-bubble-v2.msg-user .msg-content-wrapper-v2 {
  align-items: flex-end;
}

.msg-bubble-v2.msg-assistant .msg-content-wrapper-v2 {
  align-items: flex-start;
}

/* 实际消息气泡内容 */
.msg-bubble-v2-content {
  padding: 12px 18px;
  border-radius: 14px;
  font-size: 16px;
  line-height: 1.75;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
  max-width: 100%;
  word-wrap: break-word;
  overflow-wrap: break-word;
}

/* 用户消息气泡样式 */
.msg-bubble-v2.msg-user .msg-bubble-v2-content {
  background: linear-gradient(135deg, #1e4b8a 0%, #2563eb 100%);
  color: #ffffff;
  border-radius: 14px 14px 4px 14px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

/* AI 消息气泡样式 */
.msg-bubble-v2.msg-assistant .msg-bubble-v2-content {
  background: linear-gradient(135deg, #f0f9ff, #faf5ff);
  color: #1f2937;
  border-radius: 14px 14px 14px 4px;
  border: 1px solid rgba(0, 212, 255, 0.2);
}

/* 消息气泡内的段落和文本 */
.msg-bubble-v2-content p,
.msg-bubble-v2-content div,
.msg-bubble-v2-content span {
  color: inherit;
}

.msg-bubble-v2-content p {
  margin-bottom: 8px;
}

.msg-bubble-v2-content p:last-child {
  margin-bottom: 0;
}

/* 消息时间戳 */
.msg-time-v2 {
  font-size: 12px;
  color: #6b7280;
  margin-top: 6px;
  font-weight: 400;
}

.msg-bubble-v2.msg-user .msg-time-v2 {
  text-align: right;
}

.msg-bubble-v2.msg-assistant .msg-time-v2 {
  text-align: left;
}

/* 流式输出光标 */
.streaming-cursor {
  display: inline-block;
  color: #00d4ff;
  animation: blink 1s infinite;
  margin-left: 2px;
}

@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* 消息气泡内的代码块 */
.msg-bubble-v2-content pre {
  background: #1e293b;
  color: #e2e8f0;
  padding: 12px 14px;
  border-radius: 8px;
  margin: 8px 0;
  overflow-x: auto;
  font-family: "SF Mono", Monaco, Consolas, monospace;
  font-size: 14px;
  line-height: 1.6;
  border: 1px solid rgba(0, 0, 0, 0.1);
}

.msg-bubble-v2-content code {
  background: rgba(0, 212, 255, 0.1);
  color: #0891b2;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 14px;
  font-family: "SF Mono", Monaco, Consolas, monospace;
}

/* 消息气泡内的列表 */
.msg-bubble-v2-content ul,
.msg-bubble-v2-content ol {
  margin: 8px 0 8px 24px;
  color: inherit;
}

.msg-bubble-v2-content li {
  margin-bottom: 4px;
  line-height: 1.6;
}

/* 消息气泡内的链接 */
.msg-bubble-v2-content a {
  color: #0891b2;
  text-decoration: underline;
  transition: opacity 0.2s;
}

.msg-bubble-v2-content a:hover {
  opacity: 0.8;
}

/* 聊天容器 */
#chatMessages,
#chatMessagesV2,
.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  min-height: 200px;
}

/* 聊天容器滚动条样式 */
#chatMessages::-webkit-scrollbar,
#chatMessagesV2::-webkit-scrollbar {
  width: 8px;
}

#chatMessages::-webkit-scrollbar-track,
#chatMessagesV2::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.2);
}

#chatMessages::-webkit-scrollbar-thumb,
#chatMessagesV2::-webkit-scrollbar-thumb {
  background: rgba(0, 212, 255, 0.3);
  border-radius: 4px;
}

#chatMessages::-webkit-scrollbar-thumb:hover,
#chatMessagesV2::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 212, 255, 0.5);
}

/* 欢迎页容器 */
#chatMessages > div[style*="text-align:center"] {
  text-align: center;
  padding: 40px 20px !important;
}

/* ============================================================
   7. 更多 JS 动态生成元素样式补充
   ============================================================ */

/* 帮助/教程标签页按钮 */
.help-tab {
  padding: 8px 16px;
  border: 1px solid var(--border-hover, rgba(0, 212, 255, 0.35));
  border-radius: 20px;
  background: transparent;
  color: var(--text-secondary, #c0c0e0);
  font-size: 13px;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.2s;
}

.help-tab.active {
  background: rgba(0, 212, 255, 0.1);
  border-color: var(--primary, #00d4ff);
  color: var(--primary, #00d4ff);
  font-weight: 600;
}

.help-tab:hover {
  background: rgba(0, 212, 255, 0.08);
  color: var(--primary, #00d4ff);
}

/* 定价卡片网格 */
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
  margin: 24px 0;
}

/* 定价卡片 */
.pricing-card {
  background: var(--bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--border-default, rgba(0, 212, 255, 0.18));
  border-radius: 16px;
  padding: 24px;
  text-align: center;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.pricing-card:hover {
  border-color: var(--border-hover, rgba(0, 212, 255, 0.35));
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg, 0 8px 32px rgba(0, 0, 0, 0.6));
}

.pricing-card.featured {
  border-color: var(--primary, #00d4ff);
  box-shadow: 0 0 30px rgba(0, 212, 255, 0.15);
}

.pricing-card h3 {
  color: var(--text-primary, #f5f5ff);
  font-size: 1.25rem;
  font-weight: 700;
  margin-bottom: 8px;
}

.pricing-card .price {
  font-size: 2.5rem;
  font-weight: 800;
  color: var(--primary, #00d4ff);
  margin: 16px 0;
  background: linear-gradient(135deg, var(--primary, #00d4ff), var(--accent, #a855f7));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.pricing-card ul {
  list-style: none;
  padding: 0;
  margin: 16px 0;
  text-align: left;
}

.pricing-card li {
  color: var(--text-secondary, #c0c0e0);
  padding: 8px 0;
  font-size: 0.9rem;
  border-bottom: 1px solid var(--border-default, rgba(0, 212, 255, 0.1));
}

.pricing-card li::before {
  content: "✓ ";
  color: var(--emerald, #10b981);
  font-weight: 700;
}

/* 模态框 */
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  animation: fadeIn 0.2s ease;
}

.modal-content {
  background: var(--bg-card, rgba(255, 255, 255, 0.92));
  border-radius: 16px;
  border: 1px solid var(--border-default, rgba(0, 212, 255, 0.18));
  max-width: 600px;
  width: 90%;
  max-height: 85vh;
  overflow: hidden;
  box-shadow: var(--shadow-lg, 0 8px 32px rgba(0, 0, 0, 0.6);
}

.modal-header {
  padding: 20px 24px;
  border-bottom: 1px solid var(--border-default, rgba(0, 212, 255, 0.1));
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.modal-header h2,
.modal-header h3 {
  color: var(--text-primary, #f5f5ff);
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
}

.modal-close {
  background: none;
  border: none;
  color: var(--text-dim, #a0a0cc);
  font-size: 1.5rem;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  transition: color 0.2s;
}

.modal-close:hover {
  color: var(--text-primary, #f5f5ff);
}

.modal-body {
  padding: 24px;
  overflow-y: auto;
  max-height: calc(85vh - 80px);
}

.modal-body p,
.modal-body div,
.modal-body span {
  color: var(--text-primary, #f5f5ff);
}

.modal-footer {
  padding: 16px 24px;
  border-top: 1px solid var(--border-default, rgba(0, 212, 255, 0.1);
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 功能比较表格 */
.feature-comparison-table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
  font-size: 0.9rem;
}

.feature-comparison-table th {
  background: rgba(0, 212, 255, 0.08);
  color: var(--cyan, #38bdf8);
  padding: 12px 16px;
  text-align: left;
  font-weight: 600;
  border-bottom: 2px solid var(--border-glow, rgba(0, 212, 255, 0.15));
}

.feature-comparison-table td {
  padding: 12px 16px;
  color: var(--text-primary, #f5f5ff);
  border-bottom: 1px solid var(--border-default, rgba(0, 212, 255, 0.1));
}

.feature-comparison-table tr:hover td {
  background: rgba(0, 212, 255, 0.03);
}

/* 管理表格 */
.admin-table {
  width: 100%;
  border-collapse: collapse;
  margin: 16px 0;
  font-size: 0.85rem;
}

.admin-table th {
  background: rgba(0, 212, 255, 0.06);
  color: var(--text-primary, #f5f5ff);
  padding: 12px 14px;
  text-align: left;
  font-weight: 600;
  border-bottom: 2px solid var(--border-glow, rgba(0, 212, 255, 0.15);
}

.admin-table td {
  padding: 12px 14px;
  color: var(--text-primary, #f5f5ff);
  border-bottom: 1px solid var(--border-default, rgba(0, 212, 255, 0.1));
}

.admin-table tr:hover td {
  background: rgba(0, 212, 255, 0.04);
}

/* 统计卡片 */
.stat-card {
  background: var(--bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--border-default, rgba(0, 212, 255, 0.18));
  border-radius: 16px;
  padding: 20px;
  text-align: center;
}

.stat-value {
  font-size: 2rem;
  font-weight: 800;
  color: var(--primary, #00d4ff);
  margin-bottom: 8px;
  background: linear-gradient(135deg, var(--primary, #00d4ff), var(--accent, #a855f7));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.stat-label {
  color: var(--text-secondary, #c0c0e0);
  font-size: 0.9rem;
}

/h1><p style="color:var(--text-dim);max-width:600px;margin:8px auto 0;">多Agent编排 · 生命周期管理 · 行为监控 · 决策追溯 · 协作调度</p></div>
        <div id="agentDashboardContent">
            <div class="skeleton-loader" style="max-width:900px;margin:0 auto;padding:0 20px;">
                <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:20px;">
                    <div class="skeleton-card" style="height:80px;border-radius:14px;background:var(--bg-elevated);animation:skeletonPulse 1.8s ease-in-out infinite;"></div>
                    <div class="skeleton-card" style="height:80px;border-radius:14px;background:var(--bg-elevated);animation:skeletonPulse 1.8s .2s ease-in-out infinite;"></div>
                    <div class="skeleton-card" style="height:80px;border-radius:14px;background:var(--bg-elevated);animation:skeletonPulse 1.8s .4s ease-in-out infinite;"></div>
                    <div class="skeleton-card" style="height:80px;border-radius:14px;background:var(--bg-elevated);animation:skeletonPulse 1.8s .6s ease-in-out infinite;"></div>
                </div>
                <div style="display:grid;grid-template-columns:2fr 1fr;gap:16px;">
                    <div class="skeleton-card" style="height:280px;border-radius:16px;background:var(--bg-elevated);animation:skeletonPulse 1.8s ease-in-out infinite;"></div>
                    <div class="skeleton-card" style="height:280px;border-radius:16px;background:var(--bg-elevated);animation:skeletonPulse 1.8s .3s ease-in-out infinite;"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- v3.1: 工作流编辑器 -->
    <div id="workflowEditorPage" class="page">
        <div class="hero" style="padding-bottom:16px;"><h1>&#x2699; 工作流编辑器</h1><p style="color:var(--text-dim);max-width:600px;margin:8px auto 0;">可视化编排 · BPMN 2.0 · 条件分支 · 循环控制 · 模板市场</p></div>
        <div id="workflowEditorContent">
            <div class="skeleton-loader" style="max-width:900px;margin:0 auto;padding:0 20px;">
                <div style="display:flex;gap:12px;margin-bottom:16px;">
                    <div class="skeleton-card" style="width:220px;height:calc(100vh - 220px);min-height:400px;border-radius:14px;background:var(--bg-elevated);animation:skeletonPulse 1.8s ease-in-out infinite;"></div>
                    <div class="skeleton-card" style="flex:1;height:calc(100vh - 220px);min-height:400px;border-radius:16px;background:var(--bg-elevated);animation:skeletonPulse 1.8s .2s ease-in-out infinite;"></div>
                    <div class="skeleton-card" style="width:260px;height:calc(100vh - 220px);min-height:400px;border-radius:14px;background:var(--bg-elevated);animation:skeletonPulse 1.8s .4s ease-in-out infinite;"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- 模板市场 -->
    <div id="marketplacePage" class="page">
        <div class="hero" style="padding-bottom:8px;"><h1>模板市场</h1><p style="color:var(--text-dim);max-width:600px;margin:8px auto 0;">200+ 预置技能与工作流模板，一键安装即用</p></div>
        <div class="marketplace-toolbar">
            <div class="mp-search-wrap"><input type="text" id="mpSearchInput" class="mp-search-input" placeholder="&#x1F50D; 搜索模板名称、标签..."></div>
            <div class="mp-filter-tabs" id="mpFilterTabs">
                <button class="mp-filter-tab active" data-mp-cat="all">全部</button>
                <button class="mp-filter-tab" data-mp-cat="ai">&#x1F916; AI智能</button>
                <button class="mp-filter-tab" data-mp-cat="productivity">⚡ 效率工具</button>
                <button class="mp-filter-tab" data-mp-cat="business">&#x1F4BC; 商业分析</button>
                <button class="mp-filter-tab" data-mp-cat="development">&#x1F4BB; 开发工具</button>
                <button class="mp-filter-tab" data-mp-cat="data">&#x1F4CA; 数据处理</button>
                <button class="mp-filter-tab" data-mp-cat="communication">&#x1F4AC; 沟通协作</button>
                <button class="mp-filter-tab" data-mp-cat="finance">&#x1F3E6; 金融风控</button>
            </div>
            <div class="mp-sort-bar">
                <span class="mp-result-count" id="mpResultCount">24 个模板</span>
                <button class="mp-tab-btn" id="mpMyTemplatesBtn">&#x1F4E6; 我的模板 (<span id="mpMyCount">0</span>)</button>
            </div>
        </div>
        <div class="mp-grid" id="mpGrid"><div class="empty-state" style="text-align:center;padding:40px 20px;color:var(--text-secondary);grid-column:1/-1;"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">⏳</div><p style="font-size:15px;font-weight:500;margin:0 0 4px;">正在加载模板...</p><p style="font-size:13px;opacity:0.7;margin:0;">模板市场数据加载中，请稍候</p></div></div>
        <!-- 我的模板面板 -->
        <div class="mp-my-panel" id="mpMyPanel" style="display:none;">
            <div class="mp-my-header"><h3>&#x1F4E6; 已安装的模板</h3><button class="btn-outline btn-sm" id="mpBackToMarketBtn">← 返回市场</button></div>
            <div class="mp-grid" id="mpMyGrid"><div class="empty-state" style="text-align:center;padding:40px 20px;color:var(--text-secondary);grid-column:1/-1;"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">&#x1F4ED;</div><p style="font-size:15px;font-weight:500;margin:0 0 4px;">暂无已安装模板</p><p style="font-size:13px;opacity:0.7;margin:0;">安装模板后将在此处显示</p></div></div>
        </div>
    </div>

    <!-- 管理后台 -->
    <div id="adminPage" class="page"><div class="hero" style="padding-bottom:20px;"><h1>管理后台</h1><div style="display:flex;gap:8px;justify-content:center;margin-top:8px;"><a href="#download" class="btn-outline btn-sm" style="color:#10b981;border-color:#10b981;text-decoration:none;" onclick="showPage('download')">下载客户端</a><button id="logoutAdmin" class="btn-outline btn-sm">退出后台</button></div></div>
        <!-- 告警通知条 -->
        <div id="adminAlertBar" class="admin-alert-bar" style="display:none;"></div>
        <div class="admin-tabs" style="display:flex; gap:8px; margin:0 0 24px; justify-content:center; flex-wrap:wrap;">
            <button class="admin-tab active" data-admin-tab="overview">&#x1F4CA; 概览</button>
            <button class="admin-tab" data-admin-tab="analytics">&#x1F4C8; 数据分析</button>
            <button class="admin-tab" data-admin-tab="monitor">&#x1F6E1;️ 问题监控</button>
            <button class="admin-tab" data-admin-tab="posts">&#x1F4DD; 帖子管理</button>
            <button class="admin-tab" data-admin-tab="users">&#x1F465; 用户管理</button>
            <button class="admin-tab" data-admin-tab="crowdtestTasks">&#x1F9EA; 众测管理</button>
            <button class="admin-tab" data-admin-tab="cases">&#x1F4DA; 案例管理</button>
            <button class="admin-tab" data-admin-tab="news">&#x1F4F0; 新闻管理</button>
            <button class="admin-tab" data-admin-tab="messages">&#x1F4AC; 用户留言</button>
            <button class="admin-tab" data-admin-tab="customerMonitor" style="border-color:rgba(16,185,129,.4);color:#10b981;">&#x1F465; 客户监控</button>
            <button class="admin-tab" data-admin-tab="revenue" style="border-color:rgba(245,158,11,.4);color:#f59e0b;">&#x1F4B0; 收入总账</button>
        </div>
        <div id="adminOverviewPanel" class="admin-panel active"></div>
        <div id="adminAnalyticsPanel" class="admin-panel"></div>
        <div id="adminMonitorPanel" class="admin-panel"></div>
        <div id="adminPostsPanel" class="admin-panel"></div>
        <div id="adminUsersPanel" class="admin-panel"></div>
        <div id="adminCrowdtestPanel" class="admin-panel"></div>
        <div id="adminCasesPanel" class="admin-panel"></div>
        <div id="adminNewsPanel" class="admin-panel"></div>
        <div id="adminMessagesPanel" class="admin-panel"></div>
        <div id="adminCustomerMonitorPanel" class="admin-panel"></div>
        <div id="adminRevenuePanel" class="admin-panel"></div>
    </div>

    <!-- 客户端下载页面 -->
    <div id="downloadPage" class="page">
        <div class="hero" style="padding-bottom:20px;">
            <h1>下载 Edos AI 客户端</h1>
            <p style="color:var(--text-dim);max-width:600px;margin:8px auto 0;">全平台支持 · 原生体验 · 自动更新 · 数据本地加密</p>
        </div>
        <div style="max-width:1100px;margin:0 auto;padding:0 20px 40px;">
            <!-- 版本号 -->
            <div style="text-align:center;margin-bottom:28px;padding:12px 24px;background:rgba(16,185,129,.08);border-radius:12px;border:1px solid rgba(16,185,129,.15);display:inline-block;width:100%;">
                <span style="color:var(--text-dim);">最新版本</span>
                <strong style="color:#10b981;font-size:1.4rem;margin:0 8px;">v1.0.0</strong>
                <span style="color:var(--text-dim);">发布于 2026-05-30</span>
                <a href="CHANGELOG.md" target="_blank" style="color:var(--cyan);margin-left:12px;font-size:.82rem;">&#x1F4CB; 更新日志</a>
            </div>
            <!-- ===== 桌面客户端下载区 ===== -->
            <div class="section-title" style="margin-top:10px;">&#x1F4BB; 桌面客户端</div>
            <div class="cards" style="margin-bottom:30px;">
                <!-- Windows 客户端 -->
                <div class="card" style="border-color:rgba(0,212,255,.25);background:linear-gradient(135deg,rgba(0,212,255,.06),rgba(0,212,255,.02));">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2.2rem;">🪟</span>
                        <div>
                            <h3 style="color:#00d4ff;margin:0;">Windows 桌面客户端</h3>
                            <p style="color:var(--text-dim);font-size:.8rem;margin:2px 0 0;">Edos AI 启动器 · v1.0.0</p>
                        </div>
                    </div>
                    <p style="color:var(--text-dim);font-size:.82rem;margin-bottom:8px;">一键启动脚本，Chrome/Edge App模式独立窗口运行，支持开机自启、系统托盘</p>
                    <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px;">
                        <span style="background:rgba(0,212,255,.12);color:#22d3ee;padding:3px 10px;border-radius:10px;font-size:.7rem;">~4 KB</span>
                        <span style="background:rgba(16,185,129,.12);color:#10b981;padding:3px 10px;border-radius:10px;font-size:.7rem;">Win10/11</span>
                        <span style="background:rgba(168,85,247,.12);color:#c084fc;padding:3px 10px;border-radius:10px;font-size:.7rem;">需Chrome/Edge</span>
                    </div>
                    <a href="static/downloads/EdosAI_Desktop_v1.0.zip" download class="btn-primary" style="display:inline-block;width:100%;text-align:center;text-decoration:none;">⬇ 下载 Windows 版 (ZIP, 4 KB)</a>
                </div>
                <!-- macOS 客户端 -->
                <div class="card" style="border-color:rgba(100,140,220,.2);">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2.2rem;">🍎</span>
                        <div>
                            <h3 style="color:#8b9dc3;margin:0;">macOS 桌面客户端</h3>
                            <p style="color:var(--text-dim);font-size:.8rem;margin:2px 0 0;">Chrome App 模式 · v1.0.0</p>
                        </div>
                    </div>
                    <p style="color:var(--text-dim);font-size:.82rem;margin-bottom:8px;">Chrome App模式独立窗口运行，支持Spotlight唤起、菜单栏快捷方式</p>
                    <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px;">
                        <span style="background:rgba(100,140,220,.12);color:#8b9dc3;padding:3px 10px;border-radius:10px;font-size:.7rem;">~2 KB</span>
                        <span style="background:rgba(16,185,129,.12);color:#10b981;padding:3px 10px;border-radius:10px;font-size:.7rem;">macOS 11+</span>
                        <span style="background:rgba(245,158,11,.12);color:#fbbf24;padding:3px 10px;border-radius:10px;font-size:.7rem;">需Chrome</span>
                    </div>
                    <a href="static/downloads/EdosAI_Desktop_v1.0.zip" download class="btn-outline" style="display:inline-block;width:100%;text-align:center;text-decoration:none;border-color:rgba(0,212,255,.3);color:#00d4ff;">⬇ 下载 macOS 版 (ZIP, 4 KB)</a>
                </div>
                <!-- Linux 客户端 -->
                <div class="card" style="border-color:rgba(245,158,11,.2);">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2.2rem;">🐧</span>
                        <div>
                            <h3 style="color:#f59e0b;margin:0;">Linux 桌面客户端</h3>
                            <p style="color:var(--text-dim);font-size:.8rem;margin:2px 0 0;">Chrome App 模式 · v1.0.0</p>
                        </div>
                    </div>
                    <p style="color:var(--text-dim);font-size:.82rem;margin-bottom:8px;">Chrome/Chromium App模式独立窗口运行，支持.desktop快捷方式、系统托盘</p>
                    <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px;">
                        <span style="background:rgba(245,158,11,.12);color:#fbbf24;padding:3px 10px;border-radius:10px;font-size:.7rem;">~2 KB</span>
                        <span style="background:rgba(16,185,129,.12);color:#10b981;padding:3px 10px;border-radius:10px;font-size:.7rem;">Ubuntu 20.04+</span>
                        <span style="background:rgba(168,85,247,.12);color:#c084fc;padding:3px 10px;border-radius:10px;font-size:.7rem;">需Chrome</span>
                    </div>
                    <a href="static/downloads/EdosAI_Desktop_v1.0.zip" download class="btn-outline" style="display:inline-block;width:100%;text-align:center;text-decoration:none;border-color:rgba(0,212,255,.3);color:#00d4ff;">⬇ 下载 Linux 版 (ZIP, 4 KB)</a>
                </div>
            </div>
            <!-- PWA + Docker -->
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:30px;">
                <div class="card" style="border-color:rgba(16,185,129,.2);">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2rem;">&#x1F4F1;</span>
                        <div><h3 style="color:#10b981;">PWA 渐进式应用</h3><p style="color:var(--text-dim);font-size:.82rem;">无需安装，浏览器即用</p></div>
                    </div>
                    <p style="color:var(--text-dim);font-size:.82rem;margin-bottom:12px;">支持 Chrome / Edge / Safari 安装到桌面，离线可用，自动更新。</p>
                    <button class="btn-outline btn-sm" onclick="installPWA()" style="width:100%;">&#x1F4F2; 安装到桌面</button>
                </div>
                <div class="card" style="border-color:rgba(59,130,246,.2);">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2rem;">&#x1F433;</span>
                        <div><h3 style="color:#3b82f6;">Docker 一键部署</h3><p style="color:var(--text-dim);font-size:.82rem;">自托管 · 开箱即用</p></div>
                    </div>
                    <code style="display:block;background:rgba(0,0,0,.3);padding:10px;border-radius:8px;color:#00d4ff;font-size:.78rem;margin-bottom:8px;">docker pull edosai/edos-ai:2.4.0</code>
                    <button class="btn-outline btn-sm" onclick="copyDockerCmd()" style="width:100%;">&#x1F4CB; 复制命令</button>
                </div>
            </div>
            <!-- ===== 配置包下载 ===== -->
            <div class="section-title">⚙️ 开发配置包</div>
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:24px;">
                <div class="card" style="border-color:rgba(99,102,241,.2);">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2rem;">&#x1F527;</span>
                        <div>
                            <h3 style="color:#818cf8;margin:0;">启动脚本包</h3>
                            <p style="color:var(--text-dim);font-size:.8rem;margin:2px 0 0;">.bat + .ps1 双脚本 · v1.0.0</p>
                        </div>
                    </div>
                    <p style="color:var(--text-dim);font-size:.82rem;margin-bottom:8px;">Windows启动脚本(.bat/.ps1)，支持Chrome/Edge App模式自动检测启动</p>
                    <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px;">
                        <span style="background:rgba(99,102,241,.12);color:#818cf8;padding:3px 10px;border-radius:10px;font-size:.7rem;">2个脚本</span>
                        <span style="background:rgba(245,158,11,.12);color:#fbbf24;padding:3px 10px;border-radius:10px;font-size:.7rem;">~2 KB</span>
                    </div>
                    <a href="static/downloads/启动Edos_AI.bat" download class="btn-outline" style="display:inline-block;width:100%;text-align:center;text-decoration:none;border-color:rgba(99,102,241,.3);color:#818cf8;">⬇ 下载 .bat 脚本</a>
                    <a href="static/downloads/启动Edos_AI.ps1" download class="btn-outline" style="display:inline-block;width:100%;text-align:center;text-decoration:none;border-color:rgba(99,102,241,.3);color:#818cf8;margin-top:8px;">⬇ 下载 .ps1 脚本</a>
                </div>
                <div class="card" style="border-color:rgba(245,158,11,.2);">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <span style="font-size:2rem;">&#x1F310;</span>
                        <div>
                            <h3 style="color:#f59e0b;margin:0;">桌面快捷入口</h3>
                            <p style="color:var(--text-dim);font-size:.8rem;margin:2px 0 0;">HTML 独立页面 · v1.0.0</p>
                        </div>
                    </div>
                    <p style="color:var(--text-dim);font-size:.82rem;margin-bottom:8px;">双击打开Edos AI独立入口页面，包含一键跳转到主站和AI沙盒的快捷按钮</p>
                    <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px;">
                        <span style="background:rgba(245,158,11,.12);color:#fbbf24;padding:3px 10px;border-radius:10px;font-size:.7rem;">1个文件</span>
                        <span style="background:rgba(16,185,129,.12);color:#10b981;padding:3px 10px;border-radius:10px;font-size:.7rem;">~3 KB</span>
                    </div>
                    <a href="static/downloads/EdosAI_Desktop.html" download class="btn-outline" style="display:inline-block;width:100%;text-align:center;text-decoration:none;border-color:rgba(245,158,11,.3);color:#f59e0b;">⬇ 下载 HTML 入口</a>
                </div>
            </div>
            <!-- 快速配置指南 -->
            <div class="card" style="margin-bottom:24px;border-color:rgba(0,212,255,.15);background:rgba(0,212,255,.03);">
                <h4 style="margin:0 0 8px;color:#00d4ff;">📋 快速配置指南</h4>
                <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px;font-size:.78rem;color:var(--text-dim);">
                    <div>① 下载桌面客户端ZIP包 → 解压到任意目录</div>
                    <div>② 双击 启动Edos_AI.bat → 自动检测Chrome/Edge</div>
                    <div>③ 以独立窗口模式启动，享受原生桌面体验</div>
                </div>
            </div>

            <!-- 功能特性 -->
            <div class="section-title">✨ 客户端核心功能</div>
            <div class="cards" style="margin-bottom:30px;">
                <div class="card"><div class="card-icon">&#x1F9E0;</div><h3>全域记忆离线可用</h3><p style="color:var(--text-dim);font-size:.85rem;">本地向量数据库 + 混合检索，断网也能查询历史记忆</p></div>
                <div class="card"><div class="card-icon">&#x1F504;</div><h3>自动更新</h3><p style="color:var(--text-dim);font-size:.85rem;">后台静默下载更新包，下次启动自动升级，无需手动操作</p></div>
                <div class="card"><div class="card-icon">&#x1F514;</div><h3>系统托盘常驻</h3><p style="color:var(--text-dim);font-size:.85rem;">最小化到系统托盘，全局快捷键（Ctrl+Shift+E）快速唤起</p></div>
                <div class="card"><div class="card-icon">&#x1F510;</div><h3>数据本地加密</h3><p style="color:var(--text-dim);font-size:.85rem;">AES-256本地加密存储，数据完全由您掌控，不上传到云端</p></div>
                <div class="card"><div class="card-icon">&#x1F310;</div><h3>多端同步</h3><p style="color:var(--text-dim);font-size:.85rem;">登录账号后，记忆/工作流/设置跨设备自动同步</p></div>
                <div class="card"><div class="card-icon">&#x1F680;</div><h3>开机自启</h3><p style="color:var(--text-dim);font-size:.85rem;">可选开机自动启动，AI助手随时待命，即时响应</p></div>
            </div>
            <!-- 系统要求 -->
            <!-- 版本更新日志 -->
            <div class="section-title">&#x1F4CB; 版本更新日志</div>
            <div id="changelogsSection" style="margin-bottom:30px;"><div class="empty-state" style="text-align:center;padding:40px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">⏳</div><p style="font-size:15px;font-weight:500;">正在加载更新日志...</p></div></div>
            <!-- 系统要求 -->
            <div class="card" style="margin-bottom:30px;">
                <h3 style="margin-bottom:12px;">&#x1F4BB; 系统要求</h3>
                <table style="width:100%;border-collapse:collapse;font-size:.85rem;">
                    <thead><tr style="border-bottom:1px solid var(--border-glow);"><th style="text-align:left;padding:8px;color:var(--cyan);">项目</th><th style="text-align:left;padding:8px;color:var(--cyan);">最低配置</th><th style="text-align:left;padding:8px;color:var(--cyan);">推荐配置</th></tr></thead>
                    <tbody>
                        <tr style="border-bottom:1px solid rgba(100,140,220,.05);"><td style="padding:8px;">CPU</td><td style="padding:8px;">双核 2.0GHz</td><td style="padding:8px;color:#10b981;">四核 3.0GHz+</td></tr>
                        <tr style="border-bottom:1px solid rgba(100,140,220,.05);"><td style="padding:8px;">内存</td><td style="padding:8px;">4GB RAM</td><td style="padding:8px;color:#10b981;">8GB RAM+</td></tr>
                        <tr style="border-bottom:1px solid rgba(100,140,220,.05);"><td style="padding:8px;">存储</td><td style="padding:8px;">2GB 可用空间</td><td style="padding:8px;color:#10b981;">10GB SSD</td></tr>
                        <tr style="border-bottom:1px solid rgba(100,140,220,.05);"><td style="padding:8px;">网络</td><td style="padding:8px;">宽带连接</td><td style="padding:8px;color:#10b981;">稳定互联网</td></tr>
                        <tr><td style="padding:8px;">操作系统</td><td style="padding:8px;">Win10 / macOS 11 / Ubuntu 20.04</td><td style="padding:8px;color:#10b981;">Win11 / macOS 14 / Ubuntu 22.04</td></tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>


    <!-- 股票市场分析 (垂直业务模块) -->
    <div id="stockMarketPage" class="page">
        <div class="hero" style="padding-bottom:20px;">
            <h1>股市行情 & 个股分析智能体</h1>
            <p class="section-desc">AI驱动的市场洞察 · 技术面+基本面综合分析 · 智能策略建议</p>
        </div>
        <!-- 子Tab切换 -->
        <div class="stock-tabs">
            <button class="stock-tab active" data-stock-tab="market">&#x1F4CA; 大盘行情</button>
            <button class="stock-tab" data-stock-tab="individual">&#x1F50D; 个股深度分析</button>
            <button class="stock-tab" data-stock-tab="strategy">&#x1F9E0; AI策略建议</button>
            <button class="stock-tab" data-stock-tab="watchlist">⭐ 我的自选</button>
            <button class="stock-tab" data-stock-tab="trading">&#x1F4B0; 模拟交易</button>
            <button class="stock-tab" data-stock-tab="__audit__" style="background:linear-gradient(135deg,#10b981,#059669);color:#fff;margin-left:auto;">&#x1F9EA; PM全功能审计</button>
        </div>
        <!-- PM审计面板 -->
        <div id="__stockAuditPanel__" class="stock-panel" style="padding:20px;background:rgba(10,16,40,.95);border-radius:12px;border:1px solid rgba(16,185,129,.3);">
            <div style="display:flex;align-items:center;gap:12px;margin-bottom:16px;">
                <span style="font-size:1.5rem;">&#x1F9EA;</span>
                <div><h3 style="margin:0;color:#10b981;">产品经理 · 全功能审计面板</h3><p style="margin:4px 0 0;color:var(--text-dim);font-size:.8rem;">点击下方按钮自动遍历全部5个功能模块</p></div>
            </div>
            <div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px;">
                <button class="btn-primary" onclick="window.__runPMAudit__()" style="background:linear-gradient(135deg,#10b981,#059669);">▶ 运行全量审计</button>
                <button class="btn-outline" onclick="window.__runPMAuditQuick__()" style="font-size:.8rem;">⚡ 快速抽查(不调用API)</button>
                <button class="btn-outline btn-sm" onclick="document.getElementById('__auditLog__').innerHTML=''" style="font-size:.75rem;">&#x1F5D1; 清空日志</button>
            </div>
            <div id="__auditLog__" style="max-height:500px;overflow-y:auto;font-family:monospace;font-size:.78rem;line-height:1.6;background:rgba(0,0,0,.4);border-radius:8px;padding:16px;color:rgba(200,220,240,.9);"></div>
            <div id="__auditSummary__" style="display:none;margin-top:12px;padding:12px 16px;background:rgba(16,185,129,.1);border-radius:8px;border-left:3px solid #10b981;"></div>
        </div>
        <!-- 大盘行情面板 -->
        <div id="stockMarketPanel" class="stock-panel active">
            <div style="display:flex;justify-content:flex-end;margin-bottom:12px;gap:8px;align-items:center;">
                <span id="breadthSource" style="font-size:.7rem;color:var(--text-dim);margin-right:auto;"></span>
                <span id="marketUpdateTime" style="font-size:.75rem;color:var(--text-dim);">--</span>
                <button class="btn-outline btn-sm" data-action="refreshMarket" style="font-size:.75rem;padding:4px 12px;">&#x1F504; 刷新</button>
            </div>
            <div class="stock-index-cards" id="marketIndices"><div class="empty-state" style="text-align:center;padding:40px 20px;color:var(--text-secondary);grid-column:1/-1;"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">⏳</div><p style="font-size:15px;font-weight:500;margin:0 0 4px;">正在加载大盘指数...</p><p style="font-size:13px;opacity:0.7;margin:0;">实时行情数据获取中</p></div></div>
            <!-- 市场广度 -->
            <div id="marketBreadthSection" class="stock-breadth-section">
                <h3 style="color:var(--text-main);margin-bottom:12px;">&#x1F4CA; 市场情绪仪表</h3>
                <div class="stock-breadth-grid" id="marketBreadthGrid">
                    <div class="stock-breadth-card"><span>上涨家数</span><span class="stock-breadth-val up" id="breadthUp">--</span></div>
                    <div class="stock-breadth-card"><span>下跌家数</span><span class="stock-breadth-val down" id="breadthDown">--</span></div>
                    <div class="stock-breadth-card"><span>涨停</span><span class="stock-breadth-val up" id="breadthLimitUp">--</span></div>
                    <div class="stock-breadth-card"><span>跌停</span><span class="stock-breadth-val down" id="breadthLimitDown">--</span></div>
                </div>
            </div>
            <!-- 最新动态突破 -->
            <div id="stockNewsSection" class="stock-breadth-section" style="display:none;">
                <h3 style="color:var(--text-main);margin-bottom:12px;">&#x1F4F0; 最新动态 · 突破</h3>
                <div id="stockNewsList" class="cards" style="display:flex;flex-direction:column;gap:8px;"><div class="empty-state" style="text-align:center;padding:20px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:32px;margin-bottom:8px;">⏳</div><p style="font-size:14px;font-weight:500;margin:0;">财经快讯加载中...</p></div></div>
            </div>
            <div class="stock-hot-section">
                <h3 style="color:var(--text-main);margin-bottom:16px;">&#x1F525; 热门板块</h3>
                <div id="stockHotSectors" class="cards"><div class="empty-state" style="text-align:center;padding:20px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:32px;margin-bottom:8px;">⏳</div><p style="font-size:14px;font-weight:500;margin:0;">热门板块加载中...</p></div></div>
            </div>
        </div>
        <!-- 个股深度分析面板 -->
        <div id="stockIndividualPanel" class="stock-panel">
            <div class="stock-search-bar">
                <input id="stockSearchInput" type="text" placeholder="输入股票代码或名称（如 600519 / 贵州茅台 / AAPL）" maxlength="20">
                <button id="stockSearchBtn" class="btn-primary">&#x1F50D; 分析</button>
            </div>
            <div id="stockAnalysisResult" class="stock-analysis-result"><div class="empty-state" style="text-align:center;padding:40px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">&#x1F50D;</div><p style="font-size:15px;font-weight:500;margin:0 0 4px;">股票分析结果</p><p style="font-size:13px;opacity:0.7;margin:0;">输入股票代码开始分析</p></div></div>
            <!-- K线图容器 -->
            <div id="stockKlineSection" class="stock-kline-section" style="display:none;">
                <div class="stock-kline-header">
                    <h3>&#x1F4C8; K线图表</h3>
                    <div class="stock-kline-controls">
                        <button class="stock-kline-period active" data-period="day">日K</button>
                        <button class="stock-kline-period" data-period="week">周K</button>
                        <button class="stock-kline-period" data-period="month">月K</button>
                        <button class="stock-kline-period" data-period="60min">60分</button>
                        <button class="stock-kline-period" data-period="30min">30分</button>
                    </div>
                </div>
                <div class="stock-kline-chart-wrap">
                    <canvas id="stockKlineCanvas" class="stock-kline-canvas"></canvas>
                </div>
                <div class="stock-kline-legend" id="stockKlineLegend"></div>
            </div>
            <!-- 技术指标子面板 -->
            <div id="stockIndicatorSection" class="stock-indicator-section" style="display:none;">
                <div class="stock-indicator-tabs">
                    <button class="stock-ind-tab active" data-indicator="macd">MACD</button>
                    <button class="stock-ind-tab" data-indicator="rsi">RSI(14)</button>
                    <button class="stock-ind-tab" data-indicator="boll">BOLL(20)</button>
                    <button class="stock-ind-tab" data-indicator="kdj">KDJ(9)</button>
                </div>
                <div class="stock-ind-chart-wrap">
                    <canvas id="stockIndicatorCanvas" class="stock-ind-canvas"></canvas>
                </div>
                <div class="stock-ind-values" id="stockIndicatorValues"><div class="empty-state" style="text-align:center;padding:20px;color:var(--text-secondary);"><span style="opacity:0.7;">选择股票后显示技术指标</span></div></div>
            </div>
        </div>
        <!-- AI策略建议面板 -->
        <div id="stockStrategyPanel" class="stock-panel">
            <div class="stock-chat-container">
                <div class="stock-chat-messages" id="stockChatMessages">
                    <div class="stock-chat-welcome">
                        <div class="stock-chat-welcome-icon">&#x1F9E0;</div>
                        <h3>AI 投资策略顾问</h3>
                        <p>我可以帮你分析市场趋势、评估个股价值、制定投资策略</p>
                        <div class="stock-quick-questions">
                            <button class="stock-quick-q" data-question="当前A股市场整体估值水平如何？有哪些值得关注的板块？">&#x1F4CA; 当前A股市场整体估值水平如何？</button>
                            <button class="stock-quick-q" data-question="请分析新能源板块的投资逻辑和主要风险点">⚡ 分析新能源板块投资逻辑</button>
                            <button class="stock-quick-q" data-question="如何构建一个稳健的长期投资组合？请给出配置建议">&#x1F3AF; 如何构建稳健投资组合？</button>
                            <button class="stock-quick-q" data-question="最近市场有哪些重大政策或事件可能影响股市？">&#x1F4F0; 近期影响股市的重大事件</button>
                        </div>
                    </div>
                </div>
                <div class="stock-chat-input-row">
                    <input id="stockChatInput" type="text" placeholder="输入你的投资问题..." maxlength="500">
                    <button id="stockChatSendBtn" class="btn-primary">发送</button>
                </div>
            </div>
        </div>
        <!-- 自选股面板 -->
        <div id="stockWatchlistPanel" class="stock-panel">
            <div class="stock-watchlist-header">
                <div class="stock-search-bar" style="margin-bottom:16px;">
                    <input id="watchlistAddInput" type="text" placeholder="添加自选股（输入代码或名称）" maxlength="20">
                    <button id="watchlistAddBtn" class="btn-primary">+ 添加</button>
                </div>
            </div>
            <div id="stockWatchlistContent" class="cards"><div class="empty-state" style="text-align:center;padding:40px 20px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">⭐</div><p style="font-size:15px;font-weight:500;margin:0 0 4px;">暂无自选股</p><p style="font-size:13px;opacity:0.7;margin:0;">添加股票代码即可跟踪关注</p></div></div>
        </div>
        <!-- 模拟交易面板 -->
        <div id="stockTradingPanel" class="stock-panel">
            <div class="stock-trading-container">
                <!-- 账户概览 -->
                <div class="stock-trading-summary" id="tradingSummary">
                    <div class="stock-trading-stat"><span class="trading-stat-label">总资产</span><span class="trading-stat-val" id="tradingTotalValue">¥100,000.00</span></div>
                    <div class="stock-trading-stat"><span class="trading-stat-label">可用资金</span><span class="trading-stat-val" id="tradingCash">¥100,000.00</span></div>
                    <div class="stock-trading-stat"><span class="trading-stat-label">总盈亏</span><span class="trading-stat-val" id="tradingPnL">¥0.00</span></div>
                    <button class="btn-outline btn-sm" onclick="resetPaperPortfolio()" style="font-size:.75rem;padding:4px 12px;">&#x1F504; 重置账户</button>
                </div>
                <!-- 交易表单 -->
                <div class="stock-trading-form" id="tradingForm">
                    <h3>&#x1F4DD; 下单交易</h3>
                    <div class="stock-trading-row">
                        <select id="tradingAction" class="trading-select">
                            <option value="buy">买入</option>
                            <option value="sell">卖出</option>
                        </select>
                        <input id="tradingCode" type="text" placeholder="股票代码（如 600519）" maxlength="10" class="trading-input-code">
                        <input id="tradingPrice" type="number" placeholder="价格" step="0.01" min="0.01" class="trading-input-price">
                        <input id="tradingShares" type="number" placeholder="数量（股）" step="100" min="100" class="trading-input-shares">
                        <button id="tradingSubmitBtn" class="btn-primary" style="white-space:nowrap;">确认下单</button>
                    </div>
                    <div id="tradingRealtimeQuote" class="trading-quote-hint"></div>
                </div>
                <!-- 持仓列表 -->
                <div class="stock-trading-holdings" id="tradingHoldings">
                    <h3>&#x1F4E6; 当前持仓</h3>
                    <div id="tradingHoldingsContent"><div class="empty-state" style="text-align:center;padding:20px;color:var(--text-secondary);"><span style="opacity:0.7;">暂无持仓数据</span></div></div>
                </div>
                <!-- 交易记录 -->
                <div class="stock-trading-history" id="tradingHistory">
                    <h3>&#x1F4CB; 交易记录</h3>
                    <div id="tradingHistoryContent"><div class="empty-state" style="text-align:center;padding:20px;color:var(--text-secondary);"><span style="opacity:0.7;">暂无交易记录</span></div></div>
                </div>
                <!-- 回测引擎 -->
                <div class="stock-backtest-section" id="backtestSection">
                    <h3>⚙️ 策略回测</h3>
                    <div class="stock-backtest-form">
                        <input id="backtestCode" type="text" placeholder="股票代码 600519" maxlength="10" class="backtest-input">
                        <select id="backtestStrategy" class="backtest-select">
                            <option value="ma_cross">MA均线交叉</option>
                            <option value="macd_cross">MACD金叉死叉</option>
                            <option value="rsi_reversal">RSI超买超卖</option>
                            <option value="boll_breakout">布林带突破</option>
                        </select>
                        <input id="backtestCapital" type="number" placeholder="初始资金" value="100000" step="10000" min="10000" class="backtest-input-small">
                        <button id="backtestRunBtn" class="btn-primary" style="white-space:nowrap;font-size:.82rem;">▶ 运行回测</button>
                    </div>
                    <div id="backtestResult" class="stock-backtest-result" style="display:none;"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- 设置页面 (P7-9) -->
    <div id="settingsPage" class="page"><div class="hero"><h1>设置</h1></div><div id="settingsContainer"><div class="empty-state" style="text-align:center;padding:40px 20px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">⏳</div><p style="font-size:15px;font-weight:500;margin:0 0 4px;">正在加载设置...</p><p style="font-size:13px;opacity:0.7;margin:0;">用户设置面板加载中</p></div></div>
    <!-- 积分任务面板 -->
    <div id="questPanelSection" style="max-width:640px;margin:24px auto;padding:0 20px;">
        <div class="section-title">&#x1F3AF; 积分任务</div>
        <div id="questPanelContent"><div class="empty-state" style="text-align:center;padding:40px;color:var(--text-secondary);"><div class="empty-state-icon" style="font-size:48px;margin-bottom:12px;">⏳</div><p style="font-size:15px;font-weight:500;">正在加载任务列表...</p></div></div>
    </div>
    <!-- 版本信息 -->
    <div class="version-info" style="max-width:640px;margin:0 auto 40px;padding:0 20px;text-align:center;color:var(--text-dim);font-size:.82rem;">
        <p>Edos AI v1.0.0 · Build 20260609 · © 2026 上海意道网智能科技有限责任公司</p>
        <p style="margin-top:4px;font-size:.75rem;">前端版本: 2.37.0 | API版本: v1 | 区域: ap-east-1</p>
    </div>
    </div>

    <!-- 独立页面 -->
    <div id="productPage" class="page"><div class="hero"><h1>产品能力</h1><p style="color:var(--text-dim);max-width:700px;margin:8px auto 0;">六大核心技术引擎，构建企业级可解释智能体平台</p></div><div class="cards"><div class="card"><div class="card-icon">&#x1F9E0;</div><h3>全域记忆架构</h3><p>L1-L5五层记忆体系：会话记忆→项目记忆→领域知识→推理策略→元认知。跨项目、跨会话的语义检索，支持向量化存储与检索增强生成(RAG)。</p><div class="tech-detail">核心技术：向量数据库 + 混合检索 + 记忆衰减策略 · 最大容量 100GB+</div></div><div class="card"><div class="card-icon">&#x1F4C8;</div><h3>可解释推理图谱</h3><p>可视化推理链全程追溯，支持节点编辑、假设验证、矛盾检测。提供置信度评分与证据溯源，满足金融、法律等强监管场景的审计合规要求。</p><div class="tech-detail">支持：JSON导出 · PDF审计报告 · 图数据库持久化 · 实时交互式探索</div></div><div class="card"><div class="card-icon">⚙️</div><h3>工作流自生成引擎</h3><p>自然语言描述即可自动生成可执行工作流，支持条件分支、循环控制、并行任务编排。内置200+预置模板，覆盖RPA、数据处理、审批流转等场景。</p><div class="tech-detail">兼容标准：BPMN 2.0 · 支持Python/JS自定义节点 · 可视化编辑器</div></div><div class="card"><div class="card-icon">&#x1F916;</div><h3>反思Agent + 自博弈工厂</h3><p>Agent自我分析执行结果，自动改进策略。自博弈训练管线持续生成合成数据，通过对抗训练提升模型鲁棒性，实现端到端自动化迭代。</p><div class="tech-detail">训练效率：千卡GPU并行 · 日生成50万+训练样本 · 自动评估+回滚机制</div></div><div class="card"><div class="card-icon">&#x1F510;</div><h3>私有化部署方案</h3><p>国产信创全栈适配：鲲鹏/飞腾CPU + 统信UOS/麒麟OS。Docker Compose一键部署，Kubernetes Helm Chart弹性扩缩，数据完全留存客户本地。</p><div class="tech-detail">安全认证：等保三级 · 信创适配认证 · TLS 1.3 + AES-256加密 · 审计日志</div></div><div class="card"><div class="card-icon">&#x1F50C;</div><h3>开放API平台</h3><p>兼容标准 API格式，提供Python/JavaScript SDK。支持流式输出(SSE)、多模态输入、Webhook回调。5分钟快速集成。</p><div class="tech-detail">API能力：对话生成 · 推理图谱 · 记忆检索 · 自博弈训练 · 用量监控</div></div></div></div>
    <div id="solutionsPage" class="page"><div class="hero"><h1>行业解决方案</h1><p style="color:var(--text-dim);max-width:700px;margin:8px auto 0;">深耕金融、法律、政务等领域，提供可落地的AI智能体解决方案</p></div><div class="cards"><div class="card"><div class="card-icon">&#x1F3E6;</div><h3>金融行业</h3><p>智能信贷审批：多维度风险评估+推理链可追溯，满足银保监合规要求。反洗钱策略生成：基于全域记忆的异常交易检测与自动报告。合同智能解析：金融合同关键条款提取与风险预警。</p><div class="tech-detail">案例：某银行信贷审批效率提升60%，坏账率下降23%</div></div><div class="card"><div class="card-icon">⚖️</div><h3>法律行业</h3><p>智能合同审查：百页合同分钟级审阅，条款级风险标注。法规知识问答：实时检索最新法律法规库，支持引证溯源。司法案例推理：基于推理图谱的相似案例检索与判决预测。</p><div class="tech-detail">案例：某律所合同审查效率提升80%，人工复核工作量减半</div></div><div class="card"><div class="card-icon">&#x1F3DB;️</div><h3>政务领域</h3><p>政策智能问答：7×24小时政策咨询服务，支持多轮对话精准理解。公文辅助生成：基于模板+上下文的公文智能起草与合规审查。舆情分析研判：全域记忆驱动的舆情演化追踪与趋势预测。</p><div class="tech-detail">案例：某政务大厅咨询响应时间从平均30分钟降至秒级</div></div><div class="card"><div class="card-icon">&#x1F4BB;</div><h3>软件开发</h3><p>AI代码审查：自动检测安全漏洞、代码规范违规，推理评分。智能测试生成：基于代码语义理解自动生成单元测试与集成测试。技术文档撰写：代码分析后自动生成API文档与架构说明。</p><div class="tech-detail">支持语言：Python / Java / JavaScript / Go / C++ 等主流语言</div></div><div class="card"><div class="card-icon">&#x1F3E5;</div><h3>医疗健康</h3><p>临床决策辅助：基于医学知识图谱的诊断推理与治疗方案推荐。病历结构化：NLP自动抽取病历关键信息并标准化。药物相互作用检测：全域记忆驱动的药物配伍禁忌实时预警。</p><div class="tech-detail">合规：遵循《医疗卫生机构网络安全管理办法》数据安全标准</div></div><div class="card"><div class="card-icon">&#x1F393;</div><h3>教育科研</h3><p>智能导师系统：个性化学习路径规划与自适应难度调整。论文学术助手：文献综述自动生成、实验假设推理验证。代码教学评价：基于推理图谱的编程思路分析与精准反馈。</p><div class="tech-detail">支持：K12到高等教育全学段 · 多学科知识图谱覆盖</div></div></div></div>
    <div id="developersPage" class="page"><div class="hero"><h1>开发者生态</h1><p style="color:var(--text-dim);max-width:700px;margin:8px auto 0;">丰富的工具链与社区资源，助力开发者快速构建AI应用</p></div><div class="cards"><div class="card"><div class="card-icon">&#x1F4D8;</div><h3>交互式API文档</h3><p>提供完整的RESTful API参考文档，支持在线调试、代码示例自动生成（cURL/Python/JS/Go）。兼容标准 API，零修改切换。</p><div class="tech-detail">快速开始：5分钟完成首次API调用 · Swagger/OpenAPI 3.0规范</div></div><div class="card"><div class="card-icon">&#x1F419;</div><h3>GitHub 开源生态</h3><p>核心SDK及示例代码采用MIT协议开源。欢迎社区贡献插件、连接器和垂直领域模型微调方案。Issue和PR响应时间 &lt; 24h。</p><div class="tech-detail">热门仓库：edos-python-sdk · edos-js-sdk · edos-workflow-examples</div></div><div class="card"><div class="card-icon">&#x1F4AC;</div><h3>开发者社区</h3><p>Discord / 微信开发者社群，技术团队直接参与讨论。每周技术分享直播，每月开发者挑战赛。金牌贡献者获得API额度奖励和内测资格。</p><div class="tech-detail">社区规模：3000+ 开发者 · 月度活动 4+ 场</div></div><div class="card"><div class="card-icon">&#x1F3AF;</div><h3>众测激励计划</h3><p>通过众测平台参与产品测试，提交高质量反馈和Bug报告即可获得积分奖励。积分可兑换API调用额度或实物礼品。</p><div class="tech-detail">活跃测试者：500+ · 累计发放积分：200,000+ pts</div></div><div class="card"><div class="card-icon">&#x1F680;</div><h3>快速集成指南</h3><p>提供Python、JavaScript、Java、Go等多语言SDK，5行代码即可调用。Docker镜像开箱即用，支持AWS/Azure/阿里云/华为云部署。</p><div class="tech-detail">包管理器：pip install edos-ai · npm install edos-ai · Maven Central</div></div><div class="card"><div class="card-icon">&#x1F4CA;</div><h3>开放平台控制台</h3><p>可视化API用量监控、实时日志查看、告警策略配置。支持团队协作与多项目管理，API Key权限细粒度控制。</p><div class="tech-detail">功能：用量分析 · 账单管理 · 安全审计 · Webhook配置</div></div></div></div>
    <div id="aboutPage" class="page"><div class="hero"><h1>关于伊豆 AI</h1><p style="color:var(--text-dim);font-size:1.1rem;">使命：让智能体成为可信任的数字伙伴</p></div><div class="about-content"><div class="about-intro"><h3 style="color:var(--cyan);margin-bottom:16px;">&#x1F3E2; 公司简介</h3><p style="margin-bottom:1rem;">上海意道网智能科技有限责任公司（Edos AI）成立于2026年，总部位于上海市松江区洞泾人工智能产业基地16号楼403室，是国内领先的企业级可解释智能体平台提供商。公司以"让智能体成为可信任的数字伙伴"为使命，自主研发全域记忆架构、推理图谱、自博弈工厂等六大核心技术引擎，为金融、法律、政务、软件开发等行业提供可解释、可审计、可私有化部署的AI智能体解决方案。</p></div><div class="about-stats"><div class="about-stat-item"><span class="about-stat-num" data-count="6">0</span><span class="about-stat-label">核心技术引擎</span></div><div class="about-stat-item"><span class="about-stat-num" data-count="3000">0</span><span class="about-stat-label">开发者生态</span></div><div class="about-stat-item"><span class="about-stat-num" data-count="200">0</span><span class="about-stat-label">预置模板</span></div><div class="about-stat-item"><span class="about-stat-num" data-count="99.99">0</span><span class="about-stat-label">% SLA保障</span></div></div><div class="about-section"><h3 style="color:var(--cyan);margin:24px 0 16px;">&#x1F4DC; 资质与认证</h3><div class="about-cert-grid"><div class="about-cert-card"><span class="about-cert-icon">&#x1F6E1;</span><strong>等保三级</strong><br>信息安全等级保护</div><div class="about-cert-card"><span class="about-cert-icon">&#x1F4BB;</span><strong>信创适配</strong><br>鲲鹏/飞腾 + 统信/麒麟</div><div class="about-cert-card"><span class="about-cert-icon">&#x1F510;</span><strong>ISO 27001</strong><br>信息安全管理体系</div><div class="about-cert-card"><span class="about-cert-icon">&#x1F3DB;</span><strong>行业协会理事</strong><br>上海市人工智能行业协会</div></div></div><div class="about-section"><h3 style="color:var(--cyan);margin:24px 0 16px;">&#x1F30D; 核心价值观</h3><div class="about-values"><div class="about-value-item"><span class="about-value-icon">&#x1F512;</span><h4>可解释性</h4><p>每一决策链路全程可追溯，满足强监管场景审计要求</p></div><div class="about-value-item"><span class="about-value-icon">&#x1F3E0;</span><h4>数据主权</h4><p>支持私有化部署，数据完全留存客户本地，零外部传输</p></div><div class="about-value-item"><span class="about-value-icon">&#x1F91D;</span><h4>开放生态</h4><p>标准API + SDK + 开源社区，降低企业AI落地门槛</p></div><div class="about-value-item"><span class="about-value-icon">&#x26A1;</span><h4>持续进化</h4><p>自博弈工厂驱动模型自主迭代，能力日日见长</p></div></div></div><div class="about-section"><h3 style="color:var(--cyan);margin:24px 0 16px;">&#x1F4DE; 联系方式</h3><div class="about-contact-grid"><div class="about-contact-card"><span class="about-contact-icon">&#x1F310;</span><div><strong>官网</strong><br><a href="https://edosai.com" style="color:var(--cyan);">https://edosai.com</a></div></div><div class="about-contact-card"><span class="about-contact-icon">&#x1F4E7;</span><div><strong>邮箱</strong><br>contact@edosai.com</div></div><div class="about-contact-card"><span class="about-contact-icon">&#x1F4CD;</span><div><strong>地址</strong><br>上海市松江区洞泾人工智能产业基地16号楼403室</div></div><div class="about-contact-card"><span class="about-contact-icon">&#x1F4DE;</span><div><strong>商务合作</strong><br>sales@edosai.com</div></div></div></div></div></div>
    <div id="pricingPage" class="page"><div class="hero"><h1>定价方案</h1><p style="color:var(--text-dim);max-width:600px;margin:8px auto 0;">灵活的按量计费体系，从免费起步到企业定制，满足不同阶段需求</p></div>
        <div id="pricingTableContainer"></div>
        <!-- v4.4: 用量仪表盘（标准资源点可视化） -->
        <div id="usageDashboardWrap" style="display:none; max-width:900px; margin:0 auto 24px; padding:0 20px;">
            <div class="usage-dashboard" id="usageDashboard">
                <div class="usage-dash-header"><span>&#x1F4CA; 我的用量仪表盘</span><span class="usage-dash-period" id="usageDashPeriod">本月</span></div>
                <div class="usage-dash-gauges">
                    <div class="usage-gauge" id="usageGaugeApi"><div class="gauge-ring"><svg viewBox="0 0 80 80"><circle cx="40" cy="40" r="34" fill="none" stroke="var(--border-glow)" stroke-width="6"/><circle cx="40" cy="40" r="34" fill="none" stroke="var(--cyan)" stroke-width="6" stroke-dasharray="0 213.6" stroke-linecap="round" transform="rotate(-90 40 40)" id="gaugeApiArc"/></svg><div class="gauge-text" id="gaugeApiText">0%</div></div><div class="gauge-label">API 调用</div><div class="gauge-detail" id="gaugeApiDetail">0/1,000</div></div>
                    <div class="usage-gauge" id="usageGaugeMemory"><div class="gauge-ring"><svg viewBox="0 0 80 80"><circle cx="40" cy="40" r="34" fill="none" stroke="var(--border-glow)" stroke-width="6"/><circle cx="40" cy="40" r="34" fill="none" stroke="#a78bfa" stroke-width="6" stroke-dasharray="0 213.6" stroke-linecap="round" transform="rotate(-90 40 40)" id="gaugeMemArc"/></svg><div class="gauge-text" id="gaugeMemText">0%</div></div><div class="gauge-label">记忆存储</div><div class="gauge-detail" id="gaugeMemDetail">0/100MB</div></div>
                    <div class="usage-gauge" id="usageGaugeProject"><div class="gauge-ring"><svg viewBox="0 0 80 80"><circle cx="40" cy="40" r="34" fill="none" stroke="var(--border-glow)" stroke-width="6"/><circle cx="40" cy="40" r="34" fill="none" stroke="#34d399" stroke-width="6" stroke-dasharray="0 213.6" stroke-linecap="round" transform="rotate(-90 40 40)" id="gaugeProjArc"/></svg><div class="gauge-text" id="gaugeProjText">0/1</div></div><div class="gauge-label">项目数</div><div class="gauge-detail" id="gaugeProjDetail">0/1</div></div>
                </div>
                <div class="usage-dash-footer"><span id="usageDashReset">下月1日重置</span><button class="usage-dash-upgrade-btn" onclick="showPage('pricing');document.querySelector('.pricing-card.featured')?.scrollIntoView({behavior:'smooth'});">升级解锁 →</button></div>
            </div>
        </div>
        <!-- 月/年付切换 -->
        <div class="billing-toggle-wrap"><span class="billing-label active" data-billing="monthly">按月付费</span><button class="billing-toggle" id="billingToggleBtn" aria-label="切换计费周期" data-billing="monthly"></button><span class="billing-label" data-billing="yearly">按年付费 <span class="billing-save-badge" style="display:none;">省17%</span></span></div>
        <div class="pricing-grid">
            <div class="pricing-card" data-plan="free"><div class="pricing-plan-name">&#x1F680; 免费版</div><div class="pricing-plan-desc">个人开发者 & 产品体验</div><div class="pricing-price-row"><span class="pricing-amount" data-period="monthly" data-price="0">¥0</span><span class="pricing-period" data-period="monthly">/月</span><span class="pricing-period" data-period="yearly" style="display:none;">/年</span></div><div class="pricing-billing-note" data-period="monthly">永久免费，无需信用卡</div><div class="pricing-billing-note" data-period="yearly" style="display:none;">永久免费，无需信用卡</div><div class="pricing-divider"></div><ul class="pricing-features"><li><span class="pf-icon yes">✓</span> 3个项目</li><li><span class="pf-icon yes">✓</span> 200MB 全域记忆</li><li><span class="pf-icon yes">✓</span> 3,000次 API调用/月<span class="daily-hint">≈100次/天</span></li><li><span class="pf-icon yes">✓</span> 30次沙盒对话/天</li><li><span class="pf-icon yes">✓</span> 基础推理图谱</li><li><span class="pf-icon yes">✓</span> 5次AI生图/月</li><li><span class="pf-icon no">—</span> 自博弈训练</li><li><span class="pf-icon no">—</span> 私有化部署</li><li><span class="pf-icon no">—</span> SSO / 审计日志</li></ul><button class="btn-outline" style="width:100%;" onclick="showPage('sandbox')">免费开始 →</button></div>
            <div class="pricing-card" data-plan="basic"><div class="pricing-plan-name">⭐ 基础版</div><div class="pricing-plan-desc">自由职业者 & 个人用户</div><div class="pricing-price-row"><span class="pricing-amount" data-period="monthly" data-price="49">¥49</span><span class="pricing-amount" data-period="yearly" data-price="39" style="display:none;">¥39</span><span class="pricing-period" data-period="monthly">/月</span><span class="pricing-period" data-period="yearly" style="display:none;">/年</span></div><div class="pricing-billing-note" data-period="monthly">年付 ¥39/月，省 20%</div><div class="pricing-billing-note" data-period="yearly" style="display:none;">年付 ¥468/年，月均 ¥39</div><div class="pricing-divider"></div><ul class="pricing-features"><li class="highlight"><span class="pf-icon yes">✓</span> 5个项目</li><li class="highlight"><span class="pf-icon yes">✓</span> 1GB 全域记忆</li><li class="highlight"><span class="pf-icon yes">✓</span> 10,000次 API调用/月<span class="daily-hint">≈333次/天</span></li><li><span class="pf-icon yes">✓</span> 100次沙盒对话/天</li><li><span class="pf-icon yes">✓</span> 20次AI生图/月</li><li><span class="pf-icon no">—</span> 自博弈训练</li><li><span class="pf-icon no">—</span> 私有化部署</li></ul><button class="btn-outline" style="width:100%;" onclick="document.getElementById('enterpriseQuoteModal').style.display='flex'">升级基础版 →</button></div>
            <div class="pricing-card featured" data-plan="pro"><div class="pricing-popular-badge">&#x1F525; 最受欢迎</div><div class="pricing-plan-name">&#x1F48E; 专业版</div><div class="pricing-plan-desc">专业人士 & 小团队</div><div class="pricing-price-row"><span class="pricing-amount" data-period="monthly" data-price="149">¥149</span><span class="pricing-amount" data-period="yearly" data-price="119" style="display:none;">¥119</span><span class="pricing-period" data-period="monthly">/月</span><span class="pricing-period" data-period="yearly" style="display:none;">/年</span></div><div class="pricing-billing-note" data-period="monthly">年付 ¥119/月，省 20%</div><div class="pricing-billing-note" data-period="yearly" style="display:none;">年付 ¥1,428/年，月均 ¥119</div><div class="pricing-divider"></div><ul class="pricing-features"><li class="highlight"><span class="pf-icon yes">✓</span> 10个项目</li><li class="highlight"><span class="pf-icon yes">✓</span> 10GB 全域记忆</li><li class="highlight"><span class="pf-icon yes">✓</span> 100,000次 API调用/月<span class="daily-hint">≈3,333次/天</span></li><li class="highlight"><span class="pf-icon yes">✓</span> 高级推理图谱（1,000节点/次）</li><li><span class="pf-icon yes">✓</span> 不限沙盒对话</li><li><span class="pf-icon yes">✓</span> 基础自博弈训练</li><li><span class="pf-icon no">—</span> 私有化部署</li><li><span class="pf-icon no">—</span> SSO / 审计日志</li></ul><button class="btn-primary" style="width:100%;" onclick="document.getElementById('enterpriseQuoteModal').style.display='flex'">立即订阅 →</button></div>
            <div class="pricing-card" data-plan="team"><div class="pricing-plan-name">&#x1F465; 团队版</div><div class="pricing-plan-desc">中小团队 · 协作增效</div><div class="pricing-price-row"><span class="pricing-amount" data-period="monthly" data-price="499">¥499</span><span class="pricing-amount" data-period="yearly" data-price="399" style="display:none;">¥399</span><span class="pricing-period" data-period="monthly">/月</span><span class="pricing-period" data-period="yearly" style="display:none;">/年</span></div><div class="pricing-billing-note" data-period="monthly">年付 ¥399/月，省 20%</div><div class="pricing-billing-note" data-period="yearly" style="display:none;">年付 ¥4,788/年，月均 ¥399</div><div class="pricing-divider"></div><ul class="pricing-features"><li class="highlight"><span class="pf-icon yes">✓</span> 50个项目</li><li class="highlight"><span class="pf-icon yes">✓</span> 50GB 共享记忆</li><li class="highlight"><span class="pf-icon yes">✓</span> 500,000次 API调用/月<span class="daily-hint">≈16,667次/天</span></li><li class="highlight"><span class="pf-icon yes">✓</span> 高级推理图谱（不限节点）</li><li><span class="pf-icon yes">✓</span> 最多20名成员</li><li><span class="pf-icon yes">✓</span> 角色权限管理</li><li><span class="pf-icon yes">✓</span> 高级自博弈训练</li><li><span class="pf-icon yes">✓</span> 私有化部署（可选附加）</li><li><span class="pf-icon no">—</span> SSO / 审计日志</li><li><span class="pf-icon no">—</span> SLA 99.9%</li></ul><button class="btn-outline" style="width:100%;" onclick="document.getElementById('enterpriseQuoteModal').style.display='flex'">团队试用 →</button></div>
            <div class="pricing-card" data-plan="enterprise"><div class="pricing-plan-name">&#x1F3E2; 企业版</div><div class="pricing-plan-desc">大型企业 & 政府机构</div><div class="pricing-price-row"><span class="pricing-amount" data-period="monthly" data-price="custom">定制</span><span class="pricing-amount" data-period="yearly" data-price="custom" style="display:none;">定制</span><span class="pricing-period" data-period="monthly">报价</span><span class="pricing-period" data-period="yearly" style="display:none;">报价</span></div><div class="pricing-billing-note" data-period="monthly">按需定制，专属方案</div><div class="pricing-billing-note" data-period="yearly" style="display:none;">按需定制，专属方案</div><div class="pricing-divider"></div><ul class="pricing-features"><li class="highlight"><span class="pf-icon yes">✓</span> 不限项目</li><li class="highlight"><span class="pf-icon yes">✓</span> 100GB+ 全域记忆</li><li class="highlight"><span class="pf-icon yes">✓</span> 1,000,000+次 API调用/月</li><li class="highlight"><span class="pf-icon yes">✓</span> 无限推理图谱节点</li><li><span class="pf-icon yes">✓</span> 不限沙盒对话</li><li><span class="pf-icon yes">✓</span> 高级自博弈训练</li><li><span class="pf-icon yes">✓</span> 私有化部署（信创适配）</li><li><span class="pf-icon yes">✓</span> SSO + 审计日志</li><li><span class="pf-icon yes">✓</span> SLA 99.9% 保障</li><li><span class="pf-icon yes">✓</span> 专属技术支持</li></ul><button class="btn-outline" style="width:100%;" id="openEnterpriseFormBtn">获取报价 →</button></div>
        </div>
        <!-- 功能对比表 -->
        <div class="pricing-compare-wrap"><h3 style="text-align:center;margin-bottom:20px;color:var(--text-main);">&#x1F4CB; 功能全面对比</h3><table class="pricing-compare-table"><thead><tr><th>功能特性</th><th>免费版</th><th>基础版</th><th>专业版</th><th>团队版</th><th>企业版</th></tr></thead><tbody><tr><td>项目数量</td><td>1个</td><td>3个</td><td>10个</td><td>50个</td><td><span class="compare-yes">不限</span></td></tr><tr><td>全域记忆容量</td><td>100MB</td><td>1GB</td><td>10GB</td><td>50GB</td><td><span class="compare-yes">100GB+</span></td></tr><tr><td>API调用次数</td><td>1,000/月</td><td>5,000/月</td><td>100,000/月</td><td>500,000/月</td><td><span class="compare-yes">1,000,000+/月</span></td></tr><tr><td>推理图谱节点</td><td>100/次</td><td>300/次</td><td>1,000/次</td><td><span class="compare-yes">不限</span></td><td><span class="compare-yes">不限</span></td></tr><tr><td>沙盒对话</td><td>50次/天</td><td><span class="compare-yes">不限</span></td><td><span class="compare-yes">不限</span>#!/usr/bin/env python3
"""自动生成的文件"""

"""
Edos AI 后端服务 - 完整版
包含所有业务模块的 API 接口
"""

import os
import json
import logging
import random
import time
import hashlib
import uuid
import asyncio
from datetime import datetime, timedelta
from collections import defaultdict
from typing import List, Dict, Optional, Any
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException, Depends, Request, WebSocket, WebSocketDisconnect
from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, Field, EmailStr
from jose import JWTError, jwt
from passlib.context import CryptContext

load_dotenv()
logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s")
logger = logging.getLogger(__name__)

# ============== 全局配置 ==============

SECRET_KEY = os.getenv("SECRET_KEY", os.urandom(64).hex())
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60  # 从1440降至60分钟，提升安全性

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# 服务启动时间戳 (用于 v1/system 接口)
startup_time = time.time()

# ============== 数据持久化配置 ==============
import sqlite3
from pathlib import Path
import json

DB_PATH = os.path.join(os.path.dirname(__file__), "edos_data.db")

def init_sqlite():
    """初始化SQLite数据库"""
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()

    c.execute('''CREATE TABLE IF NOT EXISTS users (
        id TEXT PRIMARY KEY,
        username TEXT UNIQUE NOT NULL,
        email TEXT,
        phone TEXT,
        hashed_password TEXT NOT NULL,
        role TEXT DEFAULT 'user',
        created_at TEXT,
        updated_at TEXT,
        avatar TEXT,
        nickname TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS orders (
        id TEXT PRIMARY KEY,
        user_id TEXT,
        plan_name TEXT,
        amount REAL,
        status TEXT,
        created_at TEXT,
        paid_at TEXT,
        payment_method TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS enterprises (
        id TEXT PRIMARY KEY,
        name TEXT,
        license_key TEXT,
        owner_id TEXT,
        created_at TEXT,
        employees INTEGER DEFAULT 0,
        industry TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS files (
        id TEXT PRIMARY KEY,
        filename TEXT,
        filepath TEXT,
        size INTEGER,
        mime_type TEXT,
        user_id TEXT,
        created_at TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS logs (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        level TEXT,
        message TEXT,
        user_id TEXT,
        created_at TEXT,
        module TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS workflows (
        id TEXT PRIMARY KEY,
        name TEXT,
        description TEXT,
        steps TEXT,
        user_id TEXT,
        created_at TEXT,
        status TEXT DEFAULT 'active'
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS deployments (
        id TEXT PRIMARY KEY,
        repo_url TEXT,
        branch TEXT,
        server_ip TEXT,
        status TEXT,
        created_at TEXT,
        started_at TEXT,
        completed_at TEXT,
        logs TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS subscriptions (
        id TEXT PRIMARY KEY,
        user_id TEXT,
        plan_name TEXT,
        status TEXT,
        started_at TEXT,
        expires_at TEXT,
        usage_limit INTEGER,
        usage_used INTEGER DEFAULT 0
    )''')

    conn.commit()
    conn.close()
    logger.info(f"✓ SQLite数据库初始化完成: {DB_PATH}")

def save_to_sqlite(table: str, data: dict):
    try:
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        cols = list(data.keys())
        vals = list(data.values())
        placeholders = ','.join(['?'] * len(cols))
        c.execute(f"INSERT OR REPLACE INTO {table} ({','.join(cols)}) VALUES ({placeholders})", vals)
        conn.commit()
        conn.close()
        return True
    except Exception as e:
        logger.error(f"SQLite保存失败: {e}")
        return False

def query_from_sqlite(table: str, conditions: dict = None, limit: int = 100):
    try:
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        if conditions:
            where = ' AND '.join([f"{k}=?" for k in conditions.keys()])
            vals = list(conditions.values())
            c.execute(f"SELECT * FROM {table} WHERE {where} LIMIT {limit}", vals)
        else:
            c.execute(f"SELECT * FROM {table} LIMIT {limit}")
        cols = [desc[0] for desc in c.description]
        rows = c.fetchall()
        conn.close()
        return [dict(zip(cols, row)) for row in rows]
    except Exception as e:
        logger.error(f"SQLite查询失败: {e}")
        return []

def load_from_sqlite(table: str, key_field: str = "id") -> dict:
    """从SQLite加载数据到内存字典"""
    try:
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        c.execute(f"SELECT * FROM {table}")
        cols = [desc[0] for desc in c.description]
        rows = c.fetchall()
        conn.close()
        result = {}
        for row in rows:
            item = dict(zip(cols, row))
            result[item[key_field]] = item
        return result
    except Exception as e:
        logger.error(f"SQLite加载失败: {e}")
        return {}

# 初始化数据库
init_sqlite()

# ============== 内存数据库 ==============

users_db = {}
sessions_db = {}
orders_db = {}
enterprises_db = {}
apps_db = {}
api_keys_db = {}
cases_db = []
posts_db = []
tasks_db = []
templates_db = []
stock_cache = {}

# ============== 初始化模拟数据 ==============

DATA_DIR = Path("data/community")
DATA_DIR.mkdir(parents=True, exist_ok=True)

def _load_json_data(filename: str, default: list) -> list:
    """从文件加载数据，不存在则用默认值初始化"""
    filepath = DATA_DIR / filename
    if filepath.exists():
        try:
            return json.loads(filepath.read_text(encoding="utf-8"))
        except Exception:
            pass
    # 首次启动：写入默认数据
    filepath.write_text(json.dumps(default, ensure_ascii=False, indent=2), encoding="utf-8")
    return default

def _save_json_data(filename: str, data: list):
    """持久化数据到文件"""
    filepath = DATA_DIR / filename
    filepath.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")

def init_mock_data():
    global cases_db, posts_db, tasks_db, templates_db

    DEFAULT_CASES = [
        {"id": 1, "category": "金融", "title": "智能风控决策系统", "company": "某国有银行", "logo": "🏦",
         "summary": "基于Edos AI构建的智能风控系统", "metrics": [{"label": "准确率", "value": "99.2%"}], "detail": "详情..."},
        {"id": 2, "category": "法律", "title": "合同审查智能助手", "company": "某知名律所", "logo": "⚖️",
         "summary": "AI驱动的合同条款风险审查", "metrics": [{"label": "效率提升", "value": "70%"}], "detail": "详情..."},
        {"id": 3, "category": "医疗", "title": "辅助诊断决策支持", "company": "某三甲医院", "logo": "🏥",
         "summary": "AI辅助诊断与治疗方案推荐", "metrics": [{"label": "准确率", "value": "97.5%"}], "detail": "详情..."},
        {"id": 4, "category": "教育", "title": "智能教学辅助系统", "company": "某在线教育平台", "logo": "📚",
         "summary": "个性化学习路径规划", "metrics": [{"label": "效率提升", "value": "40%"}], "detail": "详情..."},
        {"id": 5, "category": "制造", "title": "智能制造质量预测", "company": "某汽车零部件集团", "logo": "🏭",
         "summary": "生产线质量预测与缺陷检测", "metrics": [{"label": "检出率", "value": "99.7%"}], "detail": "详情..."},
        {"id": 6, "category": "物流", "title": "智慧物流调度优化", "company": "某头部物流企业", "logo": "🚚",
         "summary": "全链路物流调度与路径优化", "metrics": [{"label": "效率提升", "value": "35%"}], "detail": "详情..."},
        {"id": 7, "category": "政务", "title": "政务服务智能导办", "company": "某市级政务中心", "logo": "🏛️",
         "summary": "AI政务服务咨询与流程引导", "metrics": [{"label": "响应时间", "value": "<3秒"}], "detail": "详情..."},
        {"id": 8, "category": "电商", "title": "智能客服与销售助手", "company": "某电商平台", "logo": "🛒",
         "summary": "全渠道智能客服与个性化推荐", "metrics": [{"label": "转化率", "value": "+28%"}], "detail": "详情..."},
    ]

    DEFAULT_POSTS = [
        {"id": 1, "author": "AI研究员小李", "avatar": "👨‍🔬", "title": "深入理解Edos AI的八层记忆架构",
         "excerpt": "深入剖析八层全域图示记忆架构...", "tags": ["架构", "记忆系统"], "likes": 128, "comments": 32, "date": "2026-05-28"},
        {"id": 2, "author": "前端开发者王工", "avatar": "👨‍💻", "title": "Edos AI SDK快速入门指南",
         "excerpt": "5分钟快速接入您的项目...", "tags": ["SDK", "入门"], "likes": 89, "comments": 15, "date": "2026-05-25"},
        {"id": 3, "author": "架构师陈总", "avatar": "🏗️", "title": "企业级私有化部署最佳实践",
         "excerpt": "分享企业环境部署经验...", "tags": ["部署", "企业"], "likes": 256, "comments": 48, "date": "2026-05-20"},
        {"id": 4, "author": "算法工程师张工", "avatar": "🧠", "title": "自定义推理图谱节点类型",
         "excerpt": "扩展推理图谱功能...", "tags": ["推理", "图谱"], "likes": 67, "comments": 23, "date": "2026-05-18"},
        {"id": 5, "author": "全栈开发者刘工", "avatar": "🎯", "title": "构建智能体工作流的最佳实践",
         "excerpt": "利用工作流引擎自动化业务流程...", "tags": ["工作流", "自动化"], "likes": 145, "comments": 28, "date": "2026-05-15"},
    ]

    DEFAULT_TASKS = [
        {"id": 1, "title": "推理图谱可视化体验测试", "description": "体验全新的推理图谱可视化功能",
         "reward": "500积分", "status": "进行中", "participants": 128, "deadline": "2026-06-30", "difficulty": "简单"},
        {"id": 2, "title": "移动端适配测试", "description": "测试响应式适配效果",
         "reward": "300积分", "status": "进行中", "participants": 89, "deadline": "2026-06-25", "difficulty": "中等"},
        {"id": 3, "title": "API性能压测", "description": "使用JMeter进行性能测试",
         "reward": "1000积分", "status": "进行中", "participants": 45, "deadline": "2026-07-15", "difficulty": "困难"},
        {"id": 4, "title": "文档翻译贡献", "description": "将英文API文档翻译成中文",
         "reward": "800积分", "status": "进行中", "participants": 23, "deadline": "2026-07-30", "difficulty": "中等"},
        {"id": 5, "title": "安全漏洞赏金计划", "description": "发现安全漏洞并报告",
         "reward": "最高5000积分", "status": "长期", "participants": 156, "deadline": "长期有效", "difficulty": "困难"},
    ]

    DEFAULT_TEMPLATES = [
        {"id": 1, "name": "ROI分析助手", "category": "business", "icon": "📊", "description": "一键分析营销活动投资回报率", "installs": 3256, "rating": 4.9},
        {"id": 2, "name": "合同审查专家", "category": "finance", "icon": "⚖️", "description": "智能识别合同风险条款", "installs": 1892, "rating": 4.8},
        {"id": 3, "name": "代码生成器", "category": "development", "icon": "💻", "description": "根据自然语言描述生成代码", "installs": 5623, "rating": 4.7},
        {"id": 4, "name": "数据分析工作台", "category": "data", "icon": "📈", "description": "自动化数据分析流程", "installs": 2156, "rating": 4.6},
        {"id": 5, "name": "智能客服机器人", "category": "communication", "icon": "🤖", "description": "一键创建智能客服机器人", "installs": 4521, "rating": 4.8},
        {"id": 6, "name": "日程规划师", "category": "productivity", "icon": "📅", "description": "智能日程安排与时间管理", "installs": 3891, "rating": 4.7},
        {"id": 7, "name": "思维导图生成器", "category": "creativity", "icon": "🌳", "description": "根据文本自动生成思维导图", "installs": 2456, "rating": 4.8},
        {"id": 8, "name": "舆情分析工具", "category": "marketing", "icon": "📢", "description": "实时监测和分析网络舆情", "installs": 1876, "rating": 4.6},
    ]

    # v3.3: 数据从文件加载，重启后保持修改
    cases_db = _load_json_data("cases.json", DEFAULT_CASES)
    posts_db = _load_json_data("posts.json", DEFAULT_POSTS)
    tasks_db = _load_json_data("tasks.json", DEFAULT_TASKS)
    templates_db = _load_json_data("templates.json", DEFAULT_TEMPLATES)

init_mock_data()

# ============== 工具函数 ==============

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password):
    return pwd_context.hash(password)

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=1440)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def generate_api_key():
    return "sk-" + hashlib.sha256(str(uuid.uuid4()).encode()).hexdigest()[:32]

# ============== AI 聊天服务 ==============

class AIChatService:
    def __init__(self):
        api_keys_str = os.getenv('DEEPSEEK_API_KEYS', '')
        self.api_keys = [k.strip() for k in api_keys_str.split(',') if k.strip()]
        self.current_key_index = 0
        self.api_url = os.getenv('DEEPSEEK_API_URL', 'https://api.deepseek.com/v1/chat/completions')
        self.default_model = os.getenv('DEFAULT_MODEL', 'deepseek-chat')
        self.max_tokens = int(os.getenv('MAX_TOKENS', 4096))
        self.temperature = float(os.getenv('TEMPERATURE', 0.7))

    def _get_api_key(self):
        if not self.api_keys:
            return ""
        key = self.api_keys[self.current_key_index]
        self.current_key_index = (self.current_key_index + 1) % len(self.api_keys)
        return key

    def _build_prompt(self, message, history):
        system_prompt = {
            "role": "system",
            "content": """你是 Edos AI - 一个硅基智能生命体系统。拥有八层记忆架构、推理图谱、自博弈进化能力。请专业友好地回答用户问题。""",
        }
        messages = [system_prompt]
        for h in history[-20:]:
            messages.append({"role": h.get("role", "user"), "content": h.get("content", "")})
        messages.append({"role": "user", "content": message})
        return messages

    async def chat(self, message, history=None, temperature=None):
        import httpx
        api_key = self._get_api_key()
        if not api_key:
            return {"answer": "AI服务尚未配置API密钥", "success": False}

        try:
            messages = self._build_prompt(message, history or [])
            async with httpx.AsyncClient(timeout=60.0) as client:
                response = await client.post(
                    self.api_url,
                    headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
                    json={
                        "model": self.default_model,
                        "messages": messages,
                        "max_tokens": self.max_tokens,
                        "temperature": temperature if temperature is not None else self.temperature,
                        "stream": False
                    }
                )
                response.raise_for_status()
                data = response.json()
                if data.get("choices"):
                    answer = data["choices"][0]["message"]["content"]
                    return {
                        "answer": answer, "model": self.default_model,
                        "usage": data.get("usage"), "success": True,
                        "layers_used": ["L1工作记忆", "L3语义记忆", "L4策略记忆"],
                        "reasoning_nodes": ["语义解析", "策略检索", "置信度传播"], "confidence": 0.92
                    }
                return {"answer": "AI响应为空", "success": False}
        except Exception as e:
            logger.error(f"AI chat error: {str(e)}")
            return {"answer": f"AI服务调用失败: {str(e)}", "success": False}

    async def chat_stream(self, message, history=None):
        import httpx
        api_key = self._get_api_key()
        if not api_key:
            for char in "AI服务尚未配置API密钥":
                yield {"token": char, "done": False}
            yield {"token": "", "done": True}
            return

        try:
            messages = self._build_prompt(message, history or [])
            async with httpx.AsyncClient(timeout=60.0) as client:
                async with client.stream(
                    "POST", self.api_url,
                    headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
                    json={
                        "model": self.default_model, "messages": messages,
                        "max_tokens": self.max_tokens, "temperature": self.temperature, "stream": True
                    }
                ) as response:
                    async for line in response.aiter_lines():
                        if line.startswith("data: "):
                            data_str = line[6:]
                            if data_str == "[DONE]":
                                break
                            try:
                                data = json.loads(data_str)
                                if data.get("choices"):
                                    delta = data["choices"][0].get("delta", {})
                                    content = delta.get("content", "")
                                    if content:
                                        yield {"token": content, "done": False}
                            except:
                                continue
                    yield {"token": "", "done": True}
        except Exception as e:
            for char in f"AI服务调用失败: {str(e)}":
                yield {"token": char, "done": False}
            yield {"token": "", "done": True}

    async def chat_ernie(self, message, model="ernie-4.0-turbo", temperature=0.7):
        """百度文心ERNIE API调用"""
        import httpx
        api_key = os.getenv('BAIDU_API_KEY', '')
        api_url = os.getenv('BAIDU_API_URL', 'https://qianfan.baidubce.com/v2')

        if not api_key or api_key == 'your_baidu_api_key':
            return {"answer": "百度文心API密钥未配置，请在.env文件中设置BAIDU_API_KEY", "success": False, "provider": "ernie"}

        try:
            # 文心API需要使用access_token，这里简化为API Key直传
            # 实际生产环境需要通过OAuth获取access_token
            messages = self._build_prompt(message, [])
            async with httpx.AsyncClient(timeout=60.0) as client:
                response = await client.post(
                    f"{api_url}/chat/completions",
                    headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
                    json={
                        "model": model,
                        "messages": messages,
                        "max_tokens": self.max_tokens,
                        "temperature": temperature,
                        "stream": False
                    }
                )
                response.raise_for_status()
                data = response.json()
                if data.get("choices"):
                    answer = data["choices"][0]["message"]["content"]
                    return {
                        "answer": answer,
                        "model": model,
                        "provider": "ernie",
                        "usage": data.get("usage"),
                        "success": True
                    }
                return {"answer": "文心响应为空", "success": False, "provider": "ernie"}
        except Exception as e:
            logger.error(f"ERNIE chat error: {str(e)}")
            return {"answer": f"文心API调用失败: {str(e)}", "success": False, "provider": "ernie"}

    async def chat_qwen(self, message, model="qwen-max", temperature=0.7):
        """阿里云通义千问API调用"""
        import httpx
        api_key = os.getenv('DASHSCOPE_API_KEY', '')
        api_url = os.getenv('DASHSCOPE_API_URL', 'https://dashscope.aliyuncs.com/compatible-mode/v1')

        if not api_key or api_key == 'your_dashscope_api_key':
            return {"answer": "通义千问API密钥未配置，请在.env文件中设置DASHSCOPE_API_KEY", "success": False, "provider": "qwen"}

        try:
            messages = self._build_prompt(message, [])
            async with httpx.AsyncClient(timeout=60.0) as client:
                response = await client.post(
                    f"{api_url}/chat/completions",
                    headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
                    json={
                        "model": model,
                        "messages": messages,
                        "max_tokens": self.max_tokens,
                        "temperature": temperature,
                        "stream": False
                    }
                )
                response.raise_for_status()
                data = response.json()
                if data.get("choices"):
                    answer = data["choices"][0]["message"]["content"]
                    return {
                        "answer": answer,
                        "model": model,
                        "provider": "qwen",
                        "usage": data.get("usage"),
                        "success": True
                    }
                return {"answer": "通义千问响应为空", "success": False, "provider": "qwen"}
        except Exception as e:
            logger.error(f"Qwen chat error: {str(e)}")
            return {"answer": f"通义千问API调用失败: {str(e)}", "success": False, "provider": "qwen"}

    async def chat_zhipu(self, message, model="glm-4-flash", temperature=0.7):
        """智谱GLM-4 API调用"""
        import httpx
        api_key = os.getenv('ZHIPU_API_KEY', '')
        api_url = os.getenv('ZHIPU_API_URL', 'https://open.bigmodel.cn/api/paas/v4')

        if not api_key or api_key == 'your_zhipu_api_key':
            return {"answer": "智谱GLM-4 API密钥未配置，请在.env文件中设置ZHIPU_API_KEY", "success": False, "provider": "zhipu"}

        try:
            messages = self._build_prompt(message, [])
            async with httpx.AsyncClient(timeout=60.0) as client:
                response = await client.post(
                    f"{api_url}/chat/completions",
                    headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
                    json={
                        "model": model,
                        "messages": messages,
                        "max_tokens": self.max_tokens,
                        "temperature": temperature,
                        "stream": False
                    }
                )
                response.raise_for_status()
                data = response.json()
                if data.get("choices"):
                    answer = data["choices"][0]["message"]["content"]
                    return {
                        "answer": answer,
                        "model": model,
                        "provider": "zhipu",
                        "usage": data.get("usage"),
                        "success": True
                    }
                return {"answer": "智谱GLM-4响应为空", "success": False, "provider": "zhipu"}
        except Exception as e:
            logger.error(f"Zhipu chat error: {str(e)}")
            return {"answer": f"智谱GLM-4 API调用失败: {str(e)}", "success": False, "provider": "zhipu"}

    async def chat_multi(self, message, providers=["deepseek", "ernie", "qwen", "zhipu"]):
        """多模型并行调用，对比结果"""
        results = {}

        if "deepseek" in providers:
            try:
                ds_result = await self.chat(message)
                results["deepseek"] = ds_result
            except Exception as e:
                results["deepseek"] = {"answer": None, "success": False, "error": str(e)}

        if "ernie" in providers:
            try:
                ernie_result = await self.chat_ernie(message)
                results["ernie"] = ernie_result
            except Exception as e:
                results["ernie"] = {"answer": None, "success": False, "error": str(e)}

        if "qwen" in providers:
            try:
                qwen_result = await self.chat_qwen(message)
                results["qwen"] = qwen_result
            except Exception as e:
                results["qwen"] = {"answer": None, "success": False, "error": str(e)}

        if "zhipu" in providers:
            try:
                zhipu_result = await self.chat_zhipu(message)
                results["zhipu"] = zhipu_result
            except Exception as e:
                results["zhipu"] = {"answer": None, "success": False, "error": str(e)}

        return results

ai_chat_service = AIChatService()

# ============== Pydantic 模型 ==============

class LoginRequest(BaseModel):
    username: str
    password: str

class RegisterRequest(BaseModel):
    username: str
    email: EmailStr
    password: str
    phone: Optional[str] = None

class PhoneVerifyRequest(BaseModel):
    phone: str

class StockSearchRequest(BaseModel):
    keyword: str

class OrderCreateRequest(BaseModel):
    product_id: str
    amount: float
    payment_method: str = "wechat"

class EnterpriseRegisterRequest(BaseModel):
    name: str
    contact_name: str
    contact_email: EmailStr
    contact_phone: str
    license_type: str = "standard"

class AppCreateRequest(BaseModel):
    name: str
    description: str
    redirect_uri: Optional[str] = None

class ChatRequest(BaseModel):
    message: str
    history: Optional[List[Dict[str, str]]] = None
    session_id: Optional[str] = None

# ============== FastAPI 应用 ==============

app = FastAPI(title="Edos AI Backend", version="2.0.0", docs_url="/docs")

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",
        "http://localhost:5173",
        "http://127.0.0.1:3000",
        "http://127.0.0.1:5173",
        "http://localhost:8080",
        "http://127.0.0.1:8080",
        "http://localhost:8000",
        "http://127.0.0.1:8000",
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allow_headers=["Content-Type", "Authorization", "X-CSRF-Token", "X-Requested-With"],
)

# ============== 认证路由 ==============

@app.post("/api/auth/login")
async def login(request: LoginRequest):
    user = users_db.get(request.username)
    if not user or not verify_password(request.password, user["hashed_password"]):
        raise HTTPException(status_code=401, detail="用户名或密码错误")

    access_token = create_access_token(data={"sub": user["username"], "role": user.get("role", "user")})
    session_id = str(uuid.uuid4())
    sessions_db[session_id] = {"user_id": user["username"], "created_at": datetime.now().timestamp()}

    return {
        "access_token": access_token,
        "token_type": "bearer",
        "session_id": session_id,
        "user": {"username": user["username"], "email": user["email"], "role": user.get("role", "user")}
    }

@app.post("/api/auth/logout")
async def logout(session_id: str = ""):
    """登出 - 使服务端session失效"""
    if session_id and session_id in sessions_db:
        del sessions_db[session_id]
    return {"message": "已登出", "code": 0}

@app.post("/api/auth/register")
async def register(request: RegisterRequest):
    if request.username in users_db:
        raise HTTPException(status_code=400, detail="用户名已存在")

    user = {
        "username": request.username,
        "email": request.email,
        "phone": request.phone,
        "hashed_password": get_password_hash(request.password),
        "role": "user",
        "created_at": datetime.now().timestamp(),
        "is_active": True
    }
    users_db[request.username] = user

    access_token = create_access_token(data={"sub": request.username})
    return {"access_token": access_token, "token_type": "bearer", "message": "注册成功"}

@app.post("/api/auth/phone-verify")
async def phone_verify(request: PhoneVerifyRequest):
    code = str(random.randint(1000, 9999))
    return {"code": code, "message": "验证码已发送"}

@app.post("/api/auth/reset-password")
async def reset_password(request: dict):
    user = users_db.get(request.get("username"))
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")

    users_db[user["username"]]["hashed_password"] = get_password_hash(request.get("new_password"))
    return {"message": "密码重置成功"}

# ============== AI 聊天路由 ==============

@app.post("/api/chat-proxy")
async def chat_proxy(request: ChatRequest):
    result = await ai_chat_service.chat(message=request.message, history=request.history)
    return result

@app.post("/api/chat-proxy/stream")
async def chat_proxy_stream(request: ChatRequest):
    async def generate():
        async for chunk in ai_chat_service.chat_stream(message=request.message, history=request.history):
            if chunk.get("done"):
                yield "data: [DONE]\n\n"
            else:
                yield f"data: {chunk.get('token', '')}\n\n"
    return StreamingResponse(generate(), media_type="text/event-stream")

# ============== 百度文心ERNIE API路由 ==============

class ErnieChatRequest(BaseModel):
    message: str
    model: str = Field(default="ernie-4.0-turbo", description="文心模型: ernie-4.0-turbo/ernie-3.5/ernie-speed")
    temperature: float = Field(default=0.7, description="温度参数 0-1")
    history: Optional[List[Dict[str, str]]] = None

class MultiModelRequest(BaseModel):
    message: str
    providers: List[str] = Field(default=["deepseek", "ernie"], description="调用的模型提供商")

@app.get("/api/ernie/models")
async def get_ernie_models():
    """获取支持的文心模型列表"""
    return {
        "models": [
            {"id": "ernie-4.0-turbo", "name": "文心一言4.0 Turbo", "max_tokens": 8192, "description": "最新最强模型"},
            {"id": "ernie-4.0", "name": "文心一言4.0", "max_tokens": 8192, "description": "旗舰模型"},
            {"id": "ernie-3.5", "name": "文心一言3.5", "max_tokens": 4096, "description": "主力模型"},
            {"id": "ernie-speed", "name": "文心一言 Speed", "max_tokens": 4096, "description": "极速响应"}
        ],
        "api_status": "configured" if os.getenv('BAIDU_API_KEY') and os.getenv('BAIDU_API_KEY') != 'your_baidu_api_key' else "not_configured"
    }

@app.post("/api/ernie/chat")
async def ernie_chat(request: ErnieChatRequest):
    """调用百度文心ERNIE API进行对话"""
    result = await ai_chat_service.chat_ernie(
        message=request.message,
        model=request.model,
        temperature=request.temperature
    )
    return result

@app.post("/api/ernie/multi")
async def multi_model_chat(request: MultiModelRequest):
    """多模型并行调用，支持DeepSeek/文心/通义千问/智谱GLM-4"""
    results = await ai_chat_service.chat_multi(
        message=request.message,
        providers=request.providers
    )
    return {
        "message": request.message,
        "providers": request.providers,
        "results": results,
        "total": len(results),
        "successful": len([r for r in results.values() if r.get("success", False)])
    }

# ============== 阿里云通义千问API路由 ==============

class QwenChatRequest(BaseModel):
    message: str
    model: str = Field(default="qwen-max", description="通义千问模型: qwen-max/qwen-plus/qwen-turbo/qwen-vl-max")
    temperature: float = Field(default=0.7, description="温度参数 0-1")
    history: Optional[List[Dict[str, str]]] = None

@app.get("/api/qwen/models")
async def get_qwen_models():
    """获取支持的通义千问模型列表"""
    return {
        "models": [
            {"id": "qwen-max", "name": "通义千问 Max", "max_tokens": 8192, "description": "旗舰模型，支持图文"},
            {"id": "qwen-plus", "name": "通义千问 Plus", "max_tokens": 4096, "description": "高性能模型"},
            {"id": "qwen-turbo", "name": "通义千问 Turbo", "max_tokens": 4096, "description": "极速响应"},
            {"id": "qwen-vl-max", "name": "通义千问 VL Max", "max_tokens": 8192, "description": "视觉模型"}
        ],
        "api_status": "configured" if os.getenv('DASHSCOPE_API_KEY') and os.getenv('DASHSCOPE_API_KEY') != 'your_dashscope_api_key' else "not_configured"
    }

@app.post("/api/qwen/chat")
async def qwen_chat(request: QwenChatRequest):
    """调用阿里云通义千问API进行对话"""
    result = await ai_chat_service.chat_qwen(
        message=request.message,
        model=request.model,
        temperature=request.temperature
    )
    return result

# ============== 智谱GLM-4 API路由 ==============

class ZhipuChatRequest(BaseModel):
    message: str
    model: str = Field(default="glm-4-flash", description="智谱模型: glm-4-plus/glm-4-flash/glm-4v-plus")
    temperature: float = Field(default=0.7, description="温度参数 0-1")
    history: Optional[List[Dict[str, str]]] = None

@app.get("/api/zhipu/models")
async def get_zhipu_models():
    """获取支持的智谱GLM模型列表"""
    return {
        "models": [
            {"id": "glm-4-plus", "name": "GLM-4 Plus", "max_tokens": 8192, "description": "旗舰模型"},
            {"id": "glm-4-flash", "name": "GLM-4 Flash", "max_tokens": 4096, "description": "高速模型"},
            {"id": "glm-4v-plus", "name": "GLM-4V Plus", "max_tokens": 8192, "description": "视觉模型"}
        ],
        "api_status": "configured" if os.getenv('ZHIPU_API_KEY') and os.getenv('ZHIPU_API_KEY') != 'your_zhipu_api_key' else "not_configured"
    }

@app.post("/api/zhipu/chat")
async def zhipu_chat(request: ZhipuChatRequest):
    """调用智谱GLM-4 API进行对话"""
    result = await ai_chat_service.chat_zhipu(
        message=request.message,
        model=request.model,
        temperature=request.temperature
    )
    return result

# ============== 多模型智能路由 ==============

class SmartRouteRequest(BaseModel):
    message: str
    strategy: str = Field(default="auto", description="路由策略: auto/fallback/parallel")
    priority: List[str] = Field(default=["deepseek", "qwen", "zhipu", "ernie"], description="模型优先级")
    temperature: float = Field(default=0.7, description="温度参数")

@app.post("/api/smart-route")
async def smart_route(request: SmartRouteRequest):
    """智能路由：根据策略自动选择最优模型，支持多API轮换调用"""

    if request.strategy == "parallel":
        results = await ai_chat_service.chat_multi(message=request.message, providers=request.priority)
        successful = [r for r in results.values() if r.get("success", False)]
        if successful:
            best_result = max(successful, key=lambda x: len(x.get("answer", "")))
            return {
                "strategy": "parallel",
                "selected_provider": best_result.get("provider"),
                "result": best_result,
                "all_results": results,
                "total_providers": len(results),
                "successful_count": len(successful),
                "message": request.message
            }
        return {
            "strategy": "parallel",
            "error": "所有模型调用失败",
            "all_results": results
        }

    elif request.strategy == "fallback":
        for provider in request.priority:
            try:
                if provider == "deepseek":
                    result = await ai_chat_service.chat(request.message)
                elif provider == "ernie":
                    result = await ai_chat_service.chat_ernie(request.message)
                elif provider == "qwen":
                    result = await ai_chat_service.chat_qwen(request.message)
                elif provider == "zhipu":
                    result = await ai_chat_service.chat_zhipu(request.message)
                else:
                    continue

                if result.get("success", False):
                    return {
                        "strategy": "fallback",
                        "selected_provider": provider,
                        "result": result,
                        "message": request.message
                    }
            except:
                continue

        return {"strategy": "fallback", "error": "所有模型调用失败"}

    else:
        result = await ai_chat_service.chat(request.message)
        if result.get("success", False):
            return {
                "strategy": "auto",
                "selected_provider": "deepseek",
                "result": result,
                "message": request.message
            }

        for provider in ["qwen", "zhipu", "ernie"]:
            try:
                if provider == "qwen":
                    fallback = await ai_chat_service.chat_qwen(request.message)
                elif provider == "zhipu":
                    fallback = await ai_chat_service.chat_zhipu(request.message)
                elif provider == "ernie":
                    fallback = await ai_chat_service.chat_ernie(request.message)

                if fallback.get("success", False):
                    return {
                        "strategy": "auto",
                        "selected_provider": provider,
                        "result": fallback,
                        "message": request.message
                    }
            except:
                continue

        return {"strategy": "auto", "error": "所有模型调用失败"}

@app.get("/api/model-providers")
async def get_model_providers():
    """获取所有已配置的模型提供商状态"""
    return {
        "providers": [
            {
                "id": "deepseek",
                "name": "DeepSeek",
                "api_key_count": len(ai_chat_service.api_keys),
                "status": "configured" if ai_chat_service.api_keys else "not_configured",
                "models": ["deepseek-chat", "deepseek-chat-v3", "deepseek-coder"],
                "description": "主模型，高性能推理"
            },
            {
                "id": "ernie",
                "name": "百度文心",
                "status": "configured" if os.getenv('BAIDU_API_KEY') and os.getenv('BAIDU_API_KEY') != 'your_baidu_api_key' else "not_configured",
                "models": ["ernie-4.0-turbo", "ernie-4.0", "ernie-3.5", "ernie-speed"],
                "description": "中文理解、知识问答"
            },
            {
                "id": "qwen",
                "name": "通义千问",
                "status": "configured" if os.getenv('DASHSCOPE_API_KEY') and os.getenv('DASHSCOPE_API_KEY') != 'your_dashscope_api_key' else "not_configured",
                "models": ["qwen-max", "qwen-plus", "qwen-turbo", "qwen-vl-max"],
                "description": "中文理解、文案创作"
            },
            {
                "id": "zhipu",
                "name": "智谱GLM-4",
                "status": "configured" if os.getenv('ZHIPU_API_KEY') and os.getenv('ZHIPU_API_KEY') != 'your_zhipu_api_key' else "not_configured",
                "models": ["glm-4-plus", "glm-4-flash", "glm-4v-plus"],
                "description": "逻辑推理、数据分析"
            }
        ],
        "configured_count": sum(1 for p in [
            bool(ai_chat_service.api_keys),
            os.getenv('BAIDU_API_KEY') and os.getenv('BAIDU_API_KEY') != 'your_baidu_api_key',
            os.getenv('DASHSCOPE_API_KEY') and os.getenv('DASHSCOPE_API_KEY') != 'your_dashscope_api_key',
            os.getenv('ZHIPU_API_KEY') and os.getenv('ZHIPU_API_KEY') != 'your_zhipu_api_key'
        ] if p),
        "total_count": 4
    }

# ============== 股票市场路由 ==============

@app.get("/api/stock/index")
async def get_stock_index():
    return {
        "data": [
            {"code": "000001", "name": "上证指数", "price": 3380.52, "change": 0.87, "changePercent": "+0.03%"},
            {"code": "399001", "name": "深证成指", "price": 10876.33, "change": -1.23, "changePercent": "-0.01%"},
            {"code": "399006", "name": "创业板指", "price": 2156.78, "change": 2.15, "changePercent": "+0.10%"},
            {"code": "000688", "name": "科创50", "price": 978.45, "change": 5.32, "changePercent": "+0.55%"},
            {"code": "HSI", "name": "恒生指数", "price": 19280.45, "change": -45.60, "changePercent": "-0.24%"},
            {"code": "IXIC", "name": "纳斯达克", "price": 17856.23, "change": 128.45, "changePercent": "+0.72%"},
        ],
        "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }

@app.get("/api/stock/sectors")
async def get_stock_sectors():
    return {
        "data": [
            {"name": "半导体", "up_count": 45, "down_count": 12, "avg_change": 3.25},
            {"name": "人工智能", "up_count": 38, "down_count": 18, "avg_change": 2.15},
            {"name": "新能源", "up_count": 28, "down_count": 25, "avg_change": 0.85},
            {"name": "生物医药", "up_count": 22, "down_count": 30, "avg_change": -0.52},
            {"name": "金融", "up_count": 18, "down_count": 35, "avg_change": -1.25},
        ]
    }

@app.get("/api/stock/breadth")
async def get_market_breadth():
    return {
        "up_count": 1856,
        "down_count": 2143,
        "flat_count": 128,
        "total_count": 4127,
        "market_sentiment": "neutral"
    }

@app.get("/api/stock/news")
async def get_stock_news():
    return {
        "data": [
            {"id": 1, "title": "AI芯片需求持续增长，半导体板块走强", "source": "财经头条", "time": "10分钟前"},
            {"id": 2, "title": "新能源汽车销量创新高，产业链迎机遇", "source": "证券时报", "time": "25分钟前"},
            {"id": 3, "title": "央行宣布降准0.5个百分点", "source": "新华社", "time": "1小时前"},
            {"id": 4, "title": "科技股集体上涨，纳斯达克创新高", "source": "华尔街日报", "time": "2小时前"},
        ]
    }

@app.get("/api/stock/kline/{code}")
async def get_stock_kline(code: str, period: str = "day"):
    data = []
    base_price = random.uniform(10, 100)
    for i in range(30):
        date = (datetime.now() - timedelta(days=29-i)).strftime("%Y-%m-%d")
        open_price = base_price + random.uniform(-2, 2)
        close_price = open_price + random.uniform(-3, 3)
        high_price = max(open_price, close_price) + random.uniform(0, 1)
        low_price = min(open_price, close_price) - random.uniform(0, 1)
        data.append({
            "date": date, "open": round(open_price, 2), "close": round(close_price, 2),
            "high": round(high_price, 2), "low": round(low_price, 2), "volume": random.randint(10000, 500000)
        })
        base_price = close_price

    return {"code": code, "period": period, "data": data}

@app.post("/api/stock/search")
async def search_stock(request: StockSearchRequest):
    return {
        "data": [
            {"code": "600519", "name": "贵州茅台", "price": 1685.00, "change": 2.50},
            {"code": "000858", "name": "五粮液", "price": 158.50, "change": -1.20},
            {"code": "000001", "name": "平安银行", "price": 12.85, "change": 0.15},
        ]
    }

# ============== 企业控制台路由 ==============

@app.post("/api/enterprise/register")
async def enterprise_register(request: EnterpriseRegisterRequest):
    enterprise_id = str(uuid.uuid4())
    enterprise = {
        "id": enterprise_id,
        "name": request.name,
        "contact_name": request.contact_name,
        "contact_email": request.contact_email,
        "contact_phone": request.contact_phone,
        "license_type": request.license_type,
        "license_status": "active",
        "created_at": datetime.now().timestamp(),
        "team_members": []
    }
    enterprises_db[enterprise_id] = enterprise
    return {"enterprise_id": enterprise_id, "message": "企业注册成功"}

@app.get("/api/enterprise/profile/{enterprise_id}")
async def get_enterprise_profile(enterprise_id: str):
    enterprise = enterprises_db.get(enterprise_id)
    if not enterprise:
        raise HTTPException(status_code=404, detail="企业不存在")
    return enterprise

@app.get("/api/enterprise/license/{enterprise_id}")
async def get_enterprise_license(enterprise_id: str):
    enterprise = enterprises_db.get(enterprise_id)
    if not enterprise:
        raise HTTPException(status_code=404, detail="企业不存在")
    return {
        "enterprise_id": enterprise_id,
        "license_type": enterprise.get("license_type", "standard"),
        "status": enterprise.get("license_status", "active"),
        "quota": {"api_calls": 100000, "remaining": 85234},
        "expire_date": (datetime.now() + timedelta(days=365)).strftime("%Y-%m-%d")
    }

@app.get("/api/enterprise/team/{enterprise_id}")
async def get_enterprise_team(enterprise_id: str):
    enterprise = enterprises_db.get(enterprise_id)
    if not enterprise:
        raise HTTPException(status_code=404, detail="企业不存在")
    return {
        "enterprise_id": enterprise_id,
        "members": [
            {"id": 1, "name": "张三", "role": "管理员", "email": "zhangsan@example.com"},
            {"id": 2, "name": "李四", "role": "开发者", "email": "lisi@example.com"},
            {"id": 3, "name": "王五", "role": "使用者", "email": "wangwu@example.com"},
        ]
    }

@app.get("/api/enterprise/usage/{enterprise_id}")
async def get_enterprise_usage(enterprise_id: str):
    return {
        "enterprise_id": enterprise_id,
        "usage": {
            "today_api_calls": 1256,
            "week_api_calls": 8532,
            "month_api_calls": 35218,
            "top_models": ["deepseek-chat", "deepseek-coder"]
        }
    }

# ============== 开发者门户路由 ==============

@app.post("/api/developer/apps")
async def create_app(request: AppCreateRequest):
    app_id = str(uuid.uuid4())
    app = {
        "id": app_id,
        "name": request.name,
        "description": request.description,
        "redirect_uri": request.redirect_uri,
        "created_at": datetime.now().timestamp(),
        "status": "active"
    }
    apps_db[app_id] = app
    return {"app_id": app_id, "message": "应用创建成功"}

@app.get("/api/developer/apps")
async def get_apps():
    return {"data": list(apps_db.values())}

@app.post("/api/developer/keys")
async def create_api_key(request: dict):
    app_id = request.get("app_id")
    if not app_id or app_id not in apps_db:
        raise HTTPException(status_code=400, detail="应用不存在")

    api_key = generate_api_key()
    api_keys_db[api_key] = {
        "app_id": app_id,
        "key": api_key,
        "created_at": datetime.now().timestamp(),
        "status": "active"
    }
    return {"api_key": api_key, "message": "API Key 创建成功"}

@app.get("/api/developer/keys")
async def get_api_keys(request: dict):
    app_id = request.get("app_id")
    keys = [k for k in api_keys_db.values() if k["app_id"] == app_id] if app_id else list(api_keys_db.values())
    return {"data": keys}

@app.delete("/api/developer/keys/{api_key}")
async def revoke_api_key(api_key: str):
    if api_key in api_keys_db:
        api_keys_db[api_key]["status"] = "revoked"
        return {"message": "API Key 已撤销"}
    raise HTTPException(status_code=404, detail="API Key 不存在")

@app.get("/api/developer/docs")
async def get_docs():
    return {
        "endpoints": [
            {"path": "/api/chat-proxy", "method": "POST", "description": "AI聊天接口"},
            {"path": "/api/chat-proxy/stream", "method": "POST", "description": "流式AI聊天接口"},
            {"path": "/api/stock/index", "method": "GET", "description": "股票指数接口"},
        ],
        "versions": ["v1.0", "v2.0"]
    }

# ============== 支付路由 ==============

@app.post("/api/payments/create")
async def create_order(request: OrderCreateRequest):
    order_id = "EDOS" + str(int(time.time()))
    order = {
        "order_id": order_id,
        "product_id": request.product_id,
        "amount": request.amount,
        "payment_method": request.payment_method,
        "status": "pending",
        "created_at": datetime.now().timestamp()
    }
    orders_db[order_id] = order
    return {"order_id": order_id, "status": "pending", "message": "订单创建成功"}

@app.get("/api/payments/wechat/{order_id}")
async def wechat_pay(order_id: str):
    order = orders_db.get(order_id)
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    order["status"] = "paid"
    return {
        "order_id": order_id,
        "status": "paid",
        "wechat_pay_url": f"weixin://wxpay/bizpayurl?pr={order_id}",
        "message": "支付成功"
    }

@app.get("/api/payments/alipay/{order_id}")
async def alipay(order_id: str):
    order = orders_db.get(order_id)
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    order["status"] = "paid"
    return {
        "order_id": order_id,
        "status": "paid",
        "alipay_url": f"alipays://platformapi/startapp?appId=20000056&orderId={order_id}",
        "message": "支付成功"
    }

@app.get("/api/payments/status/{order_id}")
async def get_payment_status(order_id: str):
    order = orders_db.get(order_id)
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")
    return {"order_id": order_id, "status": order["status"]}

# ============== 管理后台路由 ==============

@app.get("/api/admin/users")
async def get_users():
    return {"data": [{"username": k, "email": v["email"], "role": v.get("role", "user")} for k, v in users_db.items()]}

@app.get("/api/admin/orders")
async def get_orders():
    return {"data": list(orders_db.values())}

@app.get("/api/admin/monitor")
async def get_monitor():
    return {
        "system": {"cpu": 45, "memory": 68, "disk": 72},
        "api": {"total_calls": 125632, "today_calls": 8532, "avg_response_time": 125},
        "users": {"total": len(users_db), "active_today": 156}
    }

@app.get("/api/admin/security")
async def get_security_logs():
    return {
        "logs": [
            {"id": 1, "type": "login", "user": "admin", "ip": "192.168.1.100", "time": "2026-06-22 10:30:00"},
            {"id": 2, "type": "api_call", "endpoint": "/api/chat-proxy", "user": "user1", "time": "2026-06-22 10:28:00"},
        ]
    }

# ============== 数据同步路由 ==============

@app.post("/api/sync/pull")
async def sync_pull(request: dict):
    last_sync = request.get("last_sync", 0)
    return {
        "last_sync": datetime.now().timestamp(),
        "data": {"type": "user_preferences", "content": {"theme": "dark", "language": "zh-CN"}}
    }

@app.post("/api/sync/push")
async def sync_push(request: dict):
    return {"message": "数据同步成功", "status": "ok"}

# ============== 内容路由 ==============

@app.get("/api/content/cases")
async def get_cases():
    return {"data": cases_db}

@app.get("/api/content/cases/{case_id}")
async def get_case(case_id: int):
    case = next((c for c in cases_db if c["id"] == case_id), None)
    if not case:
        raise HTTPException(status_code=404, detail="案例不存在")
    return case

@app.post("/api/content/cases")
async def create_case(case: dict):
    """v3.3: 动态添加案例，数据持久化"""
    global cases_db
    new_id = max((c.get("id", 0) for c in cases_db), default=0) + 1
    case["id"] = new_id
    cases_db.append(case)
    _save_json_data("cases.json", cases_db)
    return {"status": "created", "id": new_id}

@app.put("/api/content/cases/{case_id}")
async def update_case(case_id: int, case: dict):
    global cases_db
    for i, c in enumerate(cases_db):
        if c["id"] == case_id:
            case["id"] = case_id
            cases_db[i] = case
            _save_json_data("cases.json", cases_db)
            return {"status": "updated"}
    raise HTTPException(status_code=404, detail="案例不存在")

@app.delete("/api/content/cases/{case_id}")
async def delete_case(case_id: int):
    global cases_db
    cases_db = [c for c in cases_db if c["id"] != case_id]
    _save_json_data("cases.json", cases_db)
    return {"status": "deleted"}

@app.get("/api/content/posts")
async def get_posts():
    return {"data": posts_db}

@app.post("/api/content/posts")
async def create_post(post: dict):
    """v3.3: 动态添加社区帖子"""
    global posts_db
    new_id = max((p.get("id", 0) for p in posts_db), default=0) + 1
    post["id"] = new_id
    posts_db.append(post)
    _save_json_data("posts.json", posts_db)
    return {"status": "created", "id": new_id}

@app.put("/api/content/posts/{post_id}")
async def update_post(post_id: int, post: dict):
    global posts_db
    for i, p in enumerate(posts_db):
        if p["id"] == post_id:
            post["id"] = post_id
            posts_db[i] = post
            _save_json_data("posts.json", posts_db)
            return {"status": "updated"}
    raise HTTPException(status_code=404, detail="帖子不存在")

@app.delete("/api/content/posts/{post_id}")
async def delete_post(post_id: int):
    global posts_db
    posts_db = [p for p in posts_db if p["id"] != post_id]
    _save_json_data("posts.json", posts_db)
    return {"status": "deleted"}

@app.get("/api/content/tasks")
async def get_tasks():
    return {"data": tasks_db}

@app.post("/api/content/tasks")
async def create_task(task: dict):
    global tasks_db
    new_id = max((t.get("id", 0) for t in tasks_db), default=0) + 1
    task["id"] = new_id
    tasks_db.append(task)
    _save_json_data("tasks.json", tasks_db)
    return {"status": "created", "id": new_id}

@app.put("/api/content/tasks/{task_id}")
async def update_task(task_id: int, task: dict):
    global tasks_db
    for i, t in enumerate(tasks_db):
        if t["id"] == task_id:
            task["id"] = task_id
            tasks_db[i] = task
            _save_json_data("tasks.json", tasks_db)
            return {"status": "updated"}
    raise HTTPException(status_code=404, detail="任务不存在")

@app.delete("/api/content/tasks/{task_id}")
async def delete_task(task_id: int):
    global tasks_db
    tasks_db = [t for t in tasks_db if t["id"] != task_id]
    _save_json_data("tasks.json", tasks_db)
    return {"status": "deleted"}

@app.get("/api/content/templates")
async def get_templates():
    return {"data": templates_db}

@app.post("/api/content/templates")
async def create_template(template: dict):
    global templates_db
    new_id = max((t.get("id", 0) for t in templates_db), default=0) + 1
    template["id"] = new_id
    templates_db.append(template)
    _save_json_data("templates.json", templates_db)
    return {"status": "created", "id": new_id}

@app.put("/api/content/templates/{template_id}")
async def update_template(template_id: int, template: dict):
    global templates_db
    for i, t in enumerate(templates_db):
        if t["id"] == template_id:
            template["id"] = template_id
            templates_db[i] = template
            _save_json_data("templates.json", templates_db)
            return {"status": "updated"}
    raise HTTPException(status_code=404, detail="模板不存在")

@app.delete("/api/content/templates/{template_id}")
async def delete_template(template_id: int):
    global templates_db
    templates_db = [t for t in templates_db if t["id"] != template_id]
    _save_json_data("templates.json", templates_db)
    return {"status": "deleted"}

# ============== 自博弈工厂路由 ==============

# 自博弈工厂数据存储
selfplay_games_db = {}
selfplay_strategies_db = {}
selfplay_lifecycle_db = {}

class SelfPlayGameRequest(BaseModel):
    game_type: str = Field(default="debate", description="游戏类型: debate/simulation/optimization")
    topic: str = Field(..., description="博弈主题/问题", min_length=1)
    max_rounds: int = Field(default=5, description="最大回合数")
    players: List[str] = Field(default=["strategist", "critic", "mediator"], description="参与智能体")

class SelfPlayChatRequest(BaseModel):
    message: str = Field(..., description="用户消息", min_length=1)
    context: Optional[Dict[str, Any]] = Field(default=None, description="额外上下文")

@app.get("/api/selfplay/status")
async def get_selfplay_status():
    """获取自博弈工厂状态"""
    return {
        "status": "active",
        "supported_game_types": ["debate", "simulation", "optimization"],
        "agents": [
            {"id": "strategist", "name": "策略制定者", "temperature": 0.3, "role": "逻辑严谨，制定策略"},
            {"id": "critic", "name": "批判者", "temperature": 0.8, "role": "发散思维，批判分析"},
            {"id": "mediator", "name": "调解者", "temperature": 0.5, "role": "平衡公正，协调综合"}
        ],
        "api_keys_available": len(ai_chat_service.api_keys),
        "total_games": len(selfplay_games_db),
        "total_strategies": len(selfplay_strategies_db)
    }

@app.post("/api/selfplay/game")
async def create_selfplay_game(req: SelfPlayGameRequest):
    """创建并运行自博弈游戏 - 真正调用多个API进行3智能体对抗"""
    game_id = f"game_{uuid.uuid4().hex[:8]}"

    # 智能体配置：每个智能体使用不同的模型提供商和温度
    agent_configs = {
        "strategist": {
            "name": "策略制定者",
            "provider": "deepseek",
            "temperature": 0.3,
            "role_prompt": "你是一位逻辑严谨的策略制定者。请基于事实和数据，制定最优策略方案。你的回答应该条理清晰、论据充分。"
        },
        "critic": {
            "name": "批判者",
            "provider": "qwen",
            "temperature": 0.8,
            "role_prompt": "你是一位批判性思维专家。请对其他智能体的观点提出质疑和改进建议。你的回答应该犀利、有洞察力。"
        },
        "mediator": {
            "name": "调解者",
            "provider": "deepseek",
            "temperature": 0.5,
            "role_prompt": "你是一位中立公正的调解者。请综合各方观点，找出最佳平衡点。你的回答应该客观、全面。"
        }
    }

    # 初始化游戏状态
    game_state = {
        "game_id": game_id,
        "game_type": req.game_type,
        "topic": req.topic,
        "max_rounds": req.max_rounds,
        "players": req.players,
        "agent_configs": {p: agent_configs.get(p, agent_configs["strategist"]) for p in req.players},
        "current_round": 0,
        "rounds": [],
        "scores": {p: 0 for p in req.players},
        "status": "running",
        "created_at": datetime.now().isoformat(),
        "api_calls_made": 0
    }

    selfplay_games_db[game_id] = game_state

    # 真正运行博弈 - 调用AI服务
    for round_num in range(req.max_rounds):
        round_record = {
            "round_id": round_num,
            "question": f"[{req.game_type}] Round {round_num + 1}: {req.topic[:80]}",
            "answers": [],
            "best_answer": None,
            "avg_score": 0
        }

        # 构建历史上下文
        history = []
        for prev_round in game_state["rounds"]:
            for ans in prev_round["answers"]:
                agent_info = agent_configs.get(ans["agent"], {})
                history.append({"role": "user", "content": f"{agent_info.get('name', ans['agent'])}: {ans['content'][:200]}..."})

        # 每个智能体依次发言
        round_scores = {}
        for player in req.players:
            config = agent_configs.get(player, agent_configs["strategist"])

            # 构建完整prompt
            full_prompt = f"{config['role_prompt']}\n\n当前博弈主题：{req.topic}\n\n回合 {round_num + 1}，请发表你的观点："

            # 调用对应API
            try:
                if config["provider"] == "deepseek":
                    response = await ai_chat_service.chat(full_prompt, history=history, temperature=config["temperature"])
                elif config["provider"] == "qwen":
                    response = await ai_chat_service.chat_qwen(full_prompt, temperature=config["temperature"])
                elif config["provider"] == "ernie":
                    response = await ai_chat_service.chat_ernie(full_prompt, temperature=config["temperature"])
                elif config["provider"] == "zhipu":
                    response = await ai_chat_service.chat_zhipu(full_prompt, temperature=config["temperature"])
                else:
                    response = await ai_chat_service.chat(full_prompt, history=history, temperature=config["temperature"])

                answer = response.get("answer", "") if response else ""
                success = response.get("success", False) if response else False
                game_state["api_calls_made"] += 1
            except Exception as e:
                answer = f"调用失败: {str(e)}"
                success = False

            # 计算分数（基于回答质量）
            score = 0
            if success and answer:
                # 基础分 + 长度分 + 质量分
                score = 5.0 + min(len(answer) / 100, 3.0) + (0 if "调用失败" in answer else 2.0)
                # 策略制定者额外加分（逻辑严谨）
                if player == "strategist" and ("策略" in answer or "分析" in answer):
                    score += 0.5
                # 批判者额外加分（批判性思维）
                if player == "critic" and ("质疑" in answer or "问题" in answer or "改进" in answer):
                    score += 0.5
                # 调解者额外加分（综合平衡）
                if player == "mediator" and ("综合" in answer or "平衡" in answer or "建议" in answer):
                    score += 0.5
            else:
                score = 3.0  # 失败保底分

            round_scores[player] = score
            round_record["answers"].append({
                "agent": player,
                "agent_name": config["name"],
                "provider": config["provider"],
                "content": answer,
                "score": round(score, 2),
                "success": success
            })

            # 更新历史
            history.append({"role": "assistant", "content": answer[:300]})

        # 判定本回合最佳回答
        best_player = max(round_scores.keys(), key=lambda k: round_scores[k])
        roupackage com.yidao.linxiang.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yidao.linxiang.common.CommunityFilterHelper;
import com.yidao.linxiang.common.result.Result;
import com.yidao.linxiang.entity.ServiceItem;
import com.yidao.linxiang.entity.IdleItem;
import com.yidao.linxiang.entity.RentalItem;
import com.yidao.linxiang.entity.HelpItem;
import com.yidao.linxiang.entity.GroupOrder;
import com.yidao.linxiang.service.ServiceItemService;
import com.yidao.linxiang.service.IdleItemService;
import com.yidao.linxiang.service.RentalItemService;
import com.yidao.linxiang.service.HelpItemService;
import com.yidao.linxiang.service.GroupOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 全局搜索控制器 - 所有搜索按社区隔离
 */
@RestController
@RequestMapping("/api/search")
public class SearchController {

    @Autowired
    private ServiceItemService serviceItemService;

    @Autowired
    private IdleItemService idleItemService;

    @Autowired
    private RentalItemService rentalItemService;

    @Autowired
    private HelpItemService helpItemService;

    @Autowired
    private GroupOrderService groupOrderService;

    /** 辅助方法：从参数或上下文获取社区ID */
    private Integer resolveCid(Long paramCommunityId) {
        if (paramCommunityId != null && paramCommunityId > 0) return paramCommunityId.intValue();
        return CommunityFilterHelper.getCurrentCommunityId();
    }

    /**
     * 搜索服务 - 按社区隔离
     */
    @GetMapping("/service")
    public Result<List<ServiceItem>> searchService(
            @RequestParam String keyword,
            @RequestParam(required = false) Long communityId) {
        LambdaQueryWrapper<ServiceItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(ServiceItem::getTitle, keyword)
               .or()
               .like(ServiceItem::getContent, keyword);
        wrapper.eq(ServiceItem::getStatus, 1);
        // 社区隔离
        Integer cid = resolveCid(communityId);
        if (cid != null && cid > 0) {
            wrapper.and(w -> w.eq(ServiceItem::getCommunityId, cid).or().eq(ServiceItem::getCommunityId, 0));
        }
        List<ServiceItem> list = serviceItemService.list(wrapper);
        return Result.success(list);
    }

    /**
     * 搜索闲置 - 按社区隔离
     */
    @GetMapping("/idle")
    public Result<List<IdleItem>> searchIdle(
            @RequestParam String keyword,
            @RequestParam(required = false) Long communityId) {
        LambdaQueryWrapper<IdleItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.like(IdleItem::getTitle, keyword)
                         .or()
                         .like(IdleItem::getDescription, keyword));
        Integer cid = resolveCid(communityId);
        if (cid != null && cid > 0) {
            wrapper.eq(IdleItem::getCommunityId, cid);
        }
        wrapper.eq(IdleItem::getStatus, 1);
        List<IdleItem> list = idleItemService.list(wrapper);
        return Result.success(list);
    }

    /**
     * 搜索租赁 - 按社区隔离
     */
    @GetMapping("/rental")
    public Result<List<RentalItem>> searchRental(
            @RequestParam String keyword,
            @RequestParam(required = false) Long communityId) {
        LambdaQueryWrapper<RentalItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.like(RentalItem::getTitle, keyword)
                         .or()
                         .like(RentalItem::getDescription, keyword));
        Integer cid = resolveCid(communityId);
        if (cid != null && cid > 0) {
            wrapper.eq(RentalItem::getCommunityId, cid);
        }
        wrapper.eq(RentalItem::getStatus, 1);
        List<RentalItem> list = rentalItemService.list(wrapper);
        return Result.success(list);
    }

    /**
     * 搜索求助 - 按社区隔离
     */
    @GetMapping("/help")
    public Result<List<HelpItem>> searchHelp(
            @RequestParam String keyword,
            @RequestParam(required = false) Long communityId) {
        LambdaQueryWrapper<HelpItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.like(HelpItem::getTitle, keyword)
                         .or()
                         .like(HelpItem::getDescription, keyword));
        Integer cid = resolveCid(communityId);
        if (cid != null && cid > 0) {
            wrapper.eq(HelpItem::getCommunityId, cid);
        }
        wrapper.eq(HelpItem::getStatus, "open");
        List<HelpItem> list = helpItemService.list(wrapper);
        return Result.success(list);
    }

    /**
     * 搜索团购 - 按社区隔离
     */
    @GetMapping("/group")
    public Result<List<GroupOrder>> searchGroup(
            @RequestParam String keyword,
            @RequestParam(required = false) Long communityId) {
        LambdaQueryWrapper<GroupOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(GroupOrder::getGoodsName, keyword);
        wrapper.in(GroupOrder::getStatus, 0, 1);
        // 社区隔离
        Integer cid = resolveCid(communityId);
        if (cid != null && cid > 0) {
            wrapper.eq(GroupOrder::getCommunityId, cid);
        }
        List<GroupOrder> list = groupOrderService.list(wrapper);
        return Result.success(list);
    }

    /**
     * 全局搜索（返回所有类型）- 全部按社区隔离
     */
    @GetMapping("/global")
    public Result<Map<String, Object>> globalSearch(
            @RequestParam String keyword,
            @RequestParam(required = false) Long communityId) {
        
        Map<String, Object> result = new HashMap<>();
        Integer cid = resolveCid(communityId);
        
        // 搜索服务
        LambdaQueryWrapper<ServiceItem> serviceWrapper = new LambdaQueryWrapper<>();
        serviceWrapper.like(ServiceItem::getTitle, keyword)
                     .or()
                     .like(ServiceItem::getContent, keyword);
        serviceWrapper.eq(ServiceItem::getStatus, 1);
        if (cid != null && cid > 0) {
            serviceWrapper.and(w -> w.eq(ServiceItem::getCommunityId, cid).or().eq(ServiceItem::getCommunityId, 0));
        }
        List<ServiceItem> services = serviceItemService.list(serviceWrapper);
        result.put("services", services);
        
        // 搜索闲置
        LambdaQueryWrapper<IdleItem> idleWrapper = new LambdaQueryWrapper<>();
        idleWrapper.and(w -> w.like(IdleItem::getTitle, keyword)
                             .or()
                             .like(IdleItem::getDescription, keyword));
        if (cid != null && cid > 0) {
            idleWrapper.eq(IdleItem::getCommunityId, cid);
        }
        idleWrapper.eq(IdleItem::getStatus, 1);
        List<IdleItem> idles = idleItemService.list(idleWrapper);
        result.put("idles", idles);
        
        // 搜索租赁
        LambdaQueryWrapper<RentalItem> rentalWrapper = new LambdaQueryWrapper<>();
        rentalWrapper.and(w -> w.like(RentalItem::getTitle, keyword)
                             .or()
                             .like(RentalItem::getDescription, keyword));
        if (cid != null && cid > 0) {
            rentalWrapper.eq(RentalItem::getCommunityId, cid);
        }
        rentalWrapper.eq(RentalItem::getStatus, 1);
        List<RentalItem> rentals = rentalItemService.list(rentalWrapper);
        result.put("rentals", rentals);
        
        // 搜索求助
        LambdaQueryWrapper<HelpItem> helpWrapper = new LambdaQueryWrapper<>();
        helpWrapper.and(w -> w.like(HelpItem::getTitle, keyword)
                             .or()
                             .like(HelpItem::getDescription, keyword));
        if (cid != null && cid > 0) {
            helpWrapper.eq(HelpItem::getCommunityId, cid);
        }
        helpWrapper.eq(HelpItem::getStatus, "open");
        List<HelpItem> helps = helpItemService.list(helpWrapper);
        result.put("helps", helps);
        
        // 搜索团购
        LambdaQueryWrapper<GroupOrder> groupWrapper = new LambdaQueryWrapper<>();
        groupWrapper.like(GroupOrder::getGoodsName, keyword);
        groupWrapper.in(GroupOrder::getStatus, 0, 1);
        if (cid != null && cid > 0) {
            groupWrapper.eq(GroupOrder::getCommunityId, cid);
        }
        List<GroupOrder> groups = groupOrderService.list(groupWrapper);
        result.put("groups", groups);
        
        return Result.
/**
 * Edos AI - 表单输入系统 v1.0.0
 * 完整表单组件库：输入框、选择器、复选框、单选、开关、表单分组、验证
 */

/* ============================================================
   1. 文本输入框增强 (Text Inputs)
   ============================================================ */
.edos-input {
  width: 100%;
  padding: 10px 14px;
  background: var(--edos-bg-tertiary, #f1f5f9);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-md, 10px);
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 0.875rem;
  font-family: var(--edos-font-sans, inherit);
  line-height: 1.5;
  transition: all var(--edos-transition-fast, 150ms ease);
  outline: none;
}
.edos-input:hover {
  border-color: var(--edos-border-hover, rgba(0,212,255,.25));
  background: rgba(26,26,62,.8);
}
.edos-input:focus {
  border-color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 0 3px rgba(0,212,255,.1), 0 0 12px rgba(0,212,255,.06);
  background: rgba(30,30,66,.9);
}
.edos-input::placeholder {
  color: var(--edos-text-tertiary, #7e7eaa);
  opacity: 0.7;
}
.edos-input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: rgba(255,255,255,.02);
}

/* 输入框尺寸变体 */
.edos-input-sm {
  padding: 6px 10px;
  font-size: 0.8125rem;
  border-radius: var(--edos-radius-sm, 6px);
}
.edos-input-lg {
  padding: 14px 18px;
  font-size: 1rem;
  border-radius: var(--edos-radius-lg, 16px);
}

/* 图标输入框 */
.edos-input-with-icon {
  position: relative;
}
.edos-input-with-icon .edos-input {
  padding-left: 40px;
}
.edos-input-with-icon .input-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--edos-text-tertiary, #7e7eaa);
  font-size: 1rem;
  pointer-events: none;
  transition: color var(--edos-transition-fast);
}
.edos-input-with-icon .edos-input:focus ~ .input-icon,
.edos-input-with-icon .edos-input:focus + .input-icon {
  color: var(--edos-primary, #00d4ff);
}

/* 搜索框 */
.edos-search-box {
  position: relative;
}
.edos-search-box .edos-input {
  padding-left: 40px;
  border-radius: var(--edos-radius-full, 9999px);
  background: rgba(255,255,255,.06);
  border-color: transparent;
}
.edos-search-box .search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--edos-text-tertiary, #7e7eaa);
  font-size: 1rem;
}
.edos-search-box .edos-input:focus {
  background: rgba(255,255,255,.1);
  border-color: var(--edos-primary, #00d4ff);
}

/* ============================================================
   2. 文本域 (Textarea)
   ============================================================ */
.edos-textarea {
  width: 100%;
  min-height: 100px;
  padding: 12px 14px;
  background: var(--edos-bg-tertiary, #f1f5f9);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-md, 10px);
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 0.875rem;
  font-family: var(--edos-font-sans, inherit);
  line-height: 1.6;
  resize: vertical;
  transition: all var(--edos-transition-fast);
  outline: none;
}
.edos-textarea:focus {
  border-color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 0 3px rgba(0,212,255,.1);
}
.edos-textarea::placeholder {
  color: var(--edos-text-tertiary, #7e7eaa);
}

/* 代码/等宽文本域 */
.edos-textarea-mono {
  font-family: var(--edos-font-mono, 'Consolas', monospace);
  font-size: 0.8125rem;
  line-height: 1.7;
  tab-size: 4;
}

/* ============================================================
   3. 选择器 (Select)
   ============================================================ */
.edos-select {
  width: 100%;
  padding: 10px 36px 10px 14px;
  background: var(--edos-bg-tertiary, #f1f5f9);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-md, 10px);
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 0.875rem;
  font-family: inherit;
  cursor: pointer;
  outline: none;
  transition: all var(--edos-transition-fast);
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23a0a0cc' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}
.edos-select:hover {
  border-color: var(--edos-border-hover, rgba(0,212,255,.25));
}
.edos-select:focus {
  border-color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 0 3px rgba(0,212,255,.1);
}
.edos-select option {
  background: var(--edos-bg-secondary, #12122a);
  color: var(--edos-text-primary, #f0f0ff);
  padding: 8px;
}

/* 多选选择器 */
.edos-select-multi {
  min-height: 42px;
  background-image: none;
  padding: 6px 8px;
}

/* ============================================================
   4. 复选框 (Checkbox)
   ============================================================ */
.edos-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--edos-text-primary, #f0f0ff);
  user-select: none;
}
.edos-checkbox input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border: 2px solid var(--edos-border-default, rgba(0,212,255,.2));
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: all var(--edos-transition-fast);
}
.edos-checkbox input[type="checkbox"]:checked {
  background: var(--edos-primary, #00d4ff);
  border-color: var(--edos-primary, #00d4ff);
}
.edos-checkbox input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 6px;
  height: 10px;
  border: solid #000;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.edos-checkbox input[type="checkbox"]:focus-visible {
  box-shadow: 0 0 0 3px rgba(0,212,255,.15);
}
.edos-checkbox:hover input[type="checkbox"] {
  border-color: var(--edos-primary, #00d4ff);
}

/* 复选框卡片 */
.edos-checkbox-card {
  padding: 14px 16px;
  background: var(--edos-bg-tertiary, #f1f5f9);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-md, 10px);
  transition: all var(--edos-transition-fast);
}
.edos-checkbox-card:has(input:checked) {
  border-color: var(--edos-primary, #00d4ff);
  background: rgba(0,212,255,.05);
  box-shadow: 0 0 12px rgba(0,212,255,.08);
}

/* ============================================================
   5. 单选框 (Radio)
   ============================================================ */
.edos-radio {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--edos-text-primary, #f0f0ff);
  user-select: none;
}
.edos-radio input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border: 2px solid var(--edos-border-default, rgba(0,212,255,.2));
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: all var(--edos-transition-fast);
}
.edos-radio input[type="radio"]:checked {
  border-color: var(--edos-accent, #a855f7);
}
.edos-radio input[type="radio"]:checked::after {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--edos-accent, #a855f7);
}
.edos-radio input[type="radio"]:focus-visible {
  box-shadow: 0 0 0 3px rgba(168,85,247,.15);
}

/* 单选按钮组 */
.edos-radio-group {
  display: inline-flex;
  border-radius: var(--edos-radius-md, 10px);
  overflow: hidden;
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
}
.edos-radio-group .edos-radio-btn {
  padding: 8px 16px;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--edos-text-secondary, #a0a0cc);
  background: transparent;
  border: none;
  border-right: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  cursor: pointer;
  transition: all var(--edos-transition-fast);
}
.edos-radio-group .edos-radio-btn:last-child {
  border-right: none;
}
.edos-radio-group .edos-radio-btn.active {
  background: var(--edos-primary, #00d4ff);
  color: #000;
  font-weight: 600;
}
.edos-radio-group .edos-radio-btn:hover:not(.active) {
  background: rgba(255,255,255,.05);
  color: var(--edos-text-primary, #f0f0ff);
}

/* ============================================================
   6. 开关/Toggle (Switch)
   ============================================================ */
.edos-switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  font-size: 0.875rem;
  color: var(--edos-text-primary, #f0f0ff);
}
.edos-switch input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 44px;
  height: 24px;
  background: rgba(120,140,180,.3);
  border-radius: 12px;
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
  transition: all var(--edos-transition-fast);
}
.edos-switch input[type="checkbox"]::before {
  content: '';
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  top: 3px;
  left: 3px;
  transition: transform var(--edos-transition-fast);
}
.edos-switch input[type="checkbox"]:checked {
  background: var(--edos-primary, #00d4ff);
}
.edos-switch input[type="checkbox"]:checked::before {
  transform: translateX(20px);
}
.edos-switch input[type="checkbox"]:focus-visible {
  box-shadow: 0 0 0 3px rgba(0,212,255,.15);
}

/* 强调色开关 */
.edos-switch.accent input:checked {
  background: var(--edos-accent, #a855f7);
}
.edos-switch.success input:checked {
  background: var(--edos-success, #22c55e);
}

/* 大号开关 */
.edos-switch-lg input[type="checkbox"] {
  width: 56px;
  height: 30px;
  border-radius: 15px;
}
.edos-switch-lg input[type="checkbox"]::before {
  width: 24px;
  height: 24px;
  top: 3px;
  left: 3px;
}
.edos-switch-lg input[type="checkbox"]:checked::before {
  transform: translateX(26px);
}

/* ============================================================
   7. 表单分组 (Form Groups)
   ============================================================ */
.edos-form-group {
  margin-bottom: var(--edos-spacing-md, 16px);
}
.edos-form-label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--edos-text-secondary, #a0a0cc);
  letter-spacing: 0.01em;
}
.edos-form-label .required {
  color: var(--edos-error, #ef4444);
  margin-left: 2px;
}
.edos-form-hint {
  display: block;
  margin-top: 4px;
  font-size: 0.75rem;
  color: var(--edos-text-tertiary, #7e7eaa);
}
.edos-form-error {
  display: block;
  margin-top: 4px;
  font-size: 0.75rem;
  color: var(--edos-error, #ef4444);
}

/* 水平表单行 */
.edos-form-row {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
.edos-form-row .edos-form-group {
  flex: 1;
}

/* 内联标签（标签和输入在同一行） */
.edos-form-inline {
  display: flex;
  align-items: center;
  gap: 12px;
}
.edos-form-inline .edos-form-label {
  margin-bottom: 0;
  white-space: nowrap;
}

/* ============================================================
   8. 验证状态 (Validation States)
   ============================================================ */
.edos-input.is-valid,
.edos-textarea.is-valid,
.edos-select.is-valid {
  border-color: var(--edos-success, #22c55e);
  box-shadow: 0 0 0 1px rgba(34,197,94,.15);
}
.edos-input.is-invalid,
.edos-textarea.is-invalid,
.edos-select.is-invalid {
  border-color: var(--edos-error, #ef4444);
  box-shadow: 0 0 0 1px rgba(239,68,68,.15);
}
.edos-input.is-valid:focus {
  box-shadow: 0 0 0 3px rgba(34,197,94,.15), 0 0 12px rgba(34,197,94,.06);
}
.edos-input.is-invalid:focus {
  box-shadow: 0 0 0 3px rgba(239,68,68,.15), 0 0 12px rgba(239,68,68,.06);
}

/* 验证反馈图标 */
.edos-input-feedback {
  position: relative;
}
.edos-input-feedback .edos-input.is-valid {
  padding-right: 36px;
}
.edos-input-feedback .edos-input.is-invalid {
  padding-right: 36px;
}
.edos-input-feedback .feedback-icon {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1rem;
  pointer-events: none;
}
.edos-input-feedback .is-valid ~ .feedback-icon {
  color: var(--edos-success, #22c55e);
}
.edos-input-feedback .is-invalid ~ .feedback-icon {
  color: var(--edos-error, #ef4444);
}

/* ============================================================
   9. 输入组 (Input Groups) - 前缀/后缀
   ============================================================ */
.edos-input-group {
  display: flex;
  align-items: stretch;
}
.edos-input-group .edos-input {
  border-radius: 0;
  flex: 1;
}
.edos-input-group .edos-input:first-child {
  border-radius: var(--edos-radius-md, 10px) 0 0 var(--edos-radius-md, 10px);
}
.edos-input-group .edos-input:last-child {
  border-radius: 0 var(--edos-radius-md, 10px) var(--edos-radius-md, 10px) 0;
}
.edos-input-addon {
  display: flex;
  align-items: center;
  padding: 0 14px;
  font-size: 0.8125rem;
  color: var(--edos-text-secondary, #a0a0cc);
  background: rgba(255,255,255,.04);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  white-space: nowrap;
}
.edos-input-addon:first-child {
  border-radius: var(--edos-radius-md, 10px) 0 0 var(--edos-radius-md, 10px);
  border-right: none;
}
.edos-input-addon:last-child {
  border-radius: 0 var(--edos-radius-md, 10px) var(--edos-radius-md, 10px) 0;
  border-left: none;
}

/* ============================================================
   10. 颜色选择器 (Color Picker)
   ============================================================ */
.edos-color-input {
  width: 44px;
  height: 38px;
  padding: 3px;
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-sm, 6px);
  background: var(--edos-bg-tertiary, #f1f5f9);
  cursor: pointer;
  transition: border-color var(--edos-transition-fast);
}
.edos-color-input:focus {
  border-color: var(--edos-primary, #00d4ff);
  outline: none;
}

/* ============================================================
   11. 文件上传 (File Upload)
   ============================================================ */
.edos-file-upload {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.edos-file-upload input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}
.edos-file-upload .upload-zone {
  padding: 24px;
  border: 2px dashed var(--edos-border-default, rgba(0,212,255,.15));
  border-radius: var(--edos-radius-lg, 16px);
  text-align: center;
  transition: all var(--edos-transition-fast);
  cursor: pointer;
  min-width: 200px;
}
.edos-file-upload .upload-zone:hover,
.edos-file-upload .upload-zone.drag-over {
  border-color: var(--edos-primary, #00d4ff);
  background: rgba(0,212,255,.03);
}
.edos-file-upload .upload-zone .upload-icon {
  font-size: 2rem;
  margin-bottom: 8px;
  color: var(--edos-text-tertiary, #7e7eaa);
}
.edos-file-upload .upload-zone .upload-text {
  font-size: 0.875rem;
  color: var(--edos-text-secondary, #a0a0cc);
}
.edos-file-upload .upload-zone .upload-hint {
  font-size: 0.75rem;
  color: var(--edos-text-tertiary, #7e7eaa);
  margin-top: 4px;
}

/* ============================================================
   12. 范围滑块 (Range Slider)
   ============================================================ */
.edos-range {
  width: 100%;
  height: 6px;
  border-radius: 3px;
  background: rgba(255,255,255,.08);
  appearance: none;
  -webkit-appearance: none;
  outline: none;
  cursor: pointer;
}
.edos-range::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 8px rgba(0,212,255,.3);
  cursor: pointer;
  transition: transform var(--edos-transition-fast);
}
.edos-range::-webkit-slider-thumb:hover {
  transform: scale(1.2);
}
.edos-range::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--edos-primary, #00d4ff);
  border: none;
  box-shadow: 0 0 8px rgba(0,212,255,.3);
  cursor: pointer;
}

/* 范围值显示 */
.edos-range-value {
  display: flex;
  align-items: center;
  gap: 12px;
}
.edos-range-value .edos-range {
  flex: 1;
}
.edos-range-value .range-label {
  min-width: 40px;
  text-align: center;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--edos-primary, #00d4ff);
}

/* ============================================================
   13. 表单卡片 (Form Card)
   ============================================================ */
.edos-form-card {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-lg, 16px);
  padding: var(--edos-spacing-lg, 24px);
}
.edos-form-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--edos-spacing-lg, 24px);
  padding-bottom: var(--edos-spacing-md, 16px);
  border-bottom: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
}
.edos-form-card-title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--edos-text-primary, #f0f0ff);
}
.edos-form-card-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin-top: var(--edos-spacing-lg, 24px);
  padding-top: var(--edos-spacing-md, 16px);
  border-top: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
}

/* ============================================================
   14. 响应式表单
   ============================================================ */
@media screen and (max-width: 640px) {
  .edos-form-row {
    flex-direction: column;
    gap: 0;
  }
  .edos-form-card {
    padding: var(--edos-spacing-md, 16px);
  }
  .edos-input-group {
    flex-wrap: wrap;
  }
  .edos-input-group .edos-input,
  .edos-input-group .edos-input-addon {
    border-radius: var(--edos-radius-sm, 6px) !important;
  }
}

/**
 * Edos AI - 模态框与导航系统 v1.0.0
 * 模态框、抽屉、确认对话框、标签页、分页、面包屑、步骤条
 */

/* ============================================================
   1. 模态框系统 (Modal)
   ============================================================ */
.edos-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  animation: modalFadeIn .2s ease;
  padding: 20px;
}
@keyframes modalFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modalSlideUp {
  from { opacity: 0; transform: translateY(20px) scale(.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.edos-modal {
  background: var(--edos-bg-secondary, #12122a);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-xl, 24px);
  width: 100%;
  max-height: 85vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,.5), 0 0 40px rgba(0,212,255,.05);
  animation: modalSlideUp .3s ease;
}
.edos-modal-sm { max-width: 440px; }
.edos-modal-md { max-width: 600px; }
.edos-modal-lg { max-width: 800px; }
.edos-modal-xl { max-width: 1100px; }

/* 模态框头部 */
.edos-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
  flex-shrink: 0;
}
.edos-modal-title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--edos-text-primary, #f0f0ff);
  display: flex;
  align-items: center;
  gap: 10px;
}
.edos-modal-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,.06);
  color: var(--edos-text-tertiary, #7e7eaa);
  font-size: 1.25rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--edos-transition-fast);
  flex-shrink: 0;
}
.edos-modal-close:hover {
  background: rgba(239,68,68,.15);
  color: var(--edos-error, #ef4444);
}

/* 模态框主体 */
.edos-modal-body {
  padding: 20px 24px;
  overflow-y: auto;
  flex: 1;
  color: var(--edos-text-secondary, #a0a0cc);
  font-size: 0.875rem;
  line-height: 1.6;
}

/* 模态框底部 */
.edos-modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 16px 24px;
  border-top: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
  flex-shrink: 0;
}

/* ============================================================
   2. 确认对话框 (Confirm Dialog)
   ============================================================ */
.edos-confirm-dialog .edos-modal-body {
  text-align: center;
  padding: 32px 24px;
}
.edos-confirm-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin: 0 auto 16px;
}
.edos-confirm-icon.warning {
  background: rgba(245,158,11,.12);
  color: var(--edos-warning, #f59e0b);
}
.edos-confirm-icon.error {
  background: rgba(239,68,68,.12);
  color: var(--edos-error, #ef4444);
}
.edos-confirm-icon.success {
  background: rgba(34,197,94,.12);
  color: var(--edos-success, #22c55e);
}
.edos-confirm-icon.info {
  background: rgba(59,130,246,.12);
  color: var(--edos-info, #3b82f6);
}

/* ============================================================
   3. 侧边抽屉 (Drawer / Slide Panel)
   ============================================================ */
.edos-drawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.4);
  z-index: 10000;
  animation: modalFadeIn .2s ease;
}
.edos-drawer {
  position: fixed;
  top: 0;
  bottom: 0;
  width: 400px;
  max-width: 90vw;
  background: var(--edos-bg-secondary, #12122a);
  border-left: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  box-shadow: -8px 0 32px rgba(0,0,0,.4);
  display: flex;
  flex-direction: column;
  z-index: 10001;
  animation: drawerSlideIn .3s ease;
}
.edos-drawer-right {
  right: 0;
}
.edos-drawer-left {
  left: 0;
  border-left: none;
  border-right: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  box-shadow: 8px 0 32px rgba(0,0,0,.4);
  animation: drawerSlideInLeft .3s ease;
}
@keyframes drawerSlideIn {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}
@keyframes drawerSlideInLeft {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

.edos-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
  flex-shrink: 0;
}
.edos-drawer-body {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
}
.edos-drawer-footer {
  padding: 16px 20px;
  border-top: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
  flex-shrink: 0;
}

/* ============================================================
   4. 弹出菜单 (Popover / Dropdown)
   ============================================================ */
.edos-dropdown {
  position: relative;
  display: inline-block;
}
.edos-dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 200px;
  background: var(--edos-bg-secondary, #12122a);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: var(--edos-radius-md, 10px);
  padding: 6px;
  box-shadow: 0 8px 32px rgba(0,0,0,.4);
  z-index: 1000;
  animation: dropdownFadeIn .15s ease;
}
.edos-dropdown-menu.left {
  right: auto;
  left: 0;
}
@keyframes dropdownFadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.edos-dropdown-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  font-size: 0.875rem;
  color: var(--edos-text-primary, #f0f0ff);
  border-radius: 6px;
  cursor: pointer;
  transition: all var(--edos-transition-fast);
  white-space: nowrap;
}
.edos-dropdown-item:hover {
  background: rgba(255,255,255,.06);
}
.edos-dropdown-item.danger {
  color: var(--edos-error, #ef4444);
}
.edos-dropdown-item.danger:hover {
  background: rgba(239,68,68,.1);
}
.edos-dropdown-divider {
  height: 1px;
  background: var(--edos-border-default, rgba(0,212,255,.08));
  margin: 4px 0;
}

/* ============================================================
   5. 标签页 (Tabs)
   ============================================================ */
.edos-tabs {
  display: flex;
  border-bottom: 1px solid var(--edos-border-default, rgba(0,212,255,.1));
  gap: 0;
  margin-bottom: var(--edos-spacing-md, 16px);
}
.edos-tab {
  padding: 10px 20px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--edos-text-secondary, #a0a0cc);
  border: none;
  background: none;
  cursor: pointer;
  position: relative;
  transition: all var(--edos-transition-fast);
  white-space: nowrap;
}
.edos-tab::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: transparent;
  border-radius: 2px 2px 0 0;
  transition: all var(--edos-transition-fast);
}
.edos-tab:hover {
  color: var(--edos-text-primary, #f0f0ff);
}
.edos-tab.active {
  color: var(--edos-primary, #00d4ff);
  font-weight: 600;
}
.edos-tab.active::after {
  background: var(--edos-primary, #00d4ff);
}
.edos-tab .tab-badge {
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 0.6875rem;
  font-weight: 600;
  background: var(--edos-accent, #a855f7);
  color: #fff;
}

/* 胶囊标签 */
.edos-tabs-pills {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--edos-bg-tertiary, #f1f5f9);
  border-radius: var(--edos-radius-md, 10px);
  border-bottom: none;
}
.edos-tabs-pills .edos-tab {
  border-radius: 8px;
  padding: 8px 16px;
}
.edos-tabs-pills .edos-tab::after {
  display: none;
}
.edos-tabs-pills .edos-tab.active {
  background: var(--edos-primary, #00d4ff);
  color: #000;
}

/* 下划线标签变体 */
.edos-tabs-underline .edos-tab {
  padding: 6px 0;
  margin-right: 24px;
  border-bottom: 2px solid transparent;
}
.edos-tabs-underline .edos-tab::after {
  display: none;
}
.edos-tabs-underline .edos-tab.active {
  border-bottom-color: var(--edos-primary, #00d4ff);
}

/* ============================================================
   6. 分页 (Pagination)
   ============================================================ */
.edos-pagination {
  display: flex;
  align-items: center;
  gap: 4px;
  justify-content: center;
  margin-top: var(--edos-spacing-lg, 24px);
}
.edos-page-btn {
  min-width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--edos-radius-sm, 6px);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  background: transparent;
  color: var(--edos-text-secondary, #a0a0cc);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--edos-transition-fast);
  padding: 0 8px;
}
.edos-page-btn:hover {
  border-color: var(--edos-primary, #00d4ff);
  color: var(--edos-primary, #00d4ff);
  background: rgba(0,212,255,.05);
}
.edos-page-btn.active {
  background: var(--edos-primary, #00d4ff);
  color: #000;
  border-color: var(--edos-primary, #00d4ff);
  font-weight: 600;
}
.edos-page-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
  pointer-events: none;
}
.edos-page-ellipsis {
  min-width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--edos-text-tertiary, #7e7eaa);
  font-size: 0.8125rem;
}
.edos-page-info {
  font-size: 0.8125rem;
  color: var(--edos-text-tertiary, #7e7eaa);
  margin: 0 8px;
}

/* ============================================================
   7. 面包屑 (Breadcrumbs)
   ============================================================ */
.edos-breadcrumb {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8125rem;
  padding: 8px 0;
  flex-wrap: wrap;
}
.edos-breadcrumb-item {
  color: var(--edos-text-tertiary, #7e7eaa);
  text-decoration: none;
  transition: color var(--edos-transition-fast);
  white-space: nowrap;
}
.edos-breadcrumb-item:hover {
  color: var(--edos-primary, #00d4ff);
}
.edos-breadcrumb-item.active {
  color: var(--edos-text-primary, #f0f0ff);
  font-weight: 600;
  pointer-events: none;
}
.edos-breadcrumb-separator {
  color: var(--edos-text-tertiary, #7e7eaa);
  opacity: 0.5;
  font-size: 0.625rem;
  user-select: none;
}

/* ============================================================
   8. 步骤条 (Stepper)
   ============================================================ */
.edos-stepper {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--edos-spacing-xl, 32px);
  position: relative;
}
.edos-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  position: relative;
  z-index: 1;
}
.edos-step::after {
  content: '';
  position: absolute;
  top: 16px;
  left: calc(50% + 20px);
  right: calc(-50% + 20px);
  height: 2px;
  background: rgba(255,255,255,.08);
  z-index: 0;
}
.edos-step:last-child::after {
  display: none;
}
.edos-step.completed::after {
  background: var(--edos-primary, #00d4ff);
}

.edos-step-circle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8125rem;
  font-weight: 700;
  border: 2px solid rgba(255,255,255,.1);
  background: var(--edos-bg-tertiary, #f1f5f9);
  color: var(--edos-text-tertiary, #7e7eaa);
  transition: all var(--edos-transition-fast);
  position: relative;
  z-index: 1;
  margin-bottom: 8px;
}
.edos-step.active .edos-step-circle {
  border-color: var(--edos-primary, #00d4ff);
  background: rgba(0,212,255,.1);
  color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 12px rgba(0,212,255,.15);
}
.edos-step.completed .edos-step-circle {
  border-color: var(--edos-success, #22c55e);
  background: var(--edos-success, #22c55e);
  color: #000;
}

.edos-step-label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--edos-text-tertiary, #7e7eaa);
  text-align: center;
  max-width: 100px;
  transition: color var(--edos-transition-fast);
}
.edos-step.active .edos-step-label {
  color: var(--edos-primary, #00d4ff);
  font-weight: 600;
}
.edos-step.completed .edos-step-label {
  color: var(--edos-success, #22c55e);
}

/* 垂直步骤条 */
.edos-stepper-vertical {
  flex-direction: column;
  gap: 0;
}
.edos-stepper-vertical .edos-step {
  flex-direction: row;
  align-items: flex-start;
  gap: 16px;
  padding-bottom: 24px;
  position: relative;
}
.edos-stepper-vertical .edos-step::after {
  top: 36px;
  left: 15px;
  right: auto;
  bottom: 0;
  width: 2px;
  height: auto;
}
.edos-stepper-vertical .edos-step:last-child::after {
  display: none;
}
.edos-stepper-vertical .edos-step-label {
  text-align: left;
  max-width: none;
}

/* ============================================================
   9. 工具栏 (Toolbar)
   ============================================================ */
.edos-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: var(--edos-bg-tertiary, #f1f5f9);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.1));
  border-radius: var(--edos-radius-md, 10px);
  flex-wrap: wrap;
}
.edos-toolbar-divider {
  width: 1px;
  height: 24px;
  background: var(--edos-border-default, rgba(0,212,255,.15));
  margin: 0 4px;
}

/* ============================================================
   10. 命令面板 (Command Palette)
   ============================================================ */
.edos-command-palette {
  position: fixed;
  top: 15%;
  left: 50%;
  transform: translateX(-50%);
  width: 560px;
  max-width: 90vw;
  background: var(--edos-bg-secondary, #12122a);
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.15));
  border-radius: var(--edos-radius-lg, 16px);
  box-shadow: 0 20px 60px rgba(0,0,0,.5), 0 0 40px rgba(0,212,255,.08);
  z-index: 10002;
  overflow: hidden;
  animation: modalSlideUp .2s ease;
}
.edos-command-palette input {
  width: 100%;
  padding: 16px 20px;
  border: none;
  background: transparent;
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 1rem;
  outline: none;
  border-bottom: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
}
.edos-command-palette input::placeholder {
  color: var(--edos-text-tertiary, #7e7eaa);
}
.edos-command-results {
  max-height: 360px;
  overflow-y: auto;
  padding: 6px;
}
.edos-command-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  cursor: pointer;
  transition: all var(--edos-transition-fast);
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 0.875rem;
}
.edos-command-item:hover,
.edos-command-item.selected {
  background: rgba(0,212,255,.08);
}
.edos-command-item .cmd-shortcut {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--edos-text-tertiary, #7e7eaa);
  background: rgba(255,255,255,.06);
  padding: 2px 8px;
  border-radius: 4px;
  font-family: var(--edos-font-mono, monospace);
}

/* ============================================================
   11. 底部面板 (Bottom Sheet)
   ============================================================ */
.edos-bottom-sheet-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.5);
  z-index: 10000;
  animation: modalFadeIn .2s ease;
}
.edos-bottom-sheet {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  max-height: 80vh;
  background: var(--edos-bg-secondary, #12122a);
  border-top: 1px solid var(--edos-border-default, rgba(0,212,255,.12));
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -8px 32px rgba(0,0,0,.4);
  z-index: 10001;
  animation: bottomSheetSlideUp .3s ease;
  display: flex;
  flex-direction: column;
}
@keyframes bottomSheetSlideUp {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
.edos-bottom-sheet-handle {
  width: 36px;
  height: 4px;
  background: rgba(255,255,255,.15);
  border-radius: 2px;
  margin: 10px auto;
  flex-shrink: 0;
}
.edos-bottom-sheet-body {
  flex: 1;
  overflow-y: auto;
  padding: 0 20px 20px;
}

/* ============================================================
   12. 响应式适配
   ============================================================ */
@media screen and (max-width: 640px) {
  .edos-modal {
    margin: 0 8px;
    border-radius: var(--edos-radius-lg, 16px);
    max-height: 90vh;
  }
  .edos-drawer {
    width: 85vw;
  }
  .edos-tabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .edos-tab {
    padding: 8px 14px;
    font-size: 0.8125rem;
  }
  .edos-pagination {
    flex-wrap: wrap;
  }
  .edos-stepper {
    flex-wrap: wrap;
    gap: 12px;
  }
  .edos-stepper .edos-step::after {
    display: none;
  }
}

/**
 * Edos AI - 仪表盘卡片设计系统 v1.0.0
 * 统计数据卡片、指标容器、图表面板、数据展示组件
 */

/* ============================================================
   1. 统计卡片 (Stat Cards)
   ============================================================ */
.stat-card {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  border-radius: var(--edos-radius-lg, 16px);
  padding: var(--edos-spacing-lg, 24px);
  transition: all var(--edos-transition-normal, 300ms ease);
  position: relative;
  overflow: hidden;
}
.stat-card:hover {
  border-color: var(--edos-border-hover, rgba(0, 212, 255, 0.25));
  box-shadow: var(--edos-shadow-md, 0 4px 16px rgba(0,0,0,0.4));
  transform: translateY(-2px);
}
.stat-card .stat-icon {
  width: 44px; height: 44px;
  border-radius: var(--edos-radius-md, 10px);
  display: flex;
  align-items: center; justify-content: center;
  font-size: 1.25rem;
  margin-bottom: var(--edos-spacing-md, 16px);
  flex-shrink: 0;
}
.stat-card .stat-icon.cyan  { background: rgba(0, 212, 255, 0.1); color: var(--edos-primary, #00d4ff); }
.stat-card .stat-icon.purple { background: rgba(168, 85, 247, 0.1); color: var(--edos-accent, #a855f7); }
.stat-card .stat-icon.green  { background: rgba(34, 197, 94, 0.1); color: var(--edos-success, #22c55e); }
.stat-card .stat-icon.orange { background: rgba(245, 158, 11, 0.1); color: var(--edos-warning, #f59e0b); }
.stat-card .stat-icon.blue   { background: rgba(59, 130, 246, 0.1); color: var(--edos-info, #3b82f6); }
.stat-card .stat-icon.pink   { background: rgba(244, 114, 182, 0.1); color: var(--edos-pink, #f472b6); }
.stat-card .stat-icon.red    { background: rgba(239, 68, 68, 0.1); color: var(--edos-error, #ef4444); }

.stat-card .stat-value {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--edos-text-primary, #f0f0ff);
  line-height: 1.2;
  margin-bottom: var(--edos-spacing-xs, 4px);
}
.stat-card .stat-label {
  font-size: 0.8125rem;
  color: var(--edos-text-secondary, #a0a0cc);
  font-weight: 500;
}
.stat-card .stat-change {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 0.75rem;
  font-weight: 600;
  margin-top: var(--edos-spacing-sm, 8px);
}
.stat-card .stat-change.up   { color: var(--edos-success, #22c55e); }
.stat-card .stat-change.down { color: var(--edos-error, #ef4444); }
.stat-card .stat-change.neutral { color: var(--edos-text-secondary, #a0a0cc); }

/* 卡片顶部装饰线 */
.stat-card.accent-top-cyan::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
  border-radius: var(--edos-radius-lg, 16px) var(--edos-radius-lg, 16px) 0 0;
}
.stat-card.accent-top-green::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--edos-success, #22c55e);
  border-radius: var(--edos-radius-lg, 16px) var(--edos-radius-lg, 16px) 0 0;
}
.stat-card.accent-top-warning::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--edos-warning, #f59e0b);
  border-radius: var(--edos-radius-lg, 16px) var(--edos-radius-lg, 16px) 0 0;
}

/* 小统计卡片 */
.stat-card-sm {
  padding: var(--edos-spacing-md, 16px);
}
.stat-card-sm .stat-value {
  font-size: 1.25rem;
}
.stat-card-sm .stat-icon {
  width: 36px; height: 36px;
  font-size: 1rem;
  margin-bottom: var(--edos-spacing-sm, 8px);
}

/* ============================================================
   2. 指标行 (Metric Row) - 水平布局指标
   ============================================================ */
.metric-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--edos-spacing-md, 16px) 0;
  border-bottom: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
}
.metric-row:last-child { border-bottom: none; }
.metric-row .metric-label {
  font-size: 0.8125rem;
  color: var(--edos-text-secondary, #a0a0cc);
  display: flex; align-items: center; gap: var(--edos-spacing-sm, 8px);
}
.metric-row .metric-value {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
}
.metric-row .metric-value.highlight {
  color: var(--edos-primary, #00d4ff);
}

/* ============================================================
   3. 图表容器 (Chart Container)
   ============================================================ */
.chart-container {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  border-radius: var(--edos-radius-lg, 16px);
  padding: var(--edos-spacing-lg, 24px);
  position: relative;
}
.chart-container .chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--edos-spacing-lg, 24px);
}
.chart-container .chart-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
}
.chart-container .chart-body {
  width: 100%;
  min-height: 200px;
  position: relative;
}

/* 图表占位符（实际渲染前）*/
.chart-placeholder {
  width: 100%;
  height: 100%;
  min-height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.02);
  border-radius: var(--edos-radius-md, 10px);
  border: 1px dashed var(--edos-border-default, rgba(0, 212, 255, 0.12));
}
.chart-placeholder .placeholder-text {
  color: var(--edos-text-tertiary, #7e7eaa);
  font-size: 0.875rem;
}

/* ============================================================
   4. 数据面板 (Data Panel)
   ============================================================ */
.data-panel {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  border-radius: var(--edos-radius-lg, 16px);
  overflow: hidden;
}
.data-panel .panel-header {
  padding: var(--edos-spacing-md, 16px) var(--edos-spacing-lg, 24px);
  border-bottom: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(255, 255, 255, 0.02);
}
.data-panel .panel-title {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
}
.data-panel .panel-body {
  padding: var(--edos-spacing-lg, 24px);
}
.data-panel .panel-footer {
  padding: var(--edos-spacing-md, 16px) var(--edos-spacing-lg, 24px);
  border-top: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--edos-spacing-sm, 8px);
}

/* ============================================================
   5. 信息卡片变体 (Info Card Variants)
   ============================================================ */
/* 功能卡片 */
.feature-card {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  border-radius: var(--edos-radius-lg, 16px);
  padding: var(--edos-spacing-xl, 32px);
  transition: all var(--edos-transition-normal, 300ms ease);
  text-align: center;
}
.feature-card:hover {
  border-color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 30px rgba(0, 212, 255, 0.08);
  transform: translateY(-3px);
}
.feature-card .feature-icon {
  width: 64px; height: 64px;
  border-radius: var(--edos-radius-lg, 16px);
  display: inline-flex;
  align-items: center; justify-content: center;
  font-size: 1.75rem;
  margin-bottom: var(--edos-spacing-lg, 24px);
  background: linear-gradient(135deg, rgba(0, 212, 255, 0.1), rgba(168, 85, 247, 0.1));
  border: 1px solid var(--edos-border-glow, rgba(0, 212, 255, 0.15));
}
.feature-card .feature-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
  margin-bottom: var(--edos-spacing-sm, 8px);
}
.feature-card .feature-description {
  font-size: 0.875rem;
  color: var(--edos-text-secondary, #a0a0cc);
  line-height: 1.6;
}

/* 通知卡片 */
.notification-card {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  border-radius: var(--edos-radius-md, 10px);
  padding: var(--edos-spacing-md, 16px);
  display: flex;
  gap: var(--edos-spacing-md, 16px);
  transition: all var(--edos-transition-fast, 150ms ease);
}
.notification-card:hover {
  border-color: var(--edos-border-hover, rgba(0, 212, 255, 0.25));
}
.notification-card.unread {
  border-left: 3px solid var(--edos-primary, #00d4ff);
  background: rgba(0, 212, 255, 0.03);
}
.notification-card .notif-icon {
  width: 40px; height: 40px;
  border-radius: var(--edos-radius-full, 9999px);
  display: flex;
  align-items: center; justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}
.notification-card .notif-content { flex: 1; min-width: 0; }
.notification-card .notif-title {
  font-size: 0.875rem; font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
  margin-bottom: 2px;
}
.notification-card .notif-text {
  font-size: 0.8125rem; color: var(--edos-text-secondary, #a0a0cc);
}
.notification-card .notif-time {
  font-size: 0.6875rem; color: var(--edos-text-tertiary, #7e7eaa);
  margin-top: 4px;
}

/* ============================================================
   6. 表格样式增强 (Table Styles)
   ============================================================ */
.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}
.data-table thead th {
  background: rgba(255, 255, 255, 0.03);
  padding: var(--edos-spacing-sm, 8px) var(--edos-spacing-md, 16px);
  text-align: left;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--edos-text-tertiary, #7e7eaa);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
}
.data-table thead th:first-child { border-radius: var(--edos-radius-sm, 6px) 0 0 0; }
.data-table thead th:last-child { border-radius: 0 var(--edos-radius-sm, 6px) 0 0; }
.data-table tbody td {
  padding: var(--edos-spacing-sm, 8px) var(--edos-spacing-md, 16px);
  font-size: 0.8125rem;
  color: var(--edos-text-secondary, #a0a0cc);
  border-bottom: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.06));
}
.data-table tbody tr:hover td {
  background: rgba(255, 255, 255, 0.02);
}
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody td:first-child { border-radius: 0 0 0 var(--edos-radius-sm, 6px); }
.data-table tbody td:last-child { border-radius: 0 0 var(--edos-radius-sm, 6px) 0; }

/* 紧凑表格 */
.data-table-sm thead th,
.data-table-sm tbody td {
  padding: var(--edos-spacing-xs, 4px) var(--edos-spacing-sm, 8px);
  font-size: 0.75rem;
}

/* ============================================================
   7. 进度条组件 (Progress Bar)
   ============================================================ */
.progress-bar {
  width: 100%;
  height: 6px;
  background: rgba(255, 255, 255, 0.06);
  border-radius: var(--edos-radius-full, 9999px);
  overflow: hidden;
}
.progress-bar .progress-fill {
  height: 100%;
  border-radius: var(--edos-radius-full, 9999px);
  background: linear-gradient(90deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
  transition: width var(--edos-transition-slow, 500ms ease);
}
.progress-bar.lg { height: 10px; }
.progress-bar.sm { height: 4px; }
.progress-bar .progress-fill.success { background: linear-gradient(90deg, var(--edos-success, #22c55e), #4ade80); }
.progress-bar .progress-fill.warning { background: linear-gradient(90deg, var(--edos-warning, #f59e0b), #fbbf24); }
.progress-bar .progress-fill.error   { background: linear-gradient(90deg, var(--edos-error, #ef4444), #f87171); }

.progress-bar-label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--edos-spacing-xs, 4px);
  font-size: 0.75rem;
  color: var(--edos-text-secondary, #a0a0cc);
}

/* ============================================================
   8. 列表组 (List Group)
   ============================================================ */
.list-group {
  display: flex;
  flex-direction: column;
}
.list-item {
  display: flex;
  align-items: center;
  padding: var(--edos-spacing-md, 16px);
  border-bottom: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.08));
  transition: background var(--edos-transition-fast, 150ms ease);
  gap: var(--edos-spacing-md, 16px);
}
.list-item:last-child { border-bottom: none; }
.list-item:hover { background: rgba(255, 255, 255, 0.02); }
.list-item.active {
  background: rgba(0, 212, 255, 0.06);
  border-left: 3px solid var(--edos-primary, #00d4ff);
}
.list-item .list-item-icon {
  width: 40px; height: 40px;
  border-radius: var(--edos-radius-md, 10px);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.125rem; flex-shrink: 0;
}
.list-item .list-item-body { flex: 1; min-width: 0; }
.list-item .list-item-title {
  font-size: 0.875rem; font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
  margin-bottom: 2px;
}
.list-item .list-item-subtitle {
  font-size: 0.75rem; color: var(--edos-text-tertiary, #7e7eaa);
}
.list-item .list-item-actions {
  display: flex; gap: var(--edos-spacing-sm, 8px); flex-shrink: 0;
}

/* ============================================================
   9. 标签组 (Tag / Chip)
   ============================================================ */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: var(--edos-radius-full, 9999px);
  font-size: 0.6875rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}
.tag-primary  { background: rgba(0, 212, 255, 0.1); color: var(--edos-primary, #00d4ff); }
.tag-accent   { background: rgba(168, 85, 247, 0.1); color: var(--edos-accent, #a855f7); }
.tag-success  { background: rgba(34, 197, 94, 0.1); color: var(--edos-success, #22c55e); }
.tag-warning  { background: rgba(245, 158, 11, 0.1); color: var(--edos-warning, #f59e0b); }
.tag-error    { background: rgba(239, 68, 68, 0.1); color: var(--edos-error, #ef4444); }
.tag-info     { background: rgba(59, 130, 246, 0.1); color: var(--edos-info, #3b82f6); }
.tag-outline  { background: transparent; border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12)); color: var(--edos-text-secondary, #a0a0cc); }
.tag-sm { padding: 2px 8px; font-size: 0.625rem; }

/* ============================================================
   10. 头像组件 (Avatar)
   ============================================================ */
.avatar {
  display: inline-flex;
  align-items: center; justify-content: center;
  border-radius: var(--edos-radius-full, 9999px);
  font-weight: 600; color: #fff;
  flex-shrink: 0;
  background: linear-gradient(135deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
}
.avatar-sm { width: 28px; height: 28px; font-size: 0.6875rem; }
.avatar-md { width: 36px; height: 36px; font-size: 0.8125rem; }
.avatar-lg { width: 48px; height: 48px; font-size: 1rem; }
.avatar-xl { width: 64px; height: 64px; font-size: 1.25rem; }

.avatar-group {
  display: flex; align-items: center;
}
.avatar-group .avatar:not(:first-child) {
  margin-left: -10px;
  border: 2px solid var(--edos-bg-card, #1e1e42);
}
.avatar-group .avatar-more {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--edos-bg-elevated, #252552);
  color: var(--edos-text-secondary, #a0a0cc);
  font-size: 0.75rem; font-weight: 600;
  margin-left: -10px;
  border: 2px solid var(--edos-bg-card, #1e1e42);
}

/* ============================================================
   11. 工具提示 (Tooltip)
   ============================================================ */
[data-tooltip] {
  position: relative;
  cursor: help;
}
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  padding: 6px 12px;
  background: var(--edos-bg-elevated, #252552);
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 0.75rem;
  border-radius: var(--edos-radius-sm, 6px);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--edos-transition-fast, 150ms ease);
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
  box-shadow: var(--edos-shadow-md, 0 4px 16px rgba(0,0,0,0.4));
  z-index: 9999;
}
[data-tooltip]:hover::after {
  opacity: 1;
}

/**
 * Edos AI — CSS 架构增强  v4.0
 * P6-10: CSS自定义属性 + 浅色主题 + 完整响应式 + 打印样式 + 无障碍
 */

/* ================================================================
   CSS 自定义属性 (Design Tokens)
   ================================================================ */
:root {
  /* 主色调 */
  --cyan: #38bdf8;
  --purple: #a78bfa;
  --pink: #f472b6;
  --green: #4ade80;
  --red: #f87171;
  --orange: #fb923c;

  /* 亮色主题 (默认) — 白底黑字现代风格 */
  --bg-deep: #ffffff;
  --bg-surface: #f8fafc;
  --bg-card: rgba(255, 255, 255, 0.92);
  --bg-elevated: rgba(255, 255, 255, 0.98);
  --bg-glass: rgba(255, 255, 255, 0.85);
  --bg-subtle: rgba(0, 0, 0, 0.03);
  --bg-hover: rgba(0, 0, 0, 0.06);
  --bg-pressed: rgba(0, 0, 0, 0.1);
  --input-bg: rgba(255, 255, 255, 0.95);
  --overlay-dark: rgba(0, 0, 0, 0.55);

  --text-main: #111827;
  --text-dim: #4b5563;
  --text-muted: #9ca3af;

  --border-subtle: rgba(0, 0, 0, 0.06);
  --border-glow: rgba(56, 189, 248, 0.15);
  --border-active: rgba(56, 189, 248, 0.5);

  --grad-cyan: linear-gradient(135deg, #38bdf8, #818cf8);
  --grad-hero: linear-gradient(135deg, #38bdf8 0%, #a78bfa 40%, #f472b6 80%);
  --grad-card: linear-gradient(135deg, rgba(56, 189, 248, 0.04), rgba(167, 139, 250, 0.04));

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
  --shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  --transition-fast: 0.15s ease;
  --transition-base: 0.25s ease;
  --transition-slow: 0.4s ease;

  /* 布局 */
  --navbar-height: 72px;
  --sidebar-width: 260px;
  --container-max: 1400px;

  /* 字体 */
  --font-sans: 'Inter', 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
}

/* ================================================================
   暗色主题 (prefers-color-scheme: dark) — 系统跟随
   ================================================================ */
@media (prefers-color-scheme: dark) {
  :root {
    --bg-deep: #ffffff;
    --bg-surface: #f8fafc;
    --bg-card: rgba(255, 255, 255, 0.92);
    --bg-elevated: rgba(255, 255, 255, 0.98);
    --bg-glass: rgba(255, 255, 255, 0.85);
    --bg-subtle: rgba(0, 0, 0, 0.03);
    --bg-hover: rgba(0, 0, 0, 0.06);
    --bg-pressed: rgba(0, 0, 0, 0.1);
    --input-bg: rgba(255, 255, 255, 0.95);
    --overlay-dark: rgba(0, 0, 0, 0.55);

    --text-main: #111827;
    --text-dim: #4b5563;
    --text-muted: #6b7280;

    --border-subtle: rgba(0, 0, 0, 0.06);
    --border-glow: rgba(56, 189, 248, 0.15);
    --border-active: rgba(56, 189, 248, 0.5);

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
    --shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
  }
}

/* ================================================================
   暗色主题强制类 (覆盖系统设置)
   ================================================================ */
[data-theme="dark"] {
  --bg-deep: #ffffff;
  --bg-surface: #f8fafc;
  --bg-card: rgba(255, 255, 255, 0.92);
  --bg-elevated: rgba(255, 255, 255, 0.98);
  --bg-glass: rgba(255, 255, 255, 0.85);
  --bg-subtle: rgba(0, 0, 0, 0.03);
  --bg-hover: rgba(0, 0, 0, 0.06);
  --bg-pressed: rgba(0, 0, 0, 0.1);
  --input-bg: rgba(255, 255, 255, 0.95);
  --overlay-dark: rgba(0, 0, 0, 0.55);
  --text-main: #111827;
  --text-dim: #4b5563;
  --text-muted: #6b7280;
  --border-subtle: rgba(0, 0, 0, 0.06);
  --border-glow: rgba(56, 189, 248, 0.15);
  --border-active: rgba(56, 189, 248, 0.5);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
  --shadow-glow: 0 0 20px rgba(56, 189, 248, 0.1);
}

/* 暗色主题 — 覆盖 styles.css 中硬编码的白色元素 */
[data-theme="dark"] body::before {
  background:
    radial-gradient(ellipse 70% 60% at 15% 5%, rgba(0,180,255,.05) 0%,transparent 55%),
    radial-gradient(ellipse 55% 50% at 80% 40%, rgba(139,92,246,.04) 0%,transparent 55%),
    radial-gradient(ellipse 60% 45% at 50% 90%, rgba(236,72,153,.03) 0%,transparent 55%);
}
[data-theme="dark"] body::after {
  background-image:
    linear-gradient(rgba(0,0,0,.03) 1px,transparent 1px),
    linear-gradient(90deg,rgba(0,0,0,.03) 1px,transparent 1px);
}
[data-theme="dark"] .navbar {
  background: rgba(255,255,255,.95);
  border-bottom-color: rgba(0,0,0,.08);
  box-shadow: 0 2px 12px rgba(0,0,0,.06);
}
[data-theme="dark"] .modal {
  background: rgba(0,0,0,.55);
}
[data-theme="dark"] .modal-content {
  background: rgba(255,255,255,.98);
  border-color: rgba(0,0,0,.08);
  box-shadow: 0 8px 32px rgba(0,0,0,.1);
}
[data-theme="dark"] input,
[data-theme="dark"] textarea,
[data-theme="dark"] select {
  background: rgba(255,255,255,.95);
  border-color: rgba(0,0,0,.1);
  color: var(--text-main);
}
[data-theme="dark"] input:focus,
[data-theme="dark"] textarea:focus,
[data-theme="dark"] select:focus {
  border-color: var(--cyan);
  box-shadow: 0 0 0 3px rgba(0,212,255,.1);
}
[data-theme="dark"] .sandbox-sidebar {
  background: rgba(248,250,252,.8);
  border-right-color: rgba(0,0,0,.06);
}
[data-theme="dark"] .card:hover {
  border-color: rgba(0,212,255,.3);
  box-shadow: 0 12px 40px rgba(0,0,0,.08), 0 0 20px rgba(56,189,248,.08);
}
[data-theme="dark"] .arch-row:hover {
  border-color: rgba(0,212,255,.3);
  box-shadow: 0 4px 20px rgba(0,0,0,.06);
}
/* 暗色 — 组件级覆盖 */
[data-theme="dark"] .sandbox-cv-btn { background:rgba(241,245,249,.6); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .ai .message-bubble { background:rgba(240,249,255,.7); border-color:rgba(0,212,255,.2); }
[data-theme="dark"] .message-bubble pre { background:#1e293b; border-color:rgba(100,150,220,.1); }
[data-theme="dark"] .message-bubble p code,
[data-theme="dark"] .message-bubble li code { background:rgba(0,0,0,.05); }
[data-theme="dark"] .chat-assistant .chat-bubble { background:rgba(240,249,255,.7); border-color:rgba(0,212,255,.2); }
[data-theme="dark"] .msg-action-btn { background:rgba(241,245,249,.8); border-color:rgba(0,0,0,.1); color:var(--text-dim); }
[data-theme="dark"] .img-context-menu { background:rgba(255,255,255,.98); border-color:rgba(0,0,0,.1); box-shadow:0 8px 32px rgba(0,0,0,.1); }
[data-theme="dark"] .img-ctx-item { color:#374151; }
[data-theme="dark"] .img-ctx-divider { background:rgba(0,0,0,.06); }
[data-theme="dark"] .toast-notify { background:rgba(255,255,255,.98); border-color:rgba(0,0,0,.1); color:#1f2937; box-shadow:0 8px 32px rgba(0,0,0,.1); }
[data-theme="dark"] .toast-notify.success { box-shadow:0 8px 32px rgba(0,0,0,.1),0 0 14px rgba(16,185,129,.1); }
[data-theme="dark"] .toast-notify.error { box-shadow:0 8px 32px rgba(0,0,0,.1),0 0 14px rgba(239,68,68,.1); }
[data-theme="dark"] .auth-tabs { background:rgba(241,245,249,.8); }
[data-theme="dark"] .confidence-bar { background:rgba(0,0,0,.06); }
[data-theme="dark"] .typing-indicator { background:rgba(240,249,255,.7); }
[data-theme="dark"] .ds-input-wrapper { background:rgba(248,250,252,.9); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .edit-textarea { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); color:#1f2937; }
[data-theme="dark"] .friend-item { background:rgba(248,250,252,.8); border-color:rgba(0,0,0,.06); }
[data-theme="dark"] footer { background:rgba(248,250,252,.8); border-top-color:rgba(0,0,0,.06); }
[data-theme="dark"] .video-card { background:linear-gradient(135deg,rgba(240,249,255,.9),rgba(245,243,255,.95)); border-color:rgba(0,0,0,.08); }
[data-theme="dark"] .video-card::before { background:radial-gradient(circle,rgba(0,212,255,.05) 0%,transparent 70%); }
[data-theme="dark"] .video-text h3 { color:#111827; }
[data-theme="dark"] .pricing-compare-table th { background:rgba(248,250,252,.8); }
[data-theme="dark"] .compare-no { color:rgba(0,0,0,.12); }
[data-theme="dark"] .usage-dash-footer { border-top-color:rgba(0,0,0,.04); }
[data-theme="dark"] .admin-tab { background:rgba(248,250,252,.8); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .quick-chat-section { background:linear-gradient(135deg,rgba(240,249,255,.8),rgba(245,243,255,.9)); border-color:rgba(0,0,0,.08); }
[data-theme="dark"] .quick-chat-section::before { background:radial-gradient(circle,rgba(0,212,255,.04) 0%,transparent 70%); }
[data-theme="dark"] .quick-chat-messages { background:rgba(248,250,252,.7); border-color:rgba(0,0,0,.06); }
[data-theme="dark"] .quick-msg.ai { background:rgba(240,249,255,.8); border-color:rgba(0,212,255,.2); }
[data-theme="dark"] .quick-chat-input-row textarea { background:rgba(248,250,252,.9); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .model-selector { background:rgba(248,250,252,.9); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .mp-tab-btn { background:rgba(241,245,249,.8); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .mp-card { background:rgba(248,250,252,.8); border-color:rgba(0,0,0,.06); }
[data-theme="dark"] .mp-card-name { color:#111827; }
[data-theme="dark"] .mp-card-desc { color:#6b7280; }
[data-theme="dark"] .sub-usage-item { background:rgba(248,250,252,.7); border-color:rgba(0,0,0,.06); }
[data-theme="dark"] .su-bar { background:rgba(0,0,0,.06); }
[data-theme="dark"] .edit-textarea:focus { box-shadow:0 0 0 3px rgba(0,212,255,.1); }
[data-theme="dark"] .quick-chat-input-row textarea:focus { box-shadow:0 0 0 3px rgba(0,212,255,.08); }
[data-theme="dark"] .pf-icon.no { color:rgba(0,0,0,.15); }
[data-theme="dark"] .roi-compare-table td { border-bottom-color:rgba(0,0,0,.04); }
[data-theme="dark"] .mp-card-footer { border-top-color:rgba(0,0,0,.04); }
[data-theme="dark"] .mp-detail-close { background:rgba(241,245,249,.8); }
[data-theme="dark"] .mp-detail-features li { border-bottom-color:rgba(0,0,0,.03); color:#6b7280; }
[data-theme="dark"] .ds-icon-btn:hover { background:rgba(0,212,255,.1); color:#1f2937; }
[data-theme="dark"] .mp-detail-modal { background:rgba(255,255,255,.98); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .hamburger-btn { background:rgba(248,250,252,.9); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .enterprise-form input,
[data-theme="dark"] .enterprise-form select,
[data-theme="dark"] .enterprise-form textarea { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .admin-table th { background:rgba(248,250,252,.8); }
[data-theme="dark"] .calc-row input[type="number"] { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .payment-order-summary { background:rgba(248,250,252,.9); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .payment-method-option { background:rgba(248,250,252,.8); border-color:rgba(0,0,0,.08); }
[data-theme="dark"] .payment-method-option:hover { border-color:rgba(0,212,255,.3); background:rgba(240,249,255,.8); }
[data-theme="dark"] .sub-current-card { background:rgba(248,250,252,.9); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .upgrade-nudge-toast { background:linear-gradient(135deg,rgba(240,249,255,.98),rgba(245,243,255,.98)); box-shadow:0 8px 40px rgba(0,0,0,.1),0 0 30px rgba(0,212,255,.08); }
[data-theme="dark"] .stock-search-bar input { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .stock-chat-input-row input { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .stock-msg.ai .stock-msg-bubble { background:rgba(240,249,255,.8); border-color:rgba(0,212,255,.2); }
[data-theme="dark"] .trading-select { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .trading-input-code,
[data-theme="dark"] .trading-input-price,
[data-theme="dark"] .trading-input-shares { background:rgba(248,250,252,.95); border-color:rgba(0,0,0,.1); }
[data-theme="dark"] .nav-overlay { background:rgba(0,0,0,.3); }
[data-theme="dark"] .nav-links { background:rgba(255,255,255,.98); border-color:rgba(0,0,0,.08); box-shadow:0 20px 60px rgba(0,0,0,.08); }
[data-theme="dark"] .pricing-card[data-plan="team"]:hover { box-shadow:0 8px 30px rgba(0,0,0,.06),0 0 25px rgba(52,211,153,.08); }
[data-theme="dark"] .pricing-card:hover { box-shadow:0 8px 30px rgba(0,0,0,.06); }
[data-theme="dark"] .pricing-compare-table td { border-bottom-color:rgba(0,0,0,.06); }
[data-theme="dark"] .concept-overlay { background:linear-gradient(transparent 0%,rgba(248,250,252,.92) 50%); }
[data-theme="dark"] .post-item:hover { box-shadow:0 4px 20px rgba(0,0,0,.06); }

[data-theme="light"] {
  --bg-deep: #ffffff;
  --bg-surface: #f8fafc;
  --bg-card: rgba(255, 255, 255, 0.92);
  --bg-elevated: rgba(255, 255, 255, 0.98);
  --bg-glass: rgba(255, 255, 255, 0.85);
  --text-main: #111827;
  --text-dim: #4b5563;
  --text-muted: #9ca3af;
  --border-subtle: rgba(0, 0, 0, 0.06);
  --border-glow: rgba(56, 189, 248, 0.15);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
}

/* ================================================================
   全局平滑滚动
   ================================================================ */
html {
  scroll-behavior: smooth;
}

/* ================================================================
   减少动画 (prefers-reduced-motion)
   ================================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(56, 189, 248, 0.15);
}

/* 去除鼠标点击时的焦点环（仅保留键盘导航） */
:focus:not(:focus-visible) {
  outline: none;
  box-shadow: none;
}

/* ================================================================
   密码可见性切换
   ================================================================ */
.pwd-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.pwd-wrap input {
  flex: 1;
}
.pwd-toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 1rem;
  line-height: 1;
  transition: color 0.2s, background 0.2s;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pwd-toggle:hover {
  color: var(--cyan);
  background: rgba(56, 189, 248, 0.08);
}
.pwd-toggle.showing {
  color: var(--cyan);
}
.pwd-toggle.showing i::before {
  content: "\f070"; /* fa-eye-slash */
}

/* ================================================================
   字符计数器
   ================================================================ */
.char-counter {
  display: block;
  text-align: right;
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-top: 3px;
  transition: color 0.2s;
  min-height: 16px;
}
.char-counter.near-limit { color: var(--orange); }
.char-counter.at-limit   { color: var(--red); font-weight: 600; }

/* ================================================================
   一键回到顶部
   ================================================================ */
#scrollToTopBtn {
  position: fixed;
  bottom: 28px;
  right: 28px;
  z-index: 9999;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(56, 189, 248, 0.3);
  background: rgba(10, 20, 45, 0.85);
  backdrop-filter: blur(12px);
  color: var(--cyan);
  font-size: 1.1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
  transition: opacity 0.3s, transform 0.3s, background 0.2s, box-shadow 0.2s;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}
#scrollToTopBtn.visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
#scrollToTopBtn:hover {
  background: rgba(20, 40, 80, 0.9);
  border-color: var(--cyan);
  box-shadow: 0 6px 24px rgba(56, 189, 248, 0.25);
  transform: translateY(-2px);
}
#scrollToTopBtn:active {
  transform: translateY(0) scale(0.95);
}

/* ================================================================
   按钮按下态增强
   ================================================================ */
.btn-primary:active {
  transform: scale(0.97) !important;
  box-shadow: 0 2px 8px rgba(59, 130, 246, 0.25) !important;
  transition: transform 0.08s ease, box-shadow 0.08s ease !important;
}
.btn-outline:active {
  transform: scale(0.97) !important;
  background: rgba(0, 180, 255, 0.18) !important;
  transition: transform 0.08s ease !important;
}
button:active:not(.btn-primary):not(.btn-outline):not(.pwd-toggle):not(.hamburger-btn) {
  transform: scale(0.96);
  transition: transform 0.06s ease;
}

/* ================================================================
   复制反馈 Toast
   ================================================================ */
.copy-toast {
  position: fixed;
  bottom: 80px;
  left: 50%;
  transform: translateX(-50%) translateY(10px);
  background: rgba(15, 30, 60, 0.95);
  backdrop-filter: blur(16px);
  border: 1px solid rgba(56, 189, 248, 0.3);
  color: var(--text-main);
  padding: 10px 22px;
  border-radius: 24px;
  font-size: 0.85rem;
  font-weight: 500;
  z-index: 100001;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s, transform 0.25s;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  gap: 8px;
}
.copy-toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.copy-toast .copy-toast-icon {
  color: var(--green);
  font-size: 1rem;
}

/* ================================================================
   打印样式
   ================================================================ */
@media print {
  * {
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;
  }

  body { font-size: 12pt; line-height: 1.5; }
  body::before, body::after { display: none !important; }

  .navbar, .nav-links, footer, .btn-primary, .btn-outline,
  .hero-badges, .chat-input-area, .modal, .toast,
  .ws-indicator, .floating-actions, .particles-canvas {
    display: none !important;
  }

  .page { display: block !important; animation: none !important; }
  .page:not(.active) { display: none !important; }

  .container { max-width: 100% !important; padding: 0 !important; }
  a[href]::after { content: " (" attr(href) ")"; font-size: 0.8em; }

  h1 { font-size: 24pt; }
  h2 { font-size: 18pt; }
  h3 { font-size: 14pt; }

  pre, code {
    border: 1px solid #ccc;
    background: #f5f5f5 !important;
    page-break-inside: avoid;
    white-space: pre-wrap;
    word-wrap: break-word;
  }

  table { border-collapse: collapse; width: 100%; }
  th, td { border: 1px solid #ccc; padding: 6px 10px; text-align: left; }
  thead { display: table-header-group; }

  img { max-width: 100% !important; page-break-inside: avoid; }
  .card, .glass-card { border: 1px solid #ccc !important; margin-bottom: 12pt; page-break-inside: avoid; }
}

/* ================================================================
   UX模块兼容性覆盖 — card-tilt 需禁用原有hover transform
   ================================================================ */
.card-tilt:hover { transform: none !important; }
.card-tilt:hover img { transform: none !important; }

/* ================================================================
   高对比度模式
   ================================================================ */
@media (prefers-contrast: high) {
  :root {
    --text-main: #ffffff;
    --text-dim: #e0e0e0;
    --text-muted: #b0b0b0;
    --border-glow: rgba(255, 255, 255, 0.3);
  }
}

/* ================================================================
   响应式断点细化
   ================================================================ */

/* 大屏优化 (≥1440px) */
@media (min-width: 1440px) {
  .container { max-width: 1400px; }
  .hero h1 { font-size: 3.5rem; }
  .card-grid { grid-template-columns: repeat(4, 1fr); }
  .sandbox-panel { flex-direction: row; }
}

/* 桌面 (1024px - 1439px) */
@media (min-width: 1024px) and (max-width: 1439px) {
  .container { max-width: 1200px; }
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}

/* 平板横屏 (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
  .container { max-width: 960px; padding: 0 20px; }
  .hero h1 { font-size: 2.4rem; }
  .hero-subtitle { font-size: 1rem; }
  .card-grid { grid-template-columns: repeat(2, 1fr); }
  .navbar { padding: 12px 20px; }
  .nav-links { gap: 12px; }
  .sandbox-panel { flex-direction: column; }
  .sidebar { width: var(--sidebar-width); }

  /* ===== 管理面板适配 ===== */
  .admin-stats { grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .admin-stat-card { padding: 16px; }
  .admin-stat-value { font-size: 1.5rem; }
  .admin-table { font-size: 0.85rem; }
  .admin-table th,
  .admin-table td { padding: 8px 10px; }
  .admin-table th:nth-child(5),
  .admin-table td:nth-child(5),
  .admin-table th:nth-child(6),
  .admin-table td:nth-child(6) { display: none; }

  /* ===== 仪表盘适配 ===== */
  .dashboard-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  .dashboard-card { padding: 20px; }
  .chart-container { max-height: 280px; }
  .dashboard-metrics { grid-template-columns: repeat(3, 1fr); }

  /* ===== 定价表适配 ===== */
  .pricing-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  .pricing-card.featured { transform: none; }
  .feature-comparison-table { font-size: 0.85rem; overflow-x: auto; }
  .feature-comparison-table th,
  .feature-comparison-table td { padding: 8px 10px; }

  /* ===== 模态框适配 ===== */
  .modal-content { width: 88vw; max-width: 680px; max-height: 85vh; border-radius: 16px; }
  .modal-body { padding: 20px 24px; }
  .modal-header { padding: 16px 24px; }

  /* ===== 表单适配 ===== */
  .form-row { flex-direction: column; gap: 12px; }
  .form-group.half { width: 100%; }
  textarea { min-height: 100px; }
}

/* 平板竖屏 / 大手机 (480px - 767px) */
@media (min-width: 480px) and (max-width: 767px) {
  .container { padding: 0 16px; }
  .hero { padding: 40px 0 24px; }
  .hero h1 { font-size: 2rem; }
  .hero-subtitle { font-size: 0.95rem; max-width: 400px; }
  .hero-badges { gap: 8px; }
  .hero-badge { padding: 4px 12px; font-size: 0.75rem; }
  .card-grid { grid-template-columns: 1fr; gap: 16px; }
  .navbar { flex-direction: column; border-radius: 0 0 16px 16px; }
  .nav-links { width: 100%; justify-content: center; flex-wrap: wrap; gap: 8px; }
  .nav-links a { font-size: 0.85rem; }
  .btn-primary, .btn-outline { padding: 6px 14px; font-size: 0.85rem; }
  .sandbox-panel { flex-direction: column; }
  .modal-content { width: 92vw; max-height: 85vh; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
}

/* 小手机 (< 480px) */
@media (max-width: 479px) {
  .container { padding: 0 10px; }
  .hero { padding: 32px 0 20px; }
  .hero h1 { font-size: 1.6rem; }
  .hero-subtitle { font-size: 0.85rem; }
  .hero-badges { flex-direction: column; align-items: center; gap: 6px; }
  .hero-badge { width: 100%; text-align: center; }
  .card-grid { grid-template-columns: 1fr; gap: 12px; }
  .navbar {
    flex-direction: column;
    padding: 10px 14px;
    border-radius: 0 0 12px 12px;
    margin: 0 -10px;
  }
  .nav-links { width: 100%; justify-content: center; flex-wrap: wrap; gap: 6px; }
  .nav-links a { font-size: 0.78rem; padding: 2px 6px; }
  .logo-text { font-size: 1.1rem; }
  .logo-svg { width: 36px; height: 36px; }
  .btn-primary, .btn-outline { padding: 5px 12px; font-size: 0.8rem; width: 100%; text-align: center; }
  .modal-content { width: 96vw; max-height: 90vh; border-radius: 12px; }
  .stats-grid { grid-template-columns: 1fr; }
  .chat-message { padding: 10px 14px; }
  .chat-input-area { padding: 10px; }
  .sandbox-panel { flex-direction: column; gap: 12px; }
  .card { padding: 16px; }
  pre, code { font-size: 0.75rem; max-width: 100%; overflow-x: auto; }
  table { font-size: 0.8rem; }
  input, textarea, select { font-size: 16px !important; } /* 防iOS缩放 */
}

/* ================================================================
   触摸设备优化
   ================================================================ */
@media (hover: none) and (pointer: coarse) {
  .btn-primary, .btn-outline, .nav-links a {
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  .card { cursor: default; }

  /* 增大触摸目标 */
  .nav-links a { padding: 8px 12px; }
}

/* ================================================================
   性能优化: GPU加速
   ================================================================ */
.glass-card, .card, .modal-content, .navbar {
  will-change: transform;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* ================================================================
   骨架屏动画
   ================================================================ */
@keyframes skeleton-loading {
  0% { background-position: -200px 0; }
  100% { background-position: calc(200px + 100%) 0; }
}

.skeleton {
  background: linear-gradient(
    90deg,
    var(--border-subtle) 25%,
    rgba(56, 189, 248, 0.05) 37%,
    var(--border-subtle) 63%
  );
  background-size: 200px 100%;
  animation: skeleton-loading 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

.skeleton-text { height: 14px; margin-bottom: 8px; }
.skeleton-title { height: 20px; width: 60%; margin-bottom: 16px; }
.skeleton-avatar { width: 48px; height: 48px; border-radius: 50%; }
.skeleton-card { height: 160px; border-radius: var(--radius-md); }

/* ================================================================
   焦点可见性 (键盘导航)
   ================================================================ */
:focus-visible {
  outline: 2px solid var(--cyan) !important;
  outline-offset: 2px !important;
  border-radius: 4px;
}

/* Skip to content link (屏幕阅读器) */
.skip-to-content {
  position: absolute;
  top: -100px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--cyan);
  color: #000;
  padding: 8px 20px;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  z-index: 10000;
  transition: top var(--transition-fast);
  font-weight: 600;
  text-decoration: none;
}

.skip-to-content:focus {
  top: 0;
}

/* ================================================================
   滚动条样式
   ================================================================ */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-surface); }
::-webkit-scrollbar-thumb {
  background: rgba(56, 189, 248, 0.2);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover { background: rgba(56, 189, 248, 0.35); }

/* Firefox */
* { scrollbar-width: thin; scrollbar-color: rgba(56, 189, 248, 0.2) var(--bg-surface); }

/* ================================================================
   动画工具类
   ================================================================ */
@keyframes shimmer {
  0% { background-position: -200% center; }
  100% { background-position: 200% center; }
}

@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0 8px rgba(56, 189, 248, 0.15); }
  50% { box-shadow: 0 0 20px rgba(56, 189, 248, 0.3); }
}

@keyframes slide-up {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slide-in-right {
  from { opacity: 0; transform: translateX(30px); }
  to { opacity: 1; transform: translateX(0); }
}

.animate-shimmer {
  background: linear-gradient(
    90deg, transparent, rgba(56, 189, 248, 0.08), transparent
  );
  background-size: 200% 100%;
  animation: shimmer 2s infinite;
}

.animate-pulse-glow { animation: pulse-glow 3s ease-in-out infinite; }
.animate-slide-up { animation: slide-up 0.4s ease-out forwards; }
.animate-slide-in-right { animation: slide-in-right 0.4s ease-out forwards; }

/* Staggered animation delays */
.stagger-1 { animation-delay: 0.05s; }
.stagger-2 { animation-delay: 0.1s; }
.stagger-3 { animation-delay: 0.15s; }
.stagger-4 { animation-delay: 0.2s; }
.stagger-5 { animation-delay: 0.25s; }

/* ================================================================
   v12: 客户身份分类系统 — UI 样式
   ================================================================ */

/* ---- 导航栏身份徽章 ---- */
.identity-badge-nav {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 10px; border-radius: 20px; font-size: 0.75rem;
    font-weight: 600; white-space: nowrap;
    background: rgba(10,20,50,.7); border: 1px solid rgba(100,140,220,.15);
    margin: 0 4px;
}
.identity-badge-nav .identity-badge { display: inline-flex; align-items: center; gap: 3px; }
.identity-badge-nav .identity-tier { font-size: 0.68rem; opacity: .8; }

/* ---- 身份卡片 ---- */
.identity-card {
    background: var(--bg-card); border-radius: 16px; padding: 20px;
    margin: 16px 0; border: 1px solid rgba(100,140,220,.08);
}
.identity-card-header { display: flex; align-items: center; gap: 12px; }
.identity-tier-badge {
    font-size: 0.7rem; padding: 2px 8px; border-radius: 12px; margin-left: 6px;
}
.identity-card-stats {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px;
}
.identity-stat {
    font-size: 0.78rem; color: var(--text-dim);
    background: rgba(10,20,50,.4); padding: 6px 10px; border-radius: 8px;
    display: flex; align-items: center; gap: 6px;
}
.identity-feature-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.identity-feature-tag {
    font-size: 0.68rem; padding: 2px 8px; border-radius: 10px;
    background: rgba(100,140,220,.08); color: var(--text-dim);
    border: 1px solid rgba(100,140,220,.1);
}

/* ---- 身份快捷操作入口 ---- */
.identity-quick-actions { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

/* ---- 开发者门户 ---- */
.dev-portal-container { max-width: 960px; margin: 0 auto; padding: 0 16px; }
.dev-portal-tabs {
    display: flex; gap: 4px; margin-bottom: 24px; flex-wrap: wrap;
    background: var(--bg-card); border-radius: 12px; padding: 4px;
    border: 1px solid rgba(100,140,220,.08);
}
.dev-portal-tab {
    padding: 8px 18px; border-radius: 10px; font-size: 0.85rem; font-weight: 500;
    color: var(--text-dim); background: none; border: none; cursor: pointer;
    transition: all .2s;
}
.dev-portal-tab:hover { color: var(--text-main); background: rgba(100,140,220,.06); }
.dev-portal-tab.active { color: var(--cyan); background: rgba(0,212,255,.1); font-weight: 600; }
.dev-portal-panel { display: none; }
.dev-portal-panel.active { display: block; }

/* 开发者门户 — 概览面板 */
.dev-overview-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px;
}
.dev-stat-card {
    background: var(--bg-card); border-radius: 14px; padding: 18px;
    border: 1px solid rgba(100,140,220,.08); text-align: center;
}
.dev-stat-value { font-size: 1.8rem; font-weight: 700; color: var(--cyan); }
.dev-stat-label { font-size: 0.78rem; color: var(--text-dim); margin-top: 4px; }

/* 开发者门户 — 应用卡片 */
.dev-app-card {
    background: var(--bg-card); border-radius: 14px; padding: 16px;
    border: 1px solid rgba(100,140,220,.08); margin-bottom: 12px;
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;
}
.dev-app-info h4 { margin: 0 0 4px; color: var(--text-main); }
.dev-app-info p { margin: 0; font-size: 0.8rem; color: var(--text-dim); }
.dev-app-actions { display: flex; gap: 6px; }
.dev-app-tags { display: flex; gap: 4px; margin-top: 6px; }
.dev-app-tag { font-size: 0.65rem; padding: 1px 8px; border-radius: 8px; background: rgba(96,165,250,.12); color: #60a5fa; }

/* 开发者门户 — API密钥 */
.dev-key-row {
    background: var(--bg-card); border-radius: 10px; padding: 12px 16px;
    border: 1px solid rgba(100,140,220,.08); margin-bottom: 8px;
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;
}
.dev-key-prefix { font-family: monospace; color: var(--cyan); font-size: 0.85rem; }
.dev-key-status { font-size: 0.7rem; padding: 2px 8px; border-radius: 8px; }
.dev-key-status.active { background: rgba(16,185,129,.15); color: var(--emerald); }
.dev-key-status.revoked { background: rgba(239,68,68,.15); color: #ef4444; }

/* 开发者门户 — API文档 */
.dev-api-section { margin-bottom: 20px; }
.dev-api-section h4 { color: var(--cyan); margin-bottom: 8px; }
.dev-api-endpoint {
    display: flex; align-items: center; gap: 10px; padding: 10px 14px;
    background: rgba(10,20,50,.5); border-radius: 8px; margin-bottom: 6px;
    font-family: monospace; font-size: 0.82rem;
}
.dev-api-method {
    font-weight: 700; font-size: 0.72rem; padding: 2px 8px; border-radius: 4px; min-width: 48px; text-align: center;
}
.dev-api-method.get { background: rgba(96,165,250,.15); color: #60a5fa; }
.dev-api-method.post { background: rgba(16,185,129,.15); color: #10b981; }
.dev-api-method.delete { background: rgba(239,68,68,.15); color: #ef4444; }
.dev-api-path { color: var(--text-main); }

/* 开发者门户 — 沙盒测试 */
.dev-sandbox-request {
    background: var(--bg-card); border-radius: 12px; padding: 16px;
    border: 1px solid rgba(100,140,220,.08); margin-bottom: 12px;
}
.dev-sandbox-response {
    background: rgba(10,20,50,.5); border-radius: 12px; padding: 16px;
    border: 1px solid rgba(100,140,220,.08); min-height: 80px;
    font-family: monospace; font-size: 0.8rem; white-space: pre-wrap; color: var(--text-dim);
}

/* ---- 企业控制台 ---- */
.ent-console-container { max-width: 960px; margin: 0 auto; padding: 0 16px; }
.ent-console-tabs {
    display: flex; gap: 4px; margin-bottom: 24px; flex-wrap: wrap;
    background: var(--bg-card); border-radius: 12px; padding: 4px;
    border: 1px solid rgba(100,140,220,.08);
}
.ent-console-tab {
    padding: 8px 18px; border-radius: 10px; font-size: 0.85rem; font-weight: 500;
    color: var(--text-dim); background: none; border: none; cursor: pointer;
    transition: all .2s;
}
.ent-console-tab:hover { color: var(--text-main); background: rgba(168,85,247,.06); }
.ent-console-tab.active { color: var(--purple); background: rgba(168,85,247,.12); font-weight: 600; }
.ent-console-panel { display: none; }
.ent-console-panel.active { display: block; }

/* 企业控制台 — 团队 */
.ent-team-card {
    background: var(--bg-card); border-radius: 14px; padding: 18px;
    border: 1px solid rgba(100,140,220,.08); margin-bottom: 12px;
}
.ent-member-row {
    display: flex; justify-content: space-between; align-items: center;
    padding: 8px 12px; border-radius: 8px; margin-bottom: 4px;
    background: rgba(10,20,50,.3);
}
.ent-member-role {
    font-size: 0.7rem; padding: 2px 8px; border-radius: 8px;
    background: rgba(168,85,247,.12); color: #a855f7;
}

/* 企业控制台 — 审计日志 */
.ent-audit-row {
    display: flex; gap: 12px; padding: 8px 12px; border-bottom: 1px solid rgba(100,140,220,.04);
    font-size: 0.82rem; align-items: center; flex-wrap: wrap;
}
.ent-audit-action {
    font-weight: 600; padding: 2px 8px; border-radius: 6px; font-size: 0.72rem;
}
.ent-audit-action.create { background: rgba(16,185,129,.1); color: #10b981; }
.ent-audit-action.update { background: rgba(96,165,250,.1); color: #60a5fa; }
.ent-audit-action.delete { background: rgba(239,68,68,.1); color: #ef4444; }
.ent-audit-action.login { background: rgba(168,85,247,.1); color: #a855f7; }
.ent-audit-time { color: var(--text-dim); font-size: 0.75rem; margin-left: auto; }

/* 企业控制台 — SSO配置 */
.ent-sso-card {
    background: var(--bg-card); border-radius: 14px; padding: 16px;
    border: 1px solid rgba(100,140,220,.08); margin-bottom: 10px;
    display: flex; justify-content: space-between; align-items: center;
}

/* 企业控制台 — 部署向导 */
.ent-deploy-step {
    display: flex; gap: 14px; padding: 14px;
    border-left: 3px solid rgba(168,85,247,.3); margin-bottom: 10px;
    background: var(--bg-card); border-radius: 0 12px 12px 0;
}
.ent-deploy-step-num {
    min-width: 32px; height: 32px; border-radius: 50%;
    background: rgba(168,85,247,.15); color: #a855f7;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 0.9rem;
}

/* 企业控制台 — 合规报告 */
.ent-report-card {
    background: var(--bg-card); border-radius: 14px; padding: 16px;
    border: 1px solid rgba(100,140,220,.08); margin-bottom: 10px;
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
}
.ent-report-score {
    font-size: 1.5rem; font-weight: 700; min-width: 60px; text-align: center;
}
.ent-report-score.good { color: #10b981; }
.ent-report-score.warn { color: #f59e0b; }
.ent-report-score.bad { color: #ef4444; }

/* ---- 产品体验层 — 升级提示横幅 ---- */
.upgrade-banner {
    position: fixed; top: 0; left: 0; right: 0; z-index: 999;
    background: linear-gradient(135deg, rgba(139,92,246,.95), rgba(0,212,255,.95));
    padding: 10px 20px; animation: slide-down .4s ease-out;
}
.upgrade-banner-content {
    max-width: 900px; margin: 0 auto; display: flex; align-items: center; gap: 12px;
    justify-content: center; flex-wrap: wrap;
}
.upgrade-banner-icon { font-size: 1.3rem; }
#upgradeBannerText { color: #fff; font-size: 0.9rem; font-weight: 500; }
.upgrade-banner-btn {
    padding: 6px 18px; border-radius: 20px; background: #fff; color: #7c3aed;
    border: none; font-weight: 700; font-size: 0.82rem; cursor: pointer;
}
.upgrade-banner-close {
    position: absolute; right: 16px; top: 50%; transform: translateY(-50%);
    background: none; border: none; color: rgba(255,255,255,.7); font-size: 1.4rem; cursor: pointer;
}

/* ---- 产品体验层 — 功能发现 ---- */
.feature-discovery-filters {
    display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px;
}
.fd-filter-btn {
    padding: 6px 14px; border-radius: 20px; font-size: 0.8rem; font-weight: 500;
    border: 1px solid rgba(100,140,220,.12); background: var(--bg-card); color: var(--text-dim);
    cursor: pointer; transition: all .2s;
}
.fd-filter-btn:hover { border-color: rgba(100,140,220,.3); color: var(--text-main); }
.fd-filter-btn.active { background: rgba(0,212,255,.12); color: var(--cyan); border-color: rgba(0,212,255,.3); }
.feature-discovery-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px;
}
.fd-card {
    background: var(--bg-card); border-radius: 12px; padding: 14px;
    border: 1px solid rgba(100,140,220,.06); cursor: pointer; transition: all .2s;
}
.fd-card:hover { border-color: rgba(100,140,220,.2); transform: translateY(-2px); }
.fd-card-icon { font-size: 1.6rem; margin-bottom: 6px; }
.fd-card-name { font-weight: 600; color: var(--text-main); font-size: 0.85rem; }
.fd-card-desc { font-size: 0.72rem; color: var(--text-dim); margin-top: 4px; }
.fd-card-locked { opacity: .45; cursor: not-allowed; }
.fd-card-locked:hover { transform: none; border-color: rgba(100,140,220,.06); }

/* ---- 产品体验层 — 积分任务 ---- */
.quest-section-title { color: var(--text-main); font-weight: 600; margin: 16px 0 8px; font-size: 0.9rem; }
.quest-item {
    display: flex; justify-content: space-between; align-items: center;
    padding: 10px 14px; background: var(--bg-card); border-radius: 10px;
    margin-bottom: 6px; border: 1px solid rgba(100,140,220,.06);
}
.quest-info { display: flex; align-items: center; gap: 10px; }
.quest-icon { font-size: 1.2rem; }
.quest-name { font-size: 0.84rem; color: var(--text-main); }
.quest-desc { font-size: 0.7rem; color: var(--text-dim); }
.quest-progress-bar {
    width: 80px; height: 6px; border-radius: 3px; background: rgba(100,140,220,.1); overflow: hidden;
}
.quest-progress-fill { height: 100%; background: var(--cyan); border-radius: 3px; transition: width .3s; }
.quest-claim-btn {
    padding: 4px 12px; border-radius: 8px; font-size: 0.72rem; border: none; cursor: pointer;
    background: rgba(16,185,129,.15); color: #10b981; font-weight: 600;
}
.quest-claim-btn.done { background: rgba(100,140,220,.08); color: var(--text-dim); cursor: default; }

/* ---- 产品体验层 — 交互式引导 ---- */
.onboarding-overlay {
    position: fixed; inset: 0; z-index: 10000; background: rgba(6,9,24,.85);
    display: flex; align-items: center; justify-content: center;
}
.onboarding-spotlight {
    position: absolute; border-radius: 12px;
    box-shadow: 0 0 0 9999px rgba(6,9,24,.75), 0 0 30px rgba(0,212,255,.3);
    pointer-events: none; transition: all .35s ease;
}
.onboarding-tooltip {
    position: relative; z-index: 1; max-width: 420px; width: 90%;
    background: var(--bg-card); border-radius: 16px; padding: 24px;
    border: 1px solid rgba(0,212,255,.2); text-align: center;
    animation: fade-in-up .4s ease-out;
}
.onboarding-tooltip h3 { color: var(--cyan); margin-bottom: 8px; font-size: 1.1rem; }
.onboarding-tooltip p { color: var(--text-dim); font-size: 0.85rem; margin-bottom: 16px; }
.onboarding-steps-dots { display: flex; gap: 6px; justify-content: center; margin-bottom: 16px; }
.onboarding-dot {
    width: 8px; height: 8px; border-radius: 50%; background: rgba(100,140,220,.2);
}
.onboarding-dot.active { background: var(--cyan); width: 20px; border-radius: 4px; }
.onboarding-actions { display: flex; gap: 8px; justify-content: center; }

/* ---- UI自适应过滤（identity系统使用） ---- */
[data-identity-hidden] { display: none !important; }

/* ---- v13: 管理员数据分析 & 问题监控面板样式 ---- */

/* 告警通知栏 */
.admin-alert-bar {
    background: linear-gradient(135deg, rgba(239,68,68,.12), rgba(245,158,11,.08));
    border: 1px solid rgba(239,68,68,.3);
    border-radius: 16px;
    padding: 14px 20px;
    margin-bottom: 16px;
    color: var(--text-main);
    font-size: 0.88rem;
    animation: alertPulse 2s ease-in-out infinite;
}
@keyframes alertPulse {
    0%, 100% { border-color: rgba(239,68,68,.3); }
    50% { border-color: rgba(239,68,68,.6); }
}

/* 问题状态标签 */
.issue-status-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 12px;
    font-size: 0.72rem;
    font-weight: 600;
}
.issue-status-badge.open {
    background: rgba(239,68,68,.12);
    color: #ef4444;
}
.issue-status-badge.investigating {
    background: rgba(245,158,11,.12);
    color: #f59e0b;
}
.issue-status-badge.resolved {
    background: rgba(16,185,129,.12);
    color: #10b981;
}
.issue-status-badge.closed {
    background: rgba(100,140,220,.1);
    color: var(--text-dim);
}
.issue-status-badge.wontfix {
    background: rgba(100,100,100,.1);
    color: #666;
}

/* 活跃度评分条 */
.activity-score-bar {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 10px;
    font-weight: 600;
    font-size: 0.78rem;
    background: linear-gradient(90deg,
        rgba(16,185,129,.15) 0%,
        rgba(59,130,246,.15) 50%,
        rgba(139,92,246,.15) 100%
    );
    color: var(--cyan);
    min-width: 30px;
    text-align: center;
}

/* 图表容器 */
.admin-chart-box {
    position: relative;
}
.admin-chart-box canvas {
    max-height: 220px;
}

/* 管理后台标签页增强 */
.admin-tab[data-admin-tab="analytics"]:hover,
.admin-tab[data-admin-tab="monitor"]:hover {
    background: rgba(139,92,246,.12) !important;
    border-color: rgba(139,92,246,.3) !important;
}
.admin-tab[data-admin-tab="analytics"].active {
    background: linear-gradient(135deg, #3b82f6, #8b5cf6) !important;
    box-shadow: 0 0 20px rgba(139,92,246,.3) !important;
}
.admin-tab[data-admin-tab="monitor"].active {
    background: linear-gradient(135deg, #ef4444, #f59e0b) !important;
    box-shadow: 0 0 20px rgba(239,68,68,.3) !important;
}

/* 负面关键词标签 */
.keyword-tag {
    display: inline-block;
    margin: 1px 2px;
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 0.7rem;
    background: rgba(239,68,68,.1);
    color: #ef4444;
    white-space: nowrap;
}

/* 禁用按钮样式 */
.admin-action-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

/* 监控面板筛选按钮 */
.admin-monitor-filter {
    font-size: 0.75rem !important;
    padding: 4px 12px !important;
}

/* ---- v13.1: 增强样式 ---- */

/* 日期范围选择器 */
.admin-date-range {
    display: flex;
    gap: 6px;
    align-items: center;
}
.admin-date-range input[type="date"] {
    padding: 6px 12px;
    border: 1px solid rgba(100,140,220,.25);
    border-radius: 10px;
    background: rgba(10,16,40,.6);
    color: var(--text-main);
    font-size: 0.8rem;
    font-family: inherit;
    outline: none;
}
.admin-date-range input[type="date"]:focus {
    border-color: var(--cyan);
}

/* 问题搜索输入框 */
.admin-issue-search {
    padding: 8px 16px;
    border: 1px solid rgba(100,140,220,.25);
    border-radius: 20px;
    background: rgba(10,16,40,.6);
    color: var(--text-main);
    font-size: 0.82rem;
    font-family: inherit;
    outline: none;
    width: 220px;
    transition: all 0.25s;
}
.admin-issue-search:focus {
    border-color: var(--cyan);
    box-shadow: 0 0 0 3px rgba(0,212,255,.1);
}

/* 批量操作栏 */
.admin-batch-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: rgba(59,130,246,.06);
    border: 1px solid rgba(59,130,246,.15);
    border-radius: 12px;
    margin-bottom: 12px;
    font-size: 0.82rem;
}
.admin-batch-bar .batch-count {
    color: var(--cyan);
    font-weight: 600;
}

/* 复选框列 */
.admin-check-col {
    width: 36px;
    text-align: center;
}
.admin-check-col input[type="checkbox"] {
    accent-color: var(--cyan);
    cursor: pointer;
    width: 16px;
    height: 16px;
}

/* 面包屑导航 */
.admin-breadcrumb {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.78rem;
    color: var(--text-dim);
    margin-bottom: 16px;
}
.admin-breadcrumb a {
    color: var(--cyan);
    text-decoration: none;
    cursor: pointer;
}
.admin-breadcrumb a:hover {
    text-decoration: underline;
}

/* 刷新计时器 */
.admin-refresh-timer {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.72rem;
    color: var(--text-dim);
}
.admin-refresh-timer .countdown {
    color: var(--cyan);
    font-weight: 600;
}

/* 严重度指示器点 */
.severity-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: 4px;
}
.severity-dot.critical { background: #ef4444; box-shadow: 0 0 6px rgba(239,68,68,.5); }
.severity-dot.high { background: #f59e0b; box-shadow: 0 0 6px rgba(245,158,11,.5); }
.severity-dot.medium { background: #3b82f6; box-shadow: 0 0 6px rgba(59,130,246,.5); }
.severity-dot.low { background: #10b981; box-shadow: 0 0 6px rgba(16,185,129,.5); }

/* 弹窗中问题详情样式 */
.issue-detail-section {
    margin-bottom: 12px;
}
.issue-detail-section strong {
    color: var(--text-dim);
    font-size: 0.78rem;
    display: block;
    margin-bottom: 4px;
}
.issue-detail-section .detail-value {
    color: var(--text-main);
    font-size: 0.9rem;
}

/* 饼图容器 */
.admin-pie-chart-box {
    position: relative;
    max-height: 240px;
}

/* 标签页增强 - 概览 */
.admin-tab[data-admin-tab="overview"].active {
    background: linear-gradient(135deg, #06b6d4, #3b82f6) !important;
    box-shadow: 0 0 20px rgba(6,182,212,.3) !important;
}

/* 导出下拉菜单 */
.admin-export-dropdown {
    position: relative;
    display: inline-block;
}
.admin-export-menu {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 6px;
    background: var(--bg-card);
    border: 1px solid var(--border-glow);
    border-radius: 12px;
    padding: 6px;
    min-width: 160px;
    box-shadow: 0 8px 32px rgba(0,0,0,.4);
    z-index: 100;
    display: none;
}
.admin-export-menu.show { display: block; }
.admin-export-menu button {
    display: block;
    width: 100%;
    padding: 8px 14px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text-main);
    font-size: 0.82rem;
    cursor: pointer;
    text-align: left;
    transition: all 0.2s;
    font-family: inherit;
}
.admin-export-menu button:hover {
    background: rgba(59,130,246,.12);
    color: var(--cyan);
}

/* ---- v13.2 响应式 ---- */
@media (max-width: 768px) {
    .dev-portal-tabs, .ent-console-tabs { overflow-x: auto; flex-wrap: nowrap; }
    .dev-portal-tab, .ent-console-tab { white-space: nowrap; font-size: 0.78rem; padding: 6px 12px; }
    .dev-overview-grid { grid-template-columns: repeat(2, 1fr); }
    .identity-card-stats { grid-template-columns: 1fr; }
    .feature-discovery-grid { grid-template-columns: repeat(2, 1fr); }
    .upgrade-banner-content { flex-direction: column; gap: 6px; }
    .admin-stats { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
    .admin-alert-bar { font-size: 0.78rem; }
    .admin-chart-box canvas { max-height: 160px; }
    /* v13.2: 面板布局适配 */
    .admin-header-row { flex-direction: column; gap: 8px; align-items: flex-start; }
    .admin-date-range { flex-wrap: wrap; }
    .admin-issue-search { width: 100%; max-width: none; }
    .admin-batch-bar { flex-wrap: wrap; gap: 6px; }
    .admin-export-dropdown { position: relative; }
    /* 饼图在小屏幕上缩小 */
    .admin-pie-chart-box canvas { max-height: 180px; }
    /* 表格横向滚动 */
    .admin-table-wrapper, div[style*="overflow-x:auto"] { -webkit-overflow-scrolling: touch; }
    /* 刷新计时器隐藏文字只显示倒计时 */
    .admin-refresh-timer { font-size: 0.7rem; }
}

/* v13.2: 小屏手机 (<480px) 增强 */
@media (max-width: 480px) {
    .admin-stats { grid-template-columns: 1fr 1fr; gap: 8px; }
    .admin-stat-card { padding: 12px; }
    .admin-stat-card h4 { font-size: 0.72rem; }
    .admin-stat-card p { font-size: 1rem; }
    .admin-stat-icon { width: 32px; height: 32px; font-size: 0.85rem; }
    /* 面板内图表两列变一列 */
    div[style*="grid-template-columns:1fr 1fr"] { grid-template-columns: 1fr !important; }
    .admin-table { font-size: 0.72rem; }
    .admin-table th, .admin-table td { padding: 6px 8px; }
    .admin-action-btn { font-size: 0.65rem; padding: 3px 8px; }
    .admin-tab { font-size: 0.68rem; padding: 4px 8px; }
    .admin-alert-bar { padding: 10px 14px; }
    .admin-alert-bar button { font-size: 0.68rem; padding: 4px 10px; }
    /* 导出菜单适配 */
    .admin-export-menu button { font-size: 0.72rem; padding: 8px 14px; }
}

/* ============================================================
   打字指示器 (Typing Indicator) - v1.0.0
   ============================================================ */
.chat-message.typing .chat-bubble {
    background: rgba(10, 16, 40, 0.7);
    border: 1px solid rgba(0, 212, 255, 0.15);
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 20px;
    animation: pulse-glow-typing 1.5s ease-in-out infinite;
}

@keyframes pulse-glow-typing {
    0%, 100% { box-shadow: 0 0 8px rgba(0, 212, 255, 0.05); }
    50% { box-shadow: 0 0 18px rgba(0, 212, 255, 0.15); }
}

.typing-dots {
    display: inline-flex;
    gap: 3px;
    align-items: center;
}

.typing-dots span {
    display: inline-block;
    width: 6px;
    height: 6px;
    background: var(--cyan);
    border-radius: 50%;
    animation: typingBounce 1.2s infinite;
}

.typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.typing-dots span:nth-child(3) { animation-delay: 0.4s; }

@keyframes typingBounce {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
    30% { transform: translateY(-6px); opacity: 1; }
}

.typing-text {
    position: relative;
    display: inline-block;
    min-width: 150px;
    font-size: 0.82rem;
    color: var(--cyan);
    font-style: italic;
}

.typing-text-item {
    position: absolute;
    left: 0;
    top: 0;
    white-space: nowrap;
    opacity: 0;
    animation: typingCycle 3.2s infinite;
    animation-delay: calc(var(--typing-i, 0) * 0.8s);
}

@keyframes typingCycle {
    0%, 20% { opacity: 1; }
    25%, 100% { opacity: 0; }
}

/* 聊天搜索栏 */
.chat-search-bar {
    display: none;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    margin: 0 0 10px 0;
    background: rgba(10, 16, 40, 0.7);
    border: 1px solid rgba(0, 212, 255, 0.2);
    border-radius: 12px;
    animation: fadeInDown 0.25s ease;
}

.chat-search-bar.visible {
    display: flex;
}

@keyframes fadeInDown {
    from { opacity: 0; transform: translateY(-8px); }
    to { opacity: 1; transform: translateY(0); }
}

.chat-search-bar input {
    flex: 1;
    background: transparent;
    border: none;
    color: var(--text-main);
    font-size: 0.85rem;
    outline: none;
    font-family: inherit;
    min-width: 0;
}

.chat-search-bar input::placeholder {
    color: var(--text-dim);
}

.chat-search-bar .search-count {
    font-size: 0.72rem;
    color: var(--cyan);
    white-space: nowrap;
    min-width: 50px;
    text-align: right;
}

.chat-search-bar .search-nav-btn {
    background: rgba(0, 212, 255, 0.1);
    border: 1px solid rgba(0, 212, 255, 0.15);
    color: var(--cyan);
    width: 28px;
    height: 28px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    font-family: inherit;
    line-height: 1;
}

.chat-search-bar .search-nav-btn:hover {
    background: rgba(0, 212, 255, 0.2);
}

.chat-search-bar .search-close-btn {
    background: transparent;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
    font-size: 1rem;
    padding: 2px 6px;
    border-radius: 4px;
    transition: all 0.2s;
    line-height: 1;
}

.chat-search-bar .search-close-btn:hover {
    color: #ef4444;
    background: rgba(239, 68, 68, 0.1);
}

/* 聊天消息搜索高亮 */
.chat-message .search-highlight {
    background: rgba(245, 158, 11, 0.3);
    border-radius: 2px;
    padding: 0 1px;
    color: #fbbf24;
}

.chat-message.search-match {
    border-left: 3px solid rgba(0, 212, 255, 0.5);
    padding-left: 8px;
}

.chat-message.search-match-active {
    border-left: 3px solid var(--cyan);
    background: rgba(0, 212, 255, 0.05);
    padding-left: 8px;
}

/* 消息模型标签 */
.msg-model-tag {
    display: inline-block;
    font-size: 0.65rem;
    padding: 1px 6px;
    border-radius: 4px;
    margin-left: 6px;
    background: rgba(0, 212, 255, 0.1);
    color: rgba(0, 212, 255, 0.7);
    vertical-align: middle;
}

/* 重试按钮样式 */
.msg-retry-btn {
    background: rgba(245, 158, 11, 0.1);
    border: 1px solid rgba(245, 158, 11, 0.2);
    color: #f59e0b;
    cursor: pointer;
    font-size: 0.72rem;
    padding: 4px 12px;
    border-radius: 6px;
    font-family: inherit;
    transition: all 0.2s;
}

.msg-retry-btn:hover {
    background: rgba(245, 158, 11, 0.2);
}

/* 聊天工具栏 */
.chat-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 14px;
    margin-bottom: 8px;
    background: rgba(10, 16, 40, 0.4);
    border: 1px solid rgba(100, 140, 220, 0.08);
    border-radius: 10px;
    flex-shrink: 0;
}

.chat-toolbar-title {
    font-size: 0.78rem;
    color: var(--text-dim);
    font-weight: 500;
}

.chat-toolbar-actions {
    display: flex;
    gap: 4px;
}

.chat-toolbar-btn {
    width: 30px;
    height: 30px;
    border: 1px solid rgba(100, 140, 220, 0.1);
    border-radius: 6px;
    background: rgba(10, 16, 40, 0.5);
    color: var(--text-dim);
    cursor: pointer;
    font-size: 0.8rem;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    font-family: inherit;
    line-height: 1;
}

.chat-toolbar-btn:hover {
    background: rgba(0, 212, 255, 0.1);
    border-color: rgba(0, 212, 255, 0.2);
    color: var(--cyan);
}

.chat-toolbar-btn.active {
    background: rgba(0, 212, 255, 0.15);
    border-color: rgba(0, 212, 255, 0.35);
    color: var(--cyan);
}

/* Token消耗显示 */
.chat-cost-display {
    font-size: 0.7rem;
    color: var(--text-dim);
    background: rgba(10, 16, 40, 0.5);
    border: 1px solid rgba(100, 140, 220, 0.06);
    border-radius: 20px;
    padding: 3px 12px;
    white-space: nowrap;
    flex-shrink: 0;
    transition: all 0.25s;
}

.chat-cost-display:hover {
    border-color: rgba(0, 212, 255, 0.2);
    color: var(--text-main);
}

/* ============================================================
   会话列表面板 (v3.0)
   ============================================================ */
.session-list-panel {
    position: fixed;
    top: 0;
    right: -420px;
    width: 400px;
    max-width: 90vw;
    height: 100vh;
    background: var(--bg-glass);
    backdrop-filter: blur(30px);
    -webkit-backdrop-filter: blur(30px);
    border-left: 1px solid var(--border-glow);
    z-index: 1000;
    display: flex;
    flex-direction: column;
    box-shadow: -8px 0 40px rgba(0, 0, 0, 0.4);
    transition: right 0.35s cubic-bezier(0.4, 0, 0.2, 1);
    overflow: hidden;
}

.session-list-panel.visible {
    right: 0;
}

.session-panel-header {
    padding: 16px 18px 12px;
    border-bottom: 1px solid rgba(100, 140, 220, 0.08);
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex-shrink: 0;
}

.session-panel-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px;
}

.session-panel-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-main);
    display: flex;
    align-items: center;
    gap: 8px;
}

.session-panel-stats {
    display: flex;
    gap: 10px;
    font-size: 0.68rem;
    color: var(--text-dim);
    white-space: nowrap;
}

.session-panel-stats span {
    display: flex;
    align-items: center;
    gap: 3px;
}

.session-panel-new-btn {
    width: 100%;
    padding: 10px 16px;
    background: var(--grad-cyan);
    color: #fff;
    border: none;
    border-radius: 10px;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: all 0.25s;
    font-family: inherit;
    box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3);
}

.session-panel-new-btn:hover {
    box-shadow: 0 6px 24px rgba(59, 130, 246, 0.5);
    transform: translateY(-1px);
}

/* 会话搜索栏 */
.session-search-bar {
    padding: 10px 18px;
    border-bottom: 1px solid rgba(100, 140, 220, 0.06);
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex-shrink: 0;
}

.session-search-input {
    width: 100%;
    padding: 8px 14px;
    background: rgba(10, 16, 40, 0.5);
    border: 1px solid rgba(100, 140, 220, 0.12);
    border-radius: 8px;
    color: var(--text-main);
    font-size: 0.82rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.25s;
    box-sizing: border-box;
}

.session-search-input:focus {
    border-color: rgba(0, 212, 255, 0.4);
    box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.06);
}

.session-search-input::placeholder {
    color: var(--text-dim);
    opacity: 0.6;
}

.session-filter-tabs {
    display: flex;
    gap: 6px;
}

.session-filter-tab {
    padding: 4px 12px;
    border-radius: 16px;
    border: 1px solid rgba(100, 140, 220, 0.1);
    background: transparent;
    color: var(--text-dim);
    font-size: 0.7rem;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.2s;
    white-space: nowrap;
}

.session-filter-tab:hover {
    background: rgba(0, 212, 255, 0.06);
    border-color: rgba(0, 212, 255, 0.2);
    color: var(--text-main);
}

.session-filter-tab.active {
    background: rgba(0, 212, 255, 0.12);
    border-color: rgba(0, 212, 255, 0.35);
    color: var(--cyan);
    font-weight: 600;
}

/* 会话列表主体 */
.session-list-body {
    flex: 1;
    overflow-y: auto;
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.session-list-body::-webkit-scrollbar {
    width: 4px;
}

.session-list-body::-webkit-scrollbar-thumb {
    background: rgba(100, 140, 220, 0.15);
    border-radius: 2px;
}

.session-list-empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    color: var(--text-dim);
    text-align: center;
    gap: 8px;
}

.session-empty-icon {
    font-size: 2.5rem;
    opacity: 0.4;
}

/* 单个会话项 */
.session-item {
    display: flex;
    align-items: stretch;
    gap: 8px;
    padding: 10px 12px;
    border-radius: 12px;
    cursor: pointer;
    transition: all 0.2s;
    border: 1px solid transparent;
    background: transparent;
    position: relative;
}

.session-item:hover {
    background: rgba(0, 180, 255, 0.05);
    border-color: rgba(0, 212, 255, 0.1);
}

.session-item.active {
    background: rgba(0, 212, 255, 0.08);
    border-color: rgba(0, 212, 255, 0.25);
    box-shadow: 0 0 12px rgba(0, 212, 255, 0.06);
}

.session-item.pinned {
    border-left: 2px solid rgba(0, 212, 255, 0.3);
}

.session-item.starred {
    border-left: 2px solid rgba(255, 215, 0, 0.3);
}

.session-item.starred.pinned {
    border-left: 2px solid rgba(0, 212, 255, 0.3);
}

.session-item-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.session-item-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}

.session-item-name {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
    min-width: 0;
}

.session-item.active .session-item-name {
    color: var(--cyan);
}

.session-item-time {
    font-size: 0.65rem;
    color: var(--text-dim);
    white-space: nowrap;
    flex-shrink: 0;
    opacity: 0.7;
}

.session-item-meta {
    display: flex;
    align-items: center;
}

.session-item-preview {
    font-size: 0.7rem;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0.65;
    max-width: 100%;
}

.session-item-footer {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.65rem;
    color: var(--text-dim);
    opacity: 0.6;
}

.session-item-badge.star-badge {
    color: #fbbf24;
    opacity: 1;
    font-size: 0.7rem;
}

.session-item-actions {
    display: flex;
    flex-direction: column;
    gap: 2px;
    opacity: 0;
    transition: opacity 0.2s;
    flex-shrink: 0;
    justify-content: center;
}

.session-item:hover .session-item-actions,
.session-item.active .session-item-actions {
    opacity: 1;
}

.session-item-btn {
    width: 26px;
    height: 26px;
    border: 1px solid rgba(100, 140, 220, 0.08);
    border-radius: 6px;
    background: rgba(10, 16, 40, 0.4);
    color: var(--text-dim);
    cursor: pointer;
    font-size: 0.7rem;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    padding: 0;
    line-height: 1;
}

.session-item-btn:hover {
    background: rgba(0, 212, 255, 0.1);
    border-color: rgba(0, 212, 255, 0.25);
    color: var(--cyan);
}

.session-item-delete:hover {
    background: rgba(255, 71, 87, 0.12);
    border-color: rgba(255, 71, 87, 0.3);
    color: #ff4757;
}

/* 右键菜单 */
.session-context-menu {
    position: fixed;
    z-index: 2000;
    min-width: 180px;
    background: var(--bg-glass);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    border: 1px solid rgba(100, 140, 220, 0.12);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
    padding: 6px;
    animation: ctxMenuIn 0.15s ease;
}

@keyframes ctxMenuIn {
    from { opacity: 0; transform: scale(0.95) translateY(-4px); }
    to { opacity: 1; transform: scale(1) translateY(0); }
}

.session-context-item {
    padding: 8px 14px;
    font-size: 0.78rem;
    color: var(--text-dim);
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.15s;
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: inherit;
}

.session-context-item:hover {
    background: rgba(0, 212, 255, 0.08);
    color: var(--text-main);
}

.session-context-danger {
    color: #ff6b7a;
}

.session-context-danger:hover {
    background: rgba(255, 71, 87, 0.1);
    color: #ff4757;
}

.session-context-divider {
    height: 1px;
    background: rgba(100, 140, 220, 0.08);
    margin: 4px 6px;
}

/* 聊天消息空状态 */
.chat-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-dim);
    font-size: 0.9rem;
    text-align: center;
    padding: 60px 20px;
    line-height: 1.6;
}

/* 移动端适配 */
@media (max-width: 768px) {
    .session-list-panel {
        width: 100vw;
        max-width: 100vw;
        right: -100vw;
    }

    .chat-toolbar {
        flex-wrap: wrap;
        gap: 6px;
    }

    .chat-cost-display {
        font-size: 0.65rem;
        padding: 2px 8px;
    }

    .session-item-actions {
        opacity: 0.5;
    }
}

/* 消息时间戳 */
.msg-timestamp {
    display: block;
    font-size: 0.65rem;
    color: var(--text-dim);
    margin-top: 4px;
    opacity: 0.5;
    transition: opacity 0.2s;
}

.chat-message:hover .msg-timestamp {
    opacity: 0.8;
}

/* 键盘快捷键提示 */
.kbd-shortcut {
    display: inline-block;
    font-size: 0.65rem;
    padding: 1px 5px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: var(--text-dim);
    font-family: monospace;
    margin: 0 2px;
}

/* ================================================================
   管理面板通用工具类 — 减少内联样式膨胀
   ================================================================ */
.admin-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 14px;
    margin: 16px 0;
}

.admin-card {
    background: rgba(10, 16, 40, 0.6);
    border: 1px solid rgba(100, 140, 220, 0.12);
    border-radius: 16px;
    padding: 24px;
    margin: 16px 0;
}

.admin-flex-center {
    display: flex;
    justify-content: center;
    align-items: flex-end;
    gap: 12px;
}

.admin-section-title {
    color: var(--text-main);
    margin: 0 0 16px;
    text-align: center;
}

.admin-search-input {
    width: 100%;
    max-width: 280px;
    background: rgba(10, 16, 40, 0.8);
    border: 1px solid rgba(100, 140, 220, 0.2);
    border-radius: 8px;
    padding: 9px 14px;
    color: var(--text-main);
    font-size: 0.85rem;
    transition: border-color 0.2s;
}

.admin-search-input:focus {
    outline: none;
    border-color: var(--cyan);
    box-shadow: 0 0 0 2px rgba(0, 212, 255, 0.15);
}

.admin-filter-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 16px;
}

.admin-filter-select {
    background: rgba(10, 16, 40, 0.8);
    border: 1px solid rgba(100, 140, 220, 0.2);
    border-radius: 8px;
    padding: 8px 12px;
    color: var(--text-main);
    font-size: 0.83rem;
    cursor: pointer;
}

/* ================================================================
   v1.0.0: 首页增强组件 - 客户评价 / 集成生态 / 路线图 / 里程碑
   ================================================================ */

/* ---- 客户评价网格 ---- */
.testimonials-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
    gap: 16px;
    margin: 0 0 24px;
}

.testimonial-card {
    background: var(--bg-card);
    border-radius: 16px;
    padding: 24px;
    border: 1px solid var(--border-subtle);
    border-left: 4px solid var(--cyan);
    transition: all var(--transition-base);
    position: relative;
    overflow: hidden;
}

.testimonial-card::before {
    content: '\201C';
    position: absolute;
    top: -10px;
    left: 16px;
    font-size: 72px;
    color: rgba(56, 189, 248, 0.08);
    line-height: 1;
    font-family: Georgia, serif;
}

.testimonial-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md), var(--shadow-glow);
    border-left-color: var(--purple);
}

.testimonial-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}

.testimonial-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: linear-gradient(135deg, rgba(56,189,248,.15), rgba(168,85,247,.15));
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.6rem;
    flex-shrink: 0;
}

.testimonial-name {
    font-weight: 600;
    color: var(--text-main);
    font-size: .92rem;
}

.testimonial-title {
    font-size: .72rem;
    color: var(--text-dim);
}

.testimonial-content {
    font-size: .88rem;
    color: var(--text-main);
    line-height: 1.7;
    font-style: italic;
    margin-bottom: 14px;
}

.testimonial-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.testimonial-rating {
    color: #f59e0b;
    font-size: .85rem;
    letter-spacing: 2px;
}

.testimonial-industry {
    font-size: .72rem;
    padding: 3px 10px;
    border-radius: 20px;
    background: rgba(56,189,248,.08);
    color: var(--cyan);
    font-weight: 500;
}

/* ---- 集成生态网格 ---- */
.integrations-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
    margin: 0 0 24px;
}

.integration-card {
    background: var(--bg-card);
    border-radius: 14px;
    padding: 18px;
    border: 1px solid var(--border-subtle);
    text-align: center;
    transition: all var(--transition-base);
    cursor: default;
}

.integration-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
    border-color: var(--border-glow);
}

.integration-card .int-icon {
    font-size: 2rem;
    margin-bottom: 10px;
}

.integration-card .int-name {
    font-weight: 600;
    color: var(--text-main);
    font-size: .88rem;
    margin-bottom: 4px;
}

.integration-card .int-desc {
    font-size: .75rem;
    color: var(--text-dim);
    margin-bottom: 8px;
}

.integration-card .int-status {
    font-size: .7rem;
    padding: 3px 12px;
    border-radius: 20px;
    background: rgba(16, 185, 129, .1);
    color: var(--green);
    font-weight: 600;
    display: inline-block;
}

/* ---- 路线图时间线 ---- */
.roadmap-section {
    max-width: 800px;
    margin: 0 auto 24px;
    padding: 0 16px;
}

.roadmap-item {
    display: flex;
    gap: 16px;
    padding: 16px;
    background: var(--bg-card);
    border-radius: 14px;
    border: 1px solid var(--border-subtle);
    margin-bottom: 12px;
    transition: all var(--transition-base);
    position: relative;
}

.roadmap-item:hover {
    border-color: var(--border-glow);
    box-shadow: var(--shadow-sm);
}

.roadmap-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    margin-top: 4px;
    flex-shrink: 0;
}

.roadmap-dot.in-progress { background: #3b82f6; box-shadow: 0 0 12px rgba(59,130,246,.4); }
.roadmap-dot.planned { background: #a855f7; box-shadow: 0 0 12px rgba(168,85,247,.4); }
.roadmap-dot.design { background: #f59e0b; box-shadow: 0 0 12px rgba(245,158,11,.4); }

.roadmap-content { flex: 1; }

.roadmap-header {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

.roadmap-icon {
    font-size: 1.4rem;
}

.roadmap-title {
    font-weight: 600;
    color: var(--text-main);
    font-size: .92rem;
}

.roadmap-quarter {
    font-size: .72rem;
    padding: 2px 10px;
    border-radius: 12px;
    font-weight: 600;
    margin-left: auto;
}
.roadmap-quarter.q3-2026 { background: rgba(59,130,246,.12); color: #3b82f6; }
.roadmap-quarter.q4-2026 { background: rgba(168,85,247,.12); color: #a855f7; }
.roadmap-quarter.q1-2027 { background: rgba(236,72,153,.12); color: #ec4899; }

.roadmap-desc {
    font-size: .82rem;
    color: var(--text-dim);
    margin-bottom: 10px;
}

.roadmap-status-badge {
    font-size: .68rem;
    padding: 3px 10px;
    border-radius: 12px;
    font-weight: 600;
    display: inline-block;
    margin-bottom: 8px;
}

.roadmap-status-badge.in-progress { background: rgba(59,130,246,.12); color: #3b82f6; }
.roadmap-status-badge.planned { background: rgba(168,85,247,.12); color: #a855f7; }
.roadmap-status-badge.design { background: rgba(245,158,11,.12); color: #f59e0b; }

.roadmap-progress-bar {
    height: 6px;
    border-radius: 3px;
    background: rgba(100,140,220,.1);
    overflow: hidden;
    margin-top: 4px;
}

.roadmap-progress-fill {
    height: 100%;
    border-radius: 3px;
    background: linear-gradient(90deg, var(--cyan), var(--purple));
    transition: width .6s ease;
}

/* ---- 里程碑横排 ---- */
.milestones-row {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
    margin: 0 0 24px;
}

.milestone-card {
    background: var(--bg-card);
    border-radius: 16px;
    padding: 20px;
    border: 1px solid var(--border-subtle);
    text-align: center;
    min-width: 140px;
    flex: 1;
    max-width: 200px;
    transition: all var(--transition-base);
}

.milestone-card.achieved {
    border-color: rgba(16,185,129,.3);
    box-shadow: 0 0 20px rgba(16,185,129,.08);
}

.milestone-card.achieved:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 30px rgba(16,185,129,.15);
}

.milestone-card.pending {
    opacity: .55;
    filter: grayscale(30%);
}

.milestone-icon {
    font-size: 2rem;
    margin-bottom: 10px;
}

.milestone-name {
    font-weight: 600;
    color: var(--text-main);
    font-size: .85rem;
    margin-bottom: 6px;
}

.milestone-date {
    font-size: .75rem;
    color: var(--text-dim);
}

.milestone-status {
    font-size: .68rem;
    padding: 2px 10px;
    border-radius: 12px;
    margin-top: 8px;
    display: inline-block;
    font-weight: 600;
}

.milestone-status.achieved { background: rgba(16,185,129,.1); color: var(--green); }
.milestone-status.pending { background: rgba(100,140,220,.08); color: var(--text-dim); }

/* ---- 版本更新日志卡片 ---- */
.changelog-card {
    background: var(--bg-card);
    border-radius: 14px;
    padding: 20px;
    border: 1px solid var(--border-subtle);
    margin-bottom: 12px;
    transition: all var(--transition-base);
}

.changelog-card:hover {
    border-color: var(--border-glow);
    box-shadow: var(--shadow-sm);
}

.changelog-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

.changelog-version-badge {
    padding: 4px 12px;
    border-radius: 8px;
    font-size: .8rem;
    font-weight: 700;
    color: #fff;
}

.changelog-version-badge.major { background: linear-gradient(135deg, #8b5cf6, #6d28d9); }
.changelog-version-badge.minor { background: linear-gradient(135deg, #3b82f6, #2563eb); }
.changelog-version-badge.patch { background: linear-gradient(135deg, #10b981, #059669); }

.changelog-date {
    font-size: .78rem;
    color: var(--text-dim);
}

.changelog-title {
    font-weight: 600;
    color: var(--text-main);
    font-size: .95rem;
}

.changelog-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.changelog-list li {
    padding: 4px 0;
    font-size: .84rem;
    color: var(--text-dim);
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.changelog-list li::before {
    content: '✓';
    color: var(--green);
    font-weight: 700;
    flex-shrink: 0;
}

/* ---- 下载版本卡片 ---- */
.download-version-card {
    text-align: center;
    padding: 28px 20px;
    border-radius: 16px;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    transition: all var(--transition-base);
    cursor: pointer;
}

.download-version-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.download-version-card.win { border-top: 3px solid #3b82f6; }
.download-version-card.mac { border-top: 3px solid #a855f7; }
.download-version-card.linux { border-top: 3px solid #f59e0b; }

.download-version-icon { font-size: 2.8rem; margin-bottom: 12px; }
.download-version-name { font-weight: 700; font-size: 1.1rem; color: var(--text-main); }
.download-version-info { font-size: .8rem; color: var(--text-dim); margin: 6px 0 12px; }
.download-version-changes { text-align: left; font-size: .78rem; color: var(--text-dim); margin: 12px 0; padding: 0 0 0 16px; }
.download-version-changes li { margin-bottom: 3px; }

.download-version-btn {
    display: inline-block;
    padding: 10px 28px;
    border-radius: 10px;
    border: none;
    color: #fff;
    font-weight: 700;
    font-size: .88rem;
    cursor: pointer;
    transition: all var(--transition-base);
    margin-top: 8px;
}

.download-version-btn.win { background: linear-gradient(135deg, #3b82f6, #2563eb); }
.download-version-btn.mac { background: linear-gradient(135deg, #a855f7, #7c3aed); }
.download-version-btn.linux { background: linear-gradient(135deg, #f59e0b, #d97706); }
.download-version-btn:hover { transform: scale(1.03); filter: brightness(1.1); }

/* ---- 设置面板增强 ---- */
.settings-card {
    transition: all var(--transition-base);
}

.settings-card:hover {
    border-color: var(--border-glow);
}

/* ---- ROI增强表格 ---- */
.roi-table-enhanced {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    border-radius: 14px;
    overflow: hidden;
    border: 1px solid var(--border-subtle);
    font-size: .85rem;
}

.roi-table-enhanced thead th {
    background: rgba(56, 189, 248, .06);
    color: var(--cyan);
    font-weight: 600;
    padding: 12px 14px;
    text-align: left;
    border-bottom: 2px solid var(--border-glow);
    font-size: .82rem;
}

.roi-table-enhanced tbody td {
    padding: 11px 14px;
    border-bottom: 1px solid var(--border-subtle);
    color: var(--text-main);
}

.roi-table-enhanced tbody tr:last-child td { border-bottom: none; }

.roi-table-enhanced tbody tr:hover {
    background: rgba(56, 189, 248, .03);
}

.roi-table-enhanced tbody tr.highlight {
    background: linear-gradient(90deg, rgba(16,185,129,.06), rgba(56,189,248,.04));
    border-left: 3px solid var(--green);
}

.roi-check { color: var(--green); font-weight: 700; }
.roi-cross { color: var(--red); }

/* ---- 专家卡片 ---- */
.expert-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    cursor: pointer;
    transition: all .2s;
    border: 1px solid transparent;
    margin-bottom: 4px;
}

.expert-card:hover {
    background: rgba(56, 189, 248, .06);
    border-color: rgba(56, 189, 248, .15);
}

.expert-card.selected {
    background: rgba(56, 189, 248, .1);
    border-color: rgba(56, 189, 248, .3);
}

.expert-card-icon {
    font-size: 1.3rem;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(56, 189, 248, .1);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.expert-card-info { flex: 1; min-width: 0; }
.expert-card-name { font-size: .82rem; font-weight: 600; color: var(--text-main); }
.expert-card-desc { font-size: .7rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.expert-card-model { font-size: .62rem; padding: 1px 6px; border-radius: 6px; background: rgba(168,85,247,.1); color: var(--purple); }

/* ================================================================
   v1.0.0: 卡片增强 - 玻璃拟态 / 渐变边框 / 微交互
   ================================================================ */

/* 玻璃拟态卡片 */
.glass-card {
    background: var(--bg-glass);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
}

/* 渐变边框卡片（使用outline技巧） */
.gradient-border-card {
    position: relative;
    background: var(--bg-card);
    border-radius: 16px;
    border: 1px solid transparent;
    background-clip: padding-box;
}

.gradient-border-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 16px;
    padding: 1px;
    background: linear-gradient(135deg, var(--cyan), var(--purple), var(--pink));
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
}

/* 卡片悬停抬升 */
.card-lift {
    transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.card-lift:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 40px rgba(0,0,0,.1), 0 0 20px rgba(56,189,248,.08);
}

/* 按钮增强 */
.btn-glow {
    position: relative;
    overflow: hidden;
}

.btn-glow::after {
    content: '';
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(255,255,255,.2) 0%, transparent 60%);
    opacity: 0;
    transition: opacity .3s;
}

.btn-glow:hover::after { opacity: 1; }

/* 数字跳动动画 */
@keyframes countPulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.08); }
}

.stat-pulse {
    animation: countPulse .6s ease-in-out;
}

/* ================================================================
   v1.0.0: 响应式增强
   ================================================================ */

@media (max-width: 768px) {
    .testimonials-grid { grid-template-columns: 1fr; }
    .integrations-grid { grid-template-columns: repeat(2, 1fr); }
    .milestones-row { gap: 10px; }
    .milestone-card { min-width: 120px; max-width: none; }
    .roadmap-item { flex-direction: column; gap: 8px; }
    .roi-table-enhanced { font-size: .75rem; }
    .roi-table-enhanced thead th,
    .roi-table-enhanced tbody td { padding: 8px 10px; }
    .download-version-card { padding: 20px 16px; }
}

@media (max-width: 480px) {
    .integrations-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
    .integration-card { padding: 12px; }
    .testimonial-card { padding: 16px; }
    .milestones-row { flex-direction: column; align-items: stretch; }
    .milestone-card { max-width: none; }
    .changelog-header { flex-direction: column; align-items: flex-start; gap: 6px; }
}

/* ================================================================
   暗色主题 - 新组件覆盖
   ================================================================ */
[data-theme="dark"] .testimonial-card { border-left-color: rgba(56,189,248,.3); }
[data-theme="dark"] .testimonial-card::before { color: rgba(56,189,248,.04); }
[data-theme="dark"] .integration-card:hover { box-shadow: 0 0 20px rgba(56,189,248,.1); }
[data-theme="dark"] .roadmap-item { background: rgba(0,0,0,.02); }
[data-theme="dark"] .changelog-card { background: rgba(0,0,0,.015); }
[data-theme="dark"] .download-version-card { background: rgba(0,0,0,.02); }
[data-theme="dark"] .roi-table-enhanced tbody tr.highlight { background: linear-gradient(90deg, rgba(16,185,129,.04), rgba(56,189,248,.02)); }
[data-theme="dark"] .expert-card:hover { background: rgba(56,189,248,.08); }
[data-theme="dark"] .expert-card.selected { background: rgba(56,189,248,.12); }
[data-theme="dark"] .milestone-card.achieved { box-shadow: 0 0 16px rgba(16,185,129,.04); }
[data-theme="dark"] .btn-glow::after { background: radial-gradient(circle, rgba(0,0,0,.05) 0%, transparent 60%); }

/* ================================================================
   P7: 增强样式系统 — Glass Morphism, Micro-Interactions, Skeleton,
   Gradient Borders, Scrollbar, Badge Pulse, Stat Cards, Form Inputs,
   Navigation, Table, Tags/Badges, Toast, Mobile Responsive
   ================================================================ */

/* ----------------------------------------------------------------
   1. GLASS MORPHISM CARD SYSTEM
   ---------------------------------------------------------------- */
.glass-card-enhanced {
    position: relative;
    background: var(--bg-glass);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: 24px;
    overflow: hidden;
    transition:
        transform var(--transition-base),
        box-shadow var(--transition-base),
        border-color var(--transition-base),
        background var(--transition-slow);
    z-index: 0;
}

.glass-card-enhanced::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
        ellipse at top left,
        rgba(56, 189, 248, 0.06) 0%,
        transparent 50%
    ),
    radial-gradient(
        ellipse at bottom right,
        rgba(167, 139, 250, 0.04) 0%,
        transparent 50%
    );
    z-index: -1;
    opacity: 0;
    transition: opacity var(--transition-slow);
}

.glass-card-enhanced:hover {
    transform: translateY(-4px);
    box-shadow:
        var(--shadow-lg),
        0 0 0 1px rgba(56, 189, 248, 0.15),
        0 0 40px rgba(56, 189, 248, 0.06);
    border-color: var(--border-glow);
    background: rgba(255, 255, 255, 0.15);
}

.glass-card-enhanced:hover::before {
    opacity: 1;
}

/* Glass card variants */
.glass-card-purple {
    border-color: rgba(167, 139, 250, 0.15);
}
.glass-card-purple::before {
    background: radial-gradient(
        ellipse at top left,
        rgba(167, 139, 250, 0.08) 0%,
        transparent 50%
    ),
    radial-gradient(
        ellipse at bottom right,
        rgba(244, 114, 182, 0.04) 0%,
        transparent 50%
    );
}
.glass-card-purple:hover {
    border-color: rgba(167, 139, 250, 0.3);
    box-shadow:
        var(--shadow-lg),
        0 0 0 1px rgba(167, 139, 250, 0.15),
        0 0 40px rgba(167, 139, 250, 0.06);
}

.glass-card-cyan {
    border-color: rgba(56, 189, 248, 0.12);
}
.glass-card-cyan:hover {
    border-color: rgba(56, 189, 248, 0.35);
    box-shadow:
        var(--shadow-lg),
        0 0 0 1px rgba(56, 189, 248, 0.2),
        0 0 50px rgba(56, 189, 248, 0.1);
}

.glass-card-green {
    border-color: rgba(74, 222, 128, 0.12);
}
.glass-card-green::before {
    background: radial-gradient(
        ellipse at top left,
        rgba(74, 222, 128, 0.06) 0%,
        transparent 50%
    );
}
.glass-card-green:hover {
    border-color: rgba(74, 222, 128, 0.3);
    box-shadow:
        var(--shadow-lg),
        0 0 0 1px rgba(74, 222, 128, 0.15);
}

/* Glass card with subtle border glow on hover */
.glass-card-border-glow {
    border-width: 1px;
    border-style: solid;
}
.glass-card-border-glow:hover {
    border-image: linear-gradient(
        135deg,
        rgba(56, 189, 248, 0.4),
        rgba(167, 139, 250, 0.4),
        rgba(244, 114, 182, 0.3)
    ) 1;
}

/* Glass card icon container */
.glass-icon-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 16px;
    background: rgba(56, 189, 248, 0.1);
    border: 1px solid rgba(56, 189, 248, 0.15);
    font-size: 1.5rem;
    color: var(--cyan);
    margin-bottom: 14px;
    transition: all var(--transition-base);
}
.glass-card-enhanced:hover .glass-icon-wrap {
    background: rgba(56, 189, 248, 0.15);
    border-color: rgba(56, 189, 248, 0.3);
    transform: scale(1.05);
    box-shadow: 0 0 20px rgba(56, 189, 248, 0.12);
}

/* Glass card title & description */
.glass-card-title {
    font-size: 1.1rem;
    font-weight: 650;
    color: var(--text-main);
    margin-bottom: 6px;
}
.glass-card-desc {
    font-size: 0.85rem;
    color: var(--text-dim);
    line-height: 1.55;
}

/* Glass card grid layout */
.glass-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 20px;
    padding: 20px 0;
}

/* Dark theme overrides for glass cards */
[data-theme="dark"] .glass-card-enhanced {
    background: rgba(15, 23, 42, 0.65);
    backdrop-filter: blur(20px) saturate(150%);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
}
[data-theme="dark"] .glass-card-enhanced:hover {
    background: rgba(20, 30, 55, 0.75);
    box-shadow:
        var(--shadow-lg),
        0 0 0 1px rgba(56, 189, 248, 0.2),
        0 0 50px rgba(56, 189, 248, 0.08);
}
[data-theme="dark"] .glass-icon-wrap {
    background: rgba(56, 189, 248, 0.08);
    border-color: rgba(56, 189, 248, 0.12);
}

/* ----------------------------------------------------------------
   2. SKELETON LOADING STATES (Enhanced Shimmer)
   ---------------------------------------------------------------- */
.skeleton-enhanced {
    position: relative;
    overflow: hidden;
    background: var(--border-subtle);
    border-radius: var(--radius-sm);
}

.skeleton-enhanced::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.08) 20%,
        rgba(255, 255, 255, 0.15) 40%,
        rgba(255, 255, 255, 0.08) 60%,
        transparent 100%
    );
    animation: skeleton-shimmer 1.8s ease-in-out infinite;
}

@keyframes skeleton-shimmer {
    100% { transform: translateX(100%); }
}

/* Skeleton shape variants */
.skeleton-circle {
    border-radius: 50%;
}
.skeleton-line {
    height: 14px;
    margin-bottom: 8px;
    border-radius: 6px;
}
.skeleton-line-sm { height: 10px; width: 70%; }
.skeleton-line-md { height: 14px; width: 85%; }
.skeleton-line-lg { height: 18px; width: 95%; }
.skeleton-line-xl { height: 24px; width: 50%; }

.skeleton-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    flex-shrink: 0;
}
.skeleton-avatar-sm { width: 36px; height: 36px; }
.skeleton-avatar-lg { width: 64px; height: 64px; }

.skeleton-card-full {
    height: 180px;
    border-radius: var(--radius-md);
    width: 100%;
}

.skeleton-button {
    width: 100px;
    height: 38px;
    border-radius: 20px;
}

.skeleton-badge {
    width: 60px;
    height: 22px;
    border-radius: 11px;
}

/* Skeleton layout helpers */
.skeleton-row {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-bottom: 16px;
}
.skeleton-col {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
}

/* Dark theme skeleton */
[data-theme="dark"] .skeleton-enhanced {
    background: rgba(255, 255, 255, 0.04);
}
[data-theme="dark"] .skeleton-enhanced::after {
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.03) 20%,
        rgba(255, 255, 255, 0.06) 40%,
        rgba(255, 255, 255, 0.03) 60%,
        transparent 100%
    );
}

/* ----------------------------------------------------------------
   3. MICRO-INTERACTION SYSTEM
   ---------------------------------------------------------------- */

/* Enhanced Button System */
.btn-enhanced {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 22px;
    border: none;
    border-radius: 12px;
    font-size: 0.9rem;
    font-weight: 600;
    font-family: var(--font-sans);
    cursor: pointer;
    transition: all var(--transition-base);
    overflow: hidden;
    z-index: 0;
    outline: none;
    text-decoration: none;
    line-height: 1.4;
}

/* Ripple effect */
.btn-enhanced::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
        circle at center,
        rgba(255, 255, 255, 0.3) 0%,
        transparent 70%
    );
    transform: scale(0);
    opacity: 0;
    transition: transform 0.5s ease, opacity 0.4s ease;
    z-index: -1;
}
.btn-enhanced:active::after {
    transform: scale(3);
    opacity: 0;
    transition: transform 0s, opacity 0s;
}

/* Primary button */
.btn-primary-enhanced {
    background: var(--grad-cyan);
    color: #fff;
    box-shadow: 0 4px 14px rgba(56, 189, 248, 0.25);
}
.btn-primary-enhanced:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(56, 189, 248, 0.35);
}
.btn-primary-enhanced:active {
    transform: translateY(0) scale(0.97);
    box-shadow: 0 2px 8px rgba(56, 189, 248, 0.2);
}
.btn-primary-enhanced:focus-visible {
    box-shadow:
        0 0 0 3px var(--bg-deep),
        0 0 0 5px rgba(56, 189, 248, 0.5);
}

/* Secondary / Outline button */
.btn-outline-enhanced {
    background: transparent;
    color: var(--cyan);
    border: 1.5px solid rgba(56, 189, 248, 0.35);
}
.btn-outline-enhanced:hover {
    background: rgba(56, 189, 248, 0.08);
    border-color: var(--cyan);
    transform: translateY(-2px);
    box-shadow: 0 4px 16px rgba(56, 189, 248, 0.12);
}
.btn-outline-enhanced:active {
    transform: translateY(0) scale(0.97);
    background: rgba(56, 189, 248, 0.15);
}

/* Purple button */
.btn-purple-enhanced {
    background: linear-gradient(135deg, #a78bfa, #c084fc);
    color: #fff;
    box-shadow: 0 4px 14px rgba(167, 139, 250, 0.25);
}
.btn-purple-enhanced:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(167, 139, 250, 0.35);
}
.btn-purple-enhanced:active {
    transform: translateY(0) scale(0.97);
}

/* Pink button */
.btn-pink-enhanced {
    background: linear-gradient(135deg, #f472b6, #fb7185);
    color: #fff;
    box-shadow: 0 4px 14px rgba(244, 114, 182, 0.25);
}
.btn-pink-enhanced:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(244, 114, 182, 0.35);
}
.btn-pink-enhanced:active {
    transform: translateY(0) scale(0.97);
}

/* Green button */
.btn-green-enhanced {
    background: linear-gradient(135deg, #4ade80, #34d399);
    color: #111827;
    box-shadow: 0 4px 14px rgba(74, 222, 128, 0.25);
}
.btn-green-enhanced:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(74, 222, 128, 0.35);
}
.btn-green-enhanced:active {
    transform: translateY(0) scale(0.97);
}

/* Ghost button */
.btn-ghost-enhanced {
    background: transparent;
    color: var(--text-dim);
    border: 1px solid transparent;
}
.btn-ghost-enhanced:hover {
    background: rgba(56, 189, 248, 0.06);
    color: var(--cyan);
    border-color: rgba(56, 189, 248, 0.15);
}

/* Button sizes */
.btn-sm-enhanced { padding: 6px 14px; font-size: 0.8rem; border-radius: 8px; }
.btn-lg-enhanced { padding: 14px 32px; font-size: 1rem; border-radius: 16px; }
.btn-xl-enhanced { padding: 16px 40px; font-size: 1.1rem; border-radius: 18px; }

/* Button with icon */
.btn-icon-enhanced {
    width: 40px;
    height: 40px;
    padding: 0;
    border-radius: 12px;
    font-size: 1.1rem;
}
.btn-icon-enhanced.btn-sm-enhanced { width: 32px; height: 32px; font-size: 0.9rem; border-radius: 8px; }
.btn-icon-enhanced.btn-lg-enhanced { width: 48px; height: 48px; font-size: 1.3rem; border-radius: 14px; }

/* Focus ring animation */
@keyframes focusRingPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(56, 189, 248, 0.4); }
    50% { box-shadow: 0 0 0 6px rgba(56, 189, 248, 0); }
}
.focus-ring-animated:focus-visible {
    animation: focusRingPulse 2s ease-in-out infinite;
}

/* Loading state for buttons */
.btn-loading {
    pointer-events: none;
    opacity: 0.7;
    position: relative;
}
.btn-loading::before {
    content: '';
    width: 16px;
    height: 16px;
    border: 2px solid transparent;
    border-top-color: currentColor;
    border-radius: 50%;
    animation: btn-spin 0.6s linear infinite;
    margin-right: 6px;
}
@keyframes btn-spin {
    to { transform: rotate(360deg); }
}

/* Disabled state */
.btn-enhanced:disabled,
.btn-enhanced[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
    filter: grayscale(30%);
}

/* Button group */
.btn-group-enhanced {
    display: inline-flex;
    gap: 0;
}
.btn-group-enhanced .btn-enhanced {
    border-radius: 0;
}
.btn-group-enhanced .btn-enhanced:first-child {
    border-radius: 12px 0 0 12px;
}
.btn-group-enhanced .btn-enhanced:last-child {
    border-radius: 0 12px 12px 0;
}

/* Dark theme buttons */
[data-theme="dark"] .btn-outline-enhanced {
    border-color: rgba(56, 189, 248, 0.25);
}
[data-theme="dark"] .btn-ghost-enhanced:hover {
    background: rgba(56, 189, 248, 0.08);
}

/* ----------------------------------------------------------------
   4. GRADIENT BORDER ANIMATIONS (Conic Gradient)
   ---------------------------------------------------------------- */
.gradient-border-card {
    position: relative;
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    padding: 24px;
    z-index: 0;
}

.gradient-border-card::before {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: inherit;
    background: conic-gradient(
        from 0deg,
        var(--cyan),
        var(--purple),
        var(--pink),
        var(--cyan)
    );
    -webkit-mask:
        linear-gradient(#fff 0 0) content-box,
        linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    padding: 2px;
    z-index: -1;
    animation: gradientBorderSpin 4s linear infinite;
    opacity: 0;
    transition: opacity var(--transition-slow);
}

.gradient-border-card:hover::before {
    opacity: 1;
}

@keyframes gradientBorderSpin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Gradient border - visible variant (always on) */
.gradient-border-visible::before {
    opacity: 1;
    animation: gradientBorderSpin 6s linear infinite;
}

/* Gradient border - featured / popular */
.gradient-border-featured {
    position: relative;
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    padding: 24px;
    z-index: 0;
    box-shadow: var(--shadow-md);
}
.gradient-border-featured::before {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: inherit;
    background: conic-gradient(
        from 0deg,
        #f59e0b,
        var(--orange),
        var(--pink),
        #f59e0b
    );
    -webkit-mask:
        linear-gradient(#fff 0 0) content-box,
        linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    padding: 2px;
    z-index: -1;
    animation: gradientBorderSpin 5s linear infinite;
    opacity: 1;
}

/* Gradient border - cyan/purple slow */
.gradient-border-slow::before {
    animation: gradientBorderSpin 10s linear infinite;
}

/* Dark theme */
[data-theme="dark"] .gradient-border-card {
    background: rgba(15, 23, 42, 0.8);
}

/* ----------------------------------------------------------------
   5. SCROLLBAR STYLING (Enhanced Webkit)
   ---------------------------------------------------------------- */
::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: var(--bg-surface);
    border-radius: 0;
}

::-webkit-scrollbar-thumb {
    background: linear-gradient(
        180deg,
        rgba(56, 189, 248, 0.25),
        rgba(167, 139, 250, 0.3)
    );
    border-radius: 6px;
    border: 2px solid var(--bg-surface);
    transition: background var(--transition-base);
}

::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(
        180deg,
        rgba(56, 189, 248, 0.45),
        rgba(167, 139, 250, 0.5)
    );
}

::-webkit-scrollbar-thumb:active {
    background: linear-gradient(
        180deg,
        rgba(56, 189, 248, 0.6),
        rgba(167, 139, 250, 0.65)
    );
}

::-webkit-scrollbar-corner {
    background: var(--bg-surface);
}

/* Firefox scrollbar */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(56, 189, 248, 0.25) var(--bg-surface);
}

/* Custom scrollbar for specific containers */
.custom-scrollbar::-webkit-scrollbar { width: 6px; }
.custom-scrollbar::-webkit-scrollbar-thumb {
    background: linear-gradient(
        180deg,
        rgba(56, 189, 248, 0.2),
        rgba(167, 139, 250, 0.25)
    );
    border-radius: 3px;
    border: 1px solid transparent;
}
.custom-scrollbar::-webkit-scrollbar-track {
    background: transparent;
}

/* Dark theme scrollbar */
[data-theme="dark"] ::-webkit-scrollbar-track {
    background: rgba(6, 9, 24, 0.8);
}
[data-theme="dark"] ::-webkit-scrollbar-thumb {
    border-color: rgba(6, 9, 24, 0.8);
}
[data-theme="dark"] * {
    scrollbar-color: rgba(56, 189, 248, 0.2) rgba(6, 9, 24, 0.8);
}

/* ----------------------------------------------------------------
   6. NOTIFICATION BADGE PULSE
   ---------------------------------------------------------------- */
.notification-badge {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 10px;
    background: var(--red);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
}

/* Pulse animation */
@keyframes badgePulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(248, 113, 113, 0.6);
    }
    50% {
        box-shadow: 0 0 0 8px rgba(248, 113, 113, 0);
    }
}
.notification-badge.pulse {
    animation: badgePulse 2s ease-in-out infinite;
}

/* Badge on icon */
.badge-wrapper {
    position: relative;
    display: inline-flex;
}
.badge-wrapper .notification-badge {
    position: absolute;
    top: -6px;
    right: -8px;
}

/* Badge dot variant (just a dot) */
.notification-dot {
    width: 10px;
    height: 10px;
    min-width: 10px;
    padding: 0;
    border-radius: 50%;
    background: var(--red);
    box-shadow: 0 0 6px rgba(248, 113, 113, 0.5);
}
.notification-dot.pulse {
    animation: badgePulse 2s ease-in-out infinite;
}

/* Badge colors */
.notification-badge.cyan {
    background: var(--cyan);
}
.notification-badge.cyan.pulse {
    animation-name: badgePulseCyan;
}
@keyframes badgePulseCyan {
    0%, 100% { box-shadow: 0 0 0 0 rgba(56, 189, 248, 0.6); }
    50% { box-shadow: 0 0 0 8px rgba(56, 189, 248, 0); }
}

.notification-badge.green {
    background: var(--green);
}
.notification-badge.green.pulse {
    animation-name: badgePulseGreen;
}
@keyframes badgePulseGreen {
    0%, 100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.6); }
    50% { box-shadow: 0 0 0 8px rgba(74, 222, 128, 0); }
}

.notification-badge.orange {
    background: var(--orange);
}
.notification-badge.orange.pulse {
    animation-name: badgePulseOrange;
}
@keyframes badgePulseOrange {
    0%, 100% { box-shadow: 0 0 0 0 rgba(251, 146, 60, 0.6); }
    50% { box-shadow: 0 0 0 8px rgba(251, 146, 60, 0); }
}

.notification-badge.purple {
    background: var(--purple);
}
.notification-badge.purple.pulse {
    animation-name: badgePulsePurple;
}
@keyframes badgePulsePurple {
    0%, 100% { box-shadow: 0 0 0 0 rgba(167, 139, 250, 0.6); }
    50% { box-shadow: 0 0 0 8px rgba(167, 139, 250, 0); }
}

/* Badge count animation on update */
@keyframes badgePopIn {
    0% { transform: scale(0.3); opacity: 0; }
    50% { transform: scale(1.2); }
    100% { transform: scale(1); opacity: 1; }
}
.notification-badge.pop-in {
    animation: badgePopIn 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

/* ----------------------------------------------------------------
   7. STAT CARD ENHANCEMENT
   ---------------------------------------------------------------- */
.stat-card-enhanced {
    position: relative;
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: 22px 24px;
    overflow: hidden;
    transition:
        transform var(--transition-base),
        box-shadow var(--transition-base),
        border-color var(--transition-base);
    z-index: 0;
}

.stat-card-enhanced::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--grad-cyan);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    opacity: 0;
    transition: opacity var(--transition-base);
}

.stat-card-enhanced:hover {
    transform: translateY(-6px);
    box-shadow: var(--shadow-lg), 0 0 30px rgba(56, 189, 248, 0.08);
    border-color: var(--border-glow);
}
.stat-card-enhanced:hover::before {
    opacity: 1;
}

/* Stat icon with glow */
.stat-icon-enhanced {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 14px;
    font-size: 1.3rem;
    margin-bottom: 12px;
    transition: all var(--transition-base);
}
.stat-icon-cyan {
    background: rgba(56, 189, 248, 0.12);
    color: var(--cyan);
}
.stat-icon-purple {
    background: rgba(167, 139, 250, 0.12);
    color: var(--purple);
}
.stat-icon-green {
    background: rgba(74, 222, 128, 0.12);
    color: var(--green);
}
.stat-icon-pink {
    background: rgba(244, 114, 182, 0.12);
    color: var(--pink);
}
.stat-icon-orange {
    background: rgba(251, 146, 60, 0.12);
    color: var(--orange);
}

.stat-card-enhanced:hover .stat-icon-cyan {
    box-shadow: 0 0 20px rgba(56, 189, 248, 0.25);
    background: rgba(56, 189, 248, 0.18);
}
.stat-card-enhanced:hover .stat-icon-purple {
    box-shadow: 0 0 20px rgba(167, 139, 250, 0.25);
    background: rgba(167, 139, 250, 0.18);
}
.stat-card-enhanced:hover .stat-icon-green {
    box-shadow: 0 0 20px rgba(74, 222, 128, 0.25);
    background: rgba(74, 222, 128, 0.18);
}
.stat-card-enhanced:hover .stat-icon-pink {
    box-shadow: 0 0 20px rgba(244, 114, 182, 0.25);
    background: rgba(244, 114, 182, 0.18);
}
.stat-card-enhanced:hover .stat-icon-orange {
    box-shadow: 0 0 20px rgba(251, 146, 60, 0.25);
    background: rgba(251, 146, 60, 0.18);
}

/* Stat value with gradient text */
.stat-value-enhanced {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.2;
    margin-bottom: 4px;
    background: var(--grad-cyan);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.stat-value-purple {
    background: linear-gradient(135deg, #a78bfa, #c084fc);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.stat-value-green {
    background: linear-gradient(135deg, #4ade80, #34d399);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.stat-value-pink {
    background: linear-gradient(135deg, #f472b6, #fb7185);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.stat-value-orange {
    background: linear-gradient(135deg, #fb923c, #f97316);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.stat-label-enhanced {
    font-size: 0.82rem;
    color: var(--text-dim);
    font-weight: 500;
}

.stat-trend-enhanced {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.78rem;
    font-weight: 600;
    margin-top: 6px;
}
.stat-trend-up { color: var(--green); }
.stat-trend-down { color: var(--red); }
.stat-trend-neutral { color: var(--text-muted); }

/* Stat card grid */
.stat-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
}

/* Dark theme */
[data-theme="dark"] .stat-card-enhanced {
    background: rgba(15, 23, 42, 0.6);
}

/* ----------------------------------------------------------------
   8. FORM INPUT ENHANCEMENT (Floating Labels)
   ---------------------------------------------------------------- */

/* Floating label container */
.floating-label-wrap {
    position: relative;
    margin-bottom: 18px;
}

.floating-label-wrap input,
.floating-label-wrap textarea,
.floating-label-wrap select {
    width: 100%;
    padding: 14px 16px 8px;
    border: 1.5px solid var(--border-subtle);
    border-radius: 12px;
    background: var(--bg-card);
    color: var(--text-main);
    font-size: 0.9rem;
    font-family: var(--font-sans);
    outline: none;
    transition: all var(--transition-base);
    line-height: 1.5;
}

.floating-label-wrap textarea {
    min-height: 100px;
    resize: vertical;
}

.floating-label-wrap label {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.9rem;
    color: var(--text-muted);
    pointer-events: none;
    transition: all var(--transition-fast);
    background: transparent;
    padding: 0 4px;
    line-height: 1;
}

/* Textarea label stays at top */
.floating-label-wrap textarea ~ label,
.floating-label-wrap.textarea label {
    top: 14px;
    transform: none;
}

/* Active state - label floats up */
.floating-label-wrap input:focus ~ label,
.floating-label-wrap input:not(:placeholder-shown) ~ label,
.floating-label-wrap textarea:focus ~ label,
.floating-label-wrap textarea:not(:placeholder-shown) ~ label,
.floating-label-wrap select:focus ~ label,
.floating-label-wrap select:valid ~ label,
.floating-label-wrap.filled label {
    top: 6px;
    transform: none;
    font-size: 0.7rem;
    color: var(--cyan);
    font-weight: 600;
    background: var(--bg-card);
}

/* Focus state */
.floating-label-wrap input:focus,
.floating-label-wrap textarea:focus,
.floating-label-wrap select:focus {
    border-color: var(--cyan);
    box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.1), 0 0 20px rgba(56, 189, 248, 0.04);
}

/* Error state */
.floating-label-wrap.error input,
.floating-label-wrap.error textarea,
.floating-label-wrap.error select {
    border-color: var(--red);
}
.floating-label-wrap.error input:focus,
.floating-label-wrap.error textarea:focus,
.floating-label-wrap.error select:focus {
    box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.1);
}
.floating-label-wrap.error label {
    color: var(--red) !important;
}
.floating-label-wrap .error-msg {
    display: none;
    font-size: 0.72rem;
    color: var(--red);
    margin-top: 4px;
    padding-left: 4px;
}
.floating-label-wrap.error .error-msg {
    display: block;
    animation: slide-up 0.2s ease-out;
}

/* Success state */
.floating-label-wrap.success input,
.floating-label-wrap.success textarea,
.floating-label-wrap.success select {
    border-color: var(--green);
}
.floating-label-wrap.success label {
    color: var(--green) !important;
}
.floating-label-wrap .success-icon {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--green);
    font-size: 1rem;
    display: none;
}
.floating-label-wrap.success .success-icon {
    display: block;
}

/* Input with icon prefix */
.input-with-icon {
    position: relative;
}
.input-with-icon input {
    padding-left: 42px;
}
.input-with-icon .input-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: 1rem;
    pointer-events: none;
    transition: color var(--transition-base);
}
.input-with-icon input:focus ~ .input-icon {
    color: var(--cyan);
}

/* Enhanced select */
.select-enhanced {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%239ca3af' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    padding-right: 36px;
    cursor: pointer;
}

/* Checkbox & Radio enhancement */
.checkbox-enhanced,
.radio-enhanced {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font-size: 0.88rem;
    color: var(--text-main);
    user-select: none;
}
.checkbox-enhanced input[type="checkbox"],
.radio-enhanced input[type="radio"] {
    display: none;
}
.checkbox-enhanced .checkmark,
.radio-enhanced .radiomark {
    width: 20px;
    height: 20px;
    border: 2px solid var(--border-subtle);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
    flex-shrink: 0;
    background: var(--bg-card);
}
.radio-enhanced .radiomark {
    border-radius: 50%;
}
.checkbox-enhanced input:checked ~ .checkmark {
    background: var(--cyan);
    border-color: var(--cyan);
}
.checkbox-enhanced input:checked ~ .checkmark::after {
    content: '';
    width: 5px;
    height: 10px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg) translateY(-1px);
}
.radio-enhanced input:checked ~ .radiomark {
    border-color: var(--cyan);
}
.radio-enhanced input:checked ~ .radiomark::after {
    content: '';
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--cyan);
}

/* Toggle switch */
.toggle-switch {
    position: relative;
    display: inline-block;
    width: 48px;
    height: 26px;
}
.toggle-switch input {
    display: none;
}
.toggle-switch .toggle-slider {
    position: absolute;
    inset: 0;
    background: var(--border-subtle);
    border-radius: 13px;
    cursor: pointer;
    transition: all var(--transition-base);
    border: 1px solid var(--border-subtle);
}
.toggle-switch .toggle-slider::before {
    content: '';
    position: absolute;
    width: 20px;
    height: 20px;
    left: 2px;
    top: 2px;
    background: #fff;
    border-radius: 50%;
    transition: all var(--transition-base);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
.toggle-switch input:checked ~ .toggle-slider {
    background: var(--cyan);
    border-color: var(--cyan);
}
.toggle-switch input:checked ~ .toggle-slider::before {
    transform: translateX(22px);
}

/* Form group layout */
.form-group-enhanced {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.form-row-enhanced {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}
.form-row-enhanced > * {
    flex: 1;
    min-width: 200px;
}

/* Dark theme */
[data-theme="dark"] .floating-label-wrap input,
[data-theme="dark"] .floating-label-wrap textarea,
[data-theme="dark"] .floating-label-wrap select {
    background: rgba(15, 23, 42, 0.6);
    border-color: rgba(100, 140, 220, 0.15);
}
[data-theme="dark"] .floating-label-wrap input:focus ~ label,
[data-theme="dark"] .floating-label-wrap input:not(:placeholder-shown) ~ label,
[data-theme="dark"] .floating-label-wrap.filled label {
    background: rgba(15, 23, 42, 0.6);
}
[data-theme="dark"] .checkbox-enhanced .checkmark,
[data-theme="dark"] .radio-enhanced .radiomark {
    background: rgba(15, 23, 42, 0.6);
}

/* ----------------------------------------------------------------
   9. NAVIGATION ENHANCEMENT
   ---------------------------------------------------------------- */

/* Active nav item with gradient underline */
.nav-link-enhanced {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    color: var(--text-dim);
    font-size: 0.88rem;
    font-weight: 500;
    text-decoration: none;
    border-radius: 8px;
    transition: all var(--transition-base);
    white-space: nowrap;
}

.nav-link-enhanced::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 0;
    height: 2.5px;
    background: var(--grad-cyan);
    border-radius: 2px;
    transition: width var(--transition-base);
}

.nav-link-enhanced:hover {
    color: var(--text-main);
    background: rgba(56, 189, 248, 0.06);
}

.nav-link-enhanced.active {
    color: var(--cyan);
    font-weight: 600;
}
.nav-link-enhanced.active::after {
    width: 70%;
}

.nav-link-enhanced:hover::after {
    width: 50%;
}

/* Nav item with glow on hover */
.nav-link-glow:hover {
    text-shadow: 0 0 12px rgba(56, 189, 248, 0.3);
}

/* Nav link with icon */
.nav-link-enhanced .nav-icon {
    font-size: 1rem;
    transition: transform var(--transition-base);
}
.nav-link-enhanced:hover .nav-icon {
    transform: translateY(-1px);
}

/* Sidebar nav */
.sidebar-nav-enhanced {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px;
}
.sidebar-nav-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    color: var(--text-dim);
    font-size: 0.88rem;
    text-decoration: none;
    transition: all var(--transition-base);
    border-left: 3px solid transparent;
}
.sidebar-nav-link:hover {
    color: var(--text-main);
    background: rgba(56, 189, 248, 0.05);
}
.sidebar-nav-link.active {
    color: var(--cyan);
    background: rgba(56, 189, 248, 0.08);
    border-left-color: var(--cyan);
    font-weight: 600;
}

/* Bottom tab bar (mobile) */
.bottom-tab-bar {
    display: flex;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--bg-elevated);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-top: 1px solid var(--border-subtle);
    padding: 6px 8px;
    padding-bottom: max(6px, env(safe-area-inset-bottom));
    z-index: 1000;
    justify-content: space-around;
}
.bottom-tab-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 4px 12px;
    border-radius: 10px;
    color: var(--text-muted);
    font-size: 0.68rem;
    font-weight: 500;
    text-decoration: none;
    transition: all var(--transition-base);
    min-width: 56px;
}
.bottom-tab-item .tab-icon {
    font-size: 1.25rem;
    transition: transform var(--transition-base);
}
.bottom-tab-item.active {
    color: var(--cyan);
}
.bottom-tab-item.active .tab-icon {
    transform: scale(1.1);
}

/* Dark theme */
[data-theme="dark"] .nav-link-enhanced:hover {
    background: rgba(56, 189, 248, 0.08);
}
[data-theme="dark"] .bottom-tab-bar {
    background: rgba(8, 14, 35, 0.92);
}

/* ----------------------------------------------------------------
   10. TABLE ENHANCEMENT
   ---------------------------------------------------------------- */
.table-enhanced {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.88rem;
}

.table-enhanced thead {
    position: sticky;
    top: 0;
    z-index: 10;
}

.table-enhanced th {
    background: var(--bg-elevated);
    color: var(--text-dim);
    font-weight: 600;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 14px 16px;
    text-align: left;
    border-bottom: 2px solid var(--border-glow);
    white-space: nowrap;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

.table-enhanced td {
    padding: 12px 16px;
    color: var(--text-main);
    border-bottom: 1px solid var(--border-subtle);
    transition: background var(--transition-fast);
}

/* Striped rows */
.table-enhanced tbody tr:nth-child(even) {
    background: rgba(56, 189, 248, 0.02);
}

/* Row hover */
.table-enhanced tbody tr:hover {
    background: rgba(56, 189, 248, 0.05);
}

/* Row hover highlight left border */
.table-enhanced tbody tr:hover td:first-child {
    position: relative;
}
.table-enhanced tbody tr:hover td:first-child::before {
    content: '';
    position: absolute;
    left: 0;
    top: 10%;
    height: 80%;
    width: 3px;
    background: var(--cyan);
    border-radius: 0 2px 2px 0;
}

/* Table card wrapper for mobile scroll */
.table-card-wrapper {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.table-scroll-container {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.table-scroll-container::-webkit-scrollbar { height: 6px; }

/* Compact table */
.table-compact th,
.table-compact td {
    padding: 8px 12px;
    font-size: 0.82rem;
}

/* Status dots in table */
.table-status-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: 6px;
}
.table-status-dot.active { background: var(--green); box-shadow: 0 0 6px rgba(74, 222, 128, 0.4); }
.table-status-dot.inactive { background: var(--text-muted); }
.table-status-dot.warning { background: var(--orange); box-shadow: 0 0 6px rgba(251, 146, 60, 0.4); }
.table-status-dot.error { background: var(--red); box-shadow: 0 0 6px rgba(248, 113, 113, 0.4); }

/* Empty state */
.table-empty-state {
    text-align: center;
    padding: 48px 24px;
    color: var(--text-muted);
    font-size: 0.9rem;
}
.table-empty-state .empty-icon {
    font-size: 2.5rem;
    margin-bottom: 12px;
    opacity: 0.5;
}

/* Dark theme */
[data-theme="dark"] .table-enhanced th {
    background: rgba(10, 16, 40, 0.9);
}
[data-theme="dark"] .table-enhanced tbody tr:nth-child(even) {
    background: rgba(255, 255, 255, 0.015);
}
[data-theme="dark"] .table-enhanced tbody tr:hover {
    background: rgba(56, 189, 248, 0.06);
}

/* ----------------------------------------------------------------
   11. TAG / BADGE SYSTEM
   ---------------------------------------------------------------- */
.tag-enhanced {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 0.75rem;
    font-weight: 500;
    white-space: nowrap;
    transition: all var(--transition-fast);
    cursor: default;
    line-height: 1.4;
}

/* Tag color variants */
.tag-cyan {
    background: rgba(56, 189, 248, 0.12);
    color: var(--cyan);
    border: 1px solid rgba(56, 189, 248, 0.2);
}
.tag-purple {
    background: rgba(167, 139, 250, 0.12);
    color: var(--purple);
    border: 1px solid rgba(167, 139, 250, 0.2);
}
.tag-pink {
    background: rgba(244, 114, 182, 0.12);
    color: var(--pink);
    border: 1px solid rgba(244, 114, 182, 0.2);
}
.tag-green {
    background: rgba(74, 222, 128, 0.12);
    color: var(--green);
    border: 1px solid rgba(74, 222, 128, 0.2);
}
.tag-orange {
    background: rgba(251, 146, 60, 0.12);
    color: var(--orange);
    border: 1px solid rgba(251, 146, 60, 0.2);
}
.tag-red {
    background: rgba(248, 113, 113, 0.12);
    color: var(--red);
    border: 1px solid rgba(248, 113, 113, 0.2);
}

/* Gradient tags */
.tag-gradient-cyan {
    background: linear-gradient(135deg, rgba(56, 189, 248, 0.15), rgba(129, 140, 248, 0.12));
    color: var(--cyan);
    border: 1px solid rgba(56, 189, 248, 0.25);
}
.tag-gradient-purple {
    background: linear-gradient(135deg, rgba(167, 139, 250, 0.15), rgba(244, 114, 182, 0.1));
    color: var(--purple);
    border: 1px solid rgba(167, 139, 250, 0.25);
}
.tag-gradient-green {
    background: linear-gradient(135deg, rgba(74, 222, 128, 0.15), rgba(52, 211, 153, 0.1));
    color: var(--green);
    border: 1px solid rgba(74, 222, 128, 0.25);
}

/* Tag hover effects */
.tag-enhanced:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.tag-cyan:hover { box-shadow: 0 2px 8px rgba(56, 189, 248, 0.15); }
.tag-purple:hover { box-shadow: 0 2px 8px rgba(167, 139, 250, 0.15); }
.tag-green:hover { box-shadow: 0 2px 8px rgba(74, 222, 128, 0.15); }
.tag-pink:hover { box-shadow: 0 2px 8px rgba(244, 114, 182, 0.15); }
.tag-orange:hover { box-shadow: 0 2px 8px rgba(251, 146, 60, 0.15); }
.tag-red:hover { box-shadow: 0 2px 8px rgba(248, 113, 113, 0.15); }

/* Removable tag */
.tag-removable {
    cursor: pointer;
    padding-right: 6px;
}
.tag-removable .tag-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    font-size: 0.65rem;
    margin-left: 2px;
    opacity: 0.5;
    transition: all var(--transition-fast);
}
.tag-removable:hover .tag-close {
    opacity: 1;
    background: rgba(0, 0, 0, 0.1);
}

/* Tag sizes */
.tag-sm { padding: 2px 8px; font-size: 0.68rem; border-radius: 14px; }
.tag-lg { padding: 5px 14px; font-size: 0.85rem; border-radius: 24px; }

/* Tag with dot */
.tag-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    margin-right: 2px;
}
.tag-dot-cyan { background: var(--cyan); }
.tag-dot-purple { background: var(--purple); }
.tag-dot-green { background: var(--green); }
.tag-dot-pink { background: var(--pink); }
.tag-dot-orange { background: var(--orange); }
.tag-dot-red { background: var(--red); }

/* Tag group */
.tag-group {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* Dark theme */
[data-theme="dark"] .tag-enhanced:hover {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
}

/* ----------------------------------------------------------------
   12. TOAST ANIMATION (Slide-in from right with progress bar)
   ---------------------------------------------------------------- */
.toast-enhanced {
    position: fixed;
    top: 24px;
    right: 24px;
    z-index: 100000;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    min-width: 320px;
    max-width: 420px;
    padding: 16px 20px;
    background: var(--bg-elevated);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    transform: translateX(calc(100% + 24px));
    opacity: 0;
    transition:
        transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275),
        opacity 0.3s ease;
    overflow: hidden;
}

.toast-enhanced.show {
    transform: translateX(0);
    opacity: 1;
}

.toast-enhanced.hide {
    transform: translateX(calc(100% + 24px));
    opacity: 0;
}

/* Toast icon */
.toast-icon {
    font-size: 1.3rem;
    flex-shrink: 0;
    margin-top: 1px;
}
.toast-icon.success { color: var(--green); }
.toast-icon.error { color: var(--red); }
.toast-icon.warning { color: var(--orange); }
.toast-icon.info { color: var(--cyan); }

/* Toast content */
.toast-content {
    flex: 1;
    min-width: 0;
}
.toast-title {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-main);
    margin-bottom: 2px;
}
.toast-message {
    font-size: 0.8rem;
    color: var(--text-dim);
    line-height: 1.4;
}

/* Toast close button */
.toast-close {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 6px;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
    padding: 0;
    line-height: 1;
}
.toast-close:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--text-main);
}

/* Toast progress bar */
.toast-progress {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 3px;
    background: var(--grad-cyan);
    border-radius: 0 0 0 var(--radius-md);
    transition: width 0.1s linear;
}
.toast-enhanced.success .toast-progress {
    background: linear-gradient(90deg, var(--green), #34d399);
}
.toast-enhanced.error .toast-progress {
    background: linear-gradient(90deg, var(--red), #fca5a5);
}
.toast-enhanced.warning .toast-progress {
    background: linear-gradient(90deg, var(--orange), #fbbf24);
}

/* Toast stack (multiple toasts) */
.toast-stack {
    position: fixed;
    top: 24px;
    right: 24px;
    z-index: 100000;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.toast-stack .toast-enhanced {
    position: relative;
    top: auto;
    right: auto;
}

/* Toast positions */
.toast-bottom-right {
    top: auto;
    bottom: 24px;
    right: 24px;
}
.toast-bottom-left {
    top: auto;
    bottom: 24px;
    left: 24px;
    right: auto;
    transform: translateX(calc(-100% - 24px));
}
.toast-bottom-left.show {
    transform: translateX(0);
}
.toast-bottom-left.hide {
    transform: translateX(calc(-100% - 24px));
}
.toast-top-center {
    right: 50%;
    transform: translate(50%, -20px);
}
.toast-top-center.show {
    transform: translate(50%, 0);
}
.toast-top-center.hide {
    transform: translate(50%, -20px);
}

/* Dark theme */
[data-theme="dark"] .toast-enhanced {
    background: rgba(20, 30, 55, 0.95);
    border-color: rgba(100, 140, 220, 0.15);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

/* ----------------------------------------------------------------
   13. MOBILE RESPONSIVE ENHANCEMENTS
   ---------------------------------------------------------------- */

/* Tablet landscape (1024px - 1199px) */
@media (min-width: 1024px) and (max-width: 1199px) {
    .glass-card-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
    .stat-cards-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
    .table-enhanced { font-size: 0.84rem; }
    .table-enhanced th,
    .table-enhanced td { padding: 10px 14px; }
    .toast-enhanced { min-width: 280px; max-width: 380px; }
}

/* Tablet portrait (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
    .glass-card-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
    .stat-cards-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
    .stat-card-enhanced { padding: 18px 20px; }
    .stat-value-enhanced { font-size: 1.6rem; }

    .form-row-enhanced { flex-direction: column; gap: 0; }
    .form-row-enhanced > * { min-width: 100%; }

    .table-enhanced th,
    .table-enhanced td { padding: 10px 12px; font-size: 0.82rem; }

    .glass-card-enhanced { padding: 20px; }
    .glass-icon-wrap { width: 44px; height: 44px; font-size: 1.3rem; }

    .btn-enhanced { padding: 8px 18px; font-size: 0.85rem; }
    .btn-lg-enhanced { padding: 12px 26px; font-size: 0.95rem; }

    .nav-link-enhanced { padding: 6px 12px; font-size: 0.82rem; }

    .toast-enhanced { min-width: 280px; max-width: 360px; right: 16px; }
    .toast-stack { right: 16px; }

    .bottom-tab-bar { display: flex; }

    .tag-group { gap: 4px; }
    .tag-enhanced { font-size: 0.72rem; padding: 2px 8px; }
}

/* Large phones (480px - 767px) */
@media (min-width: 480px) and (max-width: 767px) {
    .glass-card-grid { grid-template-columns: 1fr; gap: 14px; }
    .stat-cards-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .stat-card-enhanced { padding: 16px; }
    .stat-value-enhanced { font-size: 1.5rem; }
    .stat-label-enhanced { font-size: 0.76rem; }

    .form-row-enhanced { flex-direction: column; gap: 0; }
    .form-row-enhanced > * { min-width: 100%; }

    .floating-label-wrap input,
    .floating-label-wrap textarea,
    .floating-label-wrap select {
        font-size: 16px; /* prevent iOS zoom */
        padding: 12px 14px 8px;
    }

    .table-enhanced { font-size: 0.78rem; }
    .table-enhanced th { font-size: 0.7rem; padding: 8px 10px; }
    .table-enhanced td { padding: 8px 10px; }

    /* Hide less important columns on mobile */
    .table-enhanced th.col-hide-mobile,
    .table-enhanced td.col-hide-mobile { display: none; }

    .glass-card-enhanced { padding: 18px; }
    .glass-icon-wrap { width: 40px; height: 40px; font-size: 1.2rem; }
    .glass-card-title { font-size: 1rem; }

    .btn-enhanced { padding: 8px 16px; font-size: 0.85rem; width: 100%; justify-content: center; }
    .btn-group-enhanced { flex-direction: column; width: 100%; }
    .btn-group-enhanced .btn-enhanced { border-radius: 12px; }

    .nav-link-enhanced { padding: 6px 10px; font-size: 0.8rem; }
    .sidebar-nav-link { padding: 8px 12px; font-size: 0.82rem; }

    .toast-enhanced {
        min-width: 0;
        max-width: calc(100vw - 32px);
        right: 16px;
        left: 16px;
    }
    .toast-stack { right: 16px; left: 16px; }

    .bottom-tab-bar { display: flex; }

    .tag-group { gap: 3px; }
    .tag-enhanced { font-size: 0.7rem; padding: 2px 8px; }

    .gradient-border-card { padding: 18px; }

    .notification-badge { min-width: 18px; height: 18px; font-size: 0.65rem; }
}

/* Small phones (< 480px) */
@media (max-width: 479px) {
    .glass-card-grid { grid-template-columns: 1fr; gap: 12px; }
    .stat-cards-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
    .stat-card-enhanced { padding: 14px; border-radius: var(--radius-md); }
    .stat-value-enhanced { font-size: 1.3rem; }
    .stat-label-enhanced { font-size: 0.72rem; }
    .stat-icon-enhanced { width: 36px; height: 36px; font-size: 1rem; border-radius: 10px; margin-bottom: 8px; }

    .form-row-enhanced { flex-direction: column; gap: 0; }
    .form-row-enhanced > * { min-width: 100%; }

    .floating-label-wrap { margin-bottom: 14px; }
    .floating-label-wrap input,
    .floating-label-wrap textarea,
    .floating-label-wrap select {
        font-size: 16px;
        padding: 10px 12px 6px;
        border-radius: 10px;
    }
    .floating-label-wrap label { font-size: 0.82rem; }
    .floating-label-wrap input:focus ~ label,
    .floating-label-wrap input:not(:placeholder-shown) ~ label,
    .floating-label-wrap.filled label {
        font-size: 0.65rem;
    }

    .table-enhanced { font-size: 0.72rem; }
    .table-enhanced th { font-size: 0.65rem; padding: 6px 8px; }
    .table-enhanced td { padding: 6px 8px; }
    .table-enhanced th.col-hide-mobile,
    .table-enhanced td.col-hide-mobile { display: none; }
    .table-enhanced th.col-hide-small,
    .table-enhanced td.col-hide-small { display: none; }

    .glass-card-enhanced { padding: 16px; border-radius: var(--radius-md); }
    .glass-icon-wrap { width: 36px; height: 36px; font-size: 1.1rem; border-radius: 10px; margin-bottom: 10px; }
    .glass-card-title { font-size: 0.95rem; }
    .glass-card-desc { font-size: 0.78rem; }

    .btn-enhanced { padding: 8px 16px; font-size: 0.82rem; width: 100%; justify-content: center; }
    .btn-group-enhanced { flex-direction: column; width: 100%; }
    .btn-group-enhanced .btn-enhanced { border-radius: 10px; margin-bottom: 4px; }
    .btn-icon-enhanced { width: 36px; height: 36px; }

    .nav-link-enhanced { padding: 4px 8px; font-size: 0.75rem; }
    .nav-link-enhanced .nav-icon { font-size: 0.9rem; }
    .sidebar-nav-link { padding: 8px 10px; font-size: 0.78rem; }
    .sidebar-nav-link .nav-icon { font-size: 0.9rem; }

    .toast-enhanced {
        min-width: 0;
        max-width: calc(100vw - 20px);
        right: 10px;
        left: 10px;
        top: 16px;
        padding: 12px 16px;
    }
    .toast-title { font-size: 0.82rem; }
    .toast-message { font-size: 0.74rem; }
    .toast-stack { right: 10px; left: 10px; top: 16px; }

    .bottom-tab-bar { display: flex; padding: 4px 4px; }
    .bottom-tab-item { padding: 2px 8px; font-size: 0.62rem; min-width: 44px; }
    .bottom-tab-item .tab-icon { font-size: 1.1rem; }

    .tag-group { gap: 3px; }
    .tag-enhanced { font-size: 0.68rem; padding: 2px 7px; border-radius: 14px; }

    .gradient-border-card { padding: 14px; border-radius: var(--radius-md); }
    .gradient-border-featured { padding: 14px; }

    .notification-badge { min-width: 16px; height: 16px; font-size: 0.6rem; padding: 0 4px; }
    .badge-wrapper .notification-badge { top: -4px; right: -6px; }

    .table-card-wrapper { border-radius: var(--radius-md); }

    .toggle-switch { width: 42px; height: 24px; }
    .toggle-switch .toggle-slider::before { width: 18px; height: 18px; }
    .toggle-switch input:checked ~ .toggle-slider::before { transform: translateX(18px); }

    /* Toast positions adjust */
    .toast-bottom-right { bottom: 16px; right: 10px; }
    .toast-bottom-left { bottom: 16px; left: 10px; }
}

/* Mobile landscape adjustments */
@media (max-height: 500px) and (orientation: landscape) {
    .toast-enhanced { top: 8px; }
    .toast-stack { top: 8px; }
    .bottom-tab-bar { display: none; }
    .glass-card-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Safe area for notched phones */
@supports (padding: max(0px)) {
    .bottom-tab-bar {
        padding-bottom: max(6px, env(safe-area-inset-bottom, 8px));
    }
    .toast-enhanced {
        top: max(24px, env(safe-area-inset-top, 0px));
    }
    .toast-stack {
        top: max(24px, env(safe-area-inset-top, 0px));
    }
}

/* ================================================================
   v1.0.0 增强: 文本选中、高对比度、内容可见性优化
   ================================================================ */

/* 文本选中样式 */
::selection {
    background: rgba(56, 189, 248, 0.25);
    color: var(--text-main);
}
::-moz-selection {
    background: rgba(56, 189, 248, 0.25);
    color: var(--text-main);
}

/* Windows 高对比度模式 */
@media (forced-colors: active) {
    .btn-primary-enhanced,
    .btn-enhanced {
        border: 2px solid ButtonText;
    }
    .glass-card-enhanced,
    .gradient-border-card {
        border: 1px solid ButtonText;
    }
    .navbar,
    .sidebar {
        border-bottom: 1px solid ButtonText;
    }
    .toggle-switch input:checked ~ .toggle-slider {
        background: Highlight;
    }
    .nav-link-enhanced.active {
        background: Highlight;
        color: HighlightText;
    }
}

/* 内容可见性优化 — 延迟渲染离屏内容 */
.glass-card-enhanced,
.stat-card-enhanced,
.gradient-border-card,
.table-card-wrapper {
    content-visibility: auto;
    contain-intrinsic-size: auto 200px;
}

/* 锚点滚动偏移（补偿固定导航栏） */
[id] {
    scroll-margin-top: calc(var(--navbar-height, 72px) + 16px);
}

/* 图片懒加载占位 */
img[loading="lazy"] {
    background: var(--border-subtle);
    min-height: 80px;
}
img[loading="lazy"]:not([src]) {
    animation: skeleton-loading 1.5s ease-in-out infinite;
    background: linear-gradient(
        90deg,
        var(--border-subtle) 25%,
        rgba(56, 189, 248, 0.05) 37%,
        var(--border-subtle) 63%
    );
    background-size: 200px 100%;
}

/* 长文本截断工具 */
.text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.text-truncate-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.text-truncate-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* 点击涟漪效果 */
@keyframes ripple-effect {
    to {
        transform: scale(4);
        opacity: 0;
    }
}
.ripple {
    position: relative;
    overflow: hidden;
}
.ripple::after {
    content: '';
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    pointer-events: none;
    background-image: radial-gradient(circle, rgba(255,255,255,.2) 10%, transparent 10.01%);
    background-repeat: no-repeat;
    background-position: 50%;
    transform: scale(10, 10);
    opacity: 0;
    transition: transform .5s, opacity 1s;
}
.ripple:active::after {
    transform: scale(0, 0);
    opacity: .3;
    transition: 0s;
}

/* 可拖拽区域光标 */
.draggable {
    cursor: grab;
}
.draggable:active {
    cursor: grabbing;
}

/* 禁用状态统一 */
.disabled,
[disabled],
[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
    cursor: not-allowed !important;
}

/* 空状态占位 */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 48px 24px;
    color: var(--text-muted);
    text-align: center;
    gap: 12px;
}
.empty-state-icon {
    font-size: 2.5rem;
    opacity: 0.4;
}
.empty-state-text {
    font-size: 0.9rem;
    max-width: 320px;
    line-height: 1.5;
}

/* Badge计数脉冲（仅数字变化时） */
@keyframes count-pop {
    0% { transform: scale(0.8); }
    40% { transform: scale(1.2); }
    100% { transform: scale(1); }
}
.count-animate {
    animation: count-pop 0.3s ease-out;
}

/* 打印增强：保留链接可读性、页眉页脚 */
@media print {
    @page {
        margin: 2cm;
        size: A4;
    }
    .navbar, .nav-links, footer, .btn-primary, .btn-outline,
    .hero-badges, .chat-input-area, .modal, .toast,
    .ws-indicator, .floating-actions, .particles-canvas,
    .bottom-tab-bar, .skip-to-content, .toast-stack {
        display: none !important;
    }
    body {
        font-size: 11pt;
        line-height: 1.6;
        color: #000 !important;
        background: #fff !important;
    }
    h1 { font-size: 22pt; page-break-after: avoid; }
    h2 { font-size: 16pt; page-break-after: avoid; }
    h3 { font-size: 13pt; page-break-after: avoid; }
    p, li, blockquote { orphans: 3; widows: 3; }
    pre, code, .table-card-wrapper, img {
        page-break-inside: avoid;
    }
    a[href] {
        color: #0056b3 !important;
        text-decoration: underline;
    }
    a[href^="#"]::after { content: none; }
}

/* ================================================================
   v1.0.0 增强: 页面过渡 & 全局加载进度条 (提取自 index.html)
   ================================================================ */

/* 页面切换过渡动画 */
.page {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
    position: absolute;
    width: 100%;
    visibility: hidden;
}
.page.active {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    position: relative;
    visibility: visible;
}
@media (prefers-reduced-motion: reduce) {
    .page { transition: none; transform: none; opacity: 1; }
}

/* 全局加载进度条 (NProgress风格) */
#globalLoadingBar {
    position: fixed; top: 0; left: 0; z-index: 100000;
    width: 100%; height: 3px; pointer-events: none;
}
#globalLoadingBar .bar {
    width: 0; height: 100%;
    background: linear-gradient(90deg, var(--cyan), var(--purple), var(--pink));
    border-radius: 0 2px 2px 0;
    transition: width 0.3s ease;
    box-shadow: 0 0 12px rgba(56,189,248,.5);
}
#globalLoadingBar .peg {
    position: absolute; right: 0; top: 0;
    width: 60px; height: 100%;
    background: linear-gradient(90deg, transparent, rgba(56,189,248,.6));
    border-radius: 0 2px 2px 0;
}
#globalLoadingBar.done .bar {
    width: 100%;
    transition: width 0.35s ease;
}
#globalLoadingBar.done .bar,
#globalLoadingBar.done .peg {
    opacity: 0;
    transition: opacity 0.4s ease 0.35s;
}

/* 全局盒子模型 */
* { margin: 0; padding: 0; box-sizing: border-box; }

/* 主内容区域焦点样式 */
#main-content:focus { outline: none; }
#main-content:focus-visible { outline: 2px solid var(--cyan); outline-offset: 4px; }

/* ================================================================
   v1.0.0 增强: 深色主题下额外组件修复
   ================================================================ */

/* 暗色主题 — 聊天输入框 */
[data-theme="dark"] .ds-input-wrapper,
@media (prefers-color-scheme: dark) {
    .ds-input-wrapper { background: var(--input-bg); }
    
    /* 暗色主题 — 图片右键菜单 */
    .img-context-menu { 
        background: var(--bg-elevated); 
        border-color: var(--border-subtle);
    }
    .img-ctx-item { color: var(--text-main); }
    .img-ctx-divider { background: var(--border-subtle); }
    
    /* 暗色主题 — AI消息气泡 */
    .ai .message-bubble { background: var(--bg-subtle); border-color: var(--border-subtle); }
    .chat-assistant .chat-bubble { background: var(--bg-subtle); border-color: var(--border-subtle); }
    
    /* 暗色主题 — Toast */
    .toast-notify { 
        background: var(--bg-elevated); 
        border-color: var(--border-subtle);
        box-shadow: 0 4px 16px rgba(0,0,0,.3);
    }
    
    /* 暗色主题 — 模板市场详情弹窗 */
    .mp-detail-modal { 
        background: var(--bg-elevated); 
        border-color: var(--border-subtle);
    }
    .mp-detail-name { color: var(--text-main); }
    .mp-detail-desc { color: var(--text-dim); }
    .mp-detail-close { background: var(--bg-subtle); }
    
    /* 暗色主题 — 支付方式选项 */
    .payment-method-option { background: var(--bg-subtle); border-color: var(--border-subtle); }
    .payment-order-summary { background: var(--bg-subtle); border-color: var(--border-subtle); }
    
    /* 暗色主题 — 视频卡片 */
    .video-card { background: var(--bg-card); }
    
    /* 暗色主题 — 友链 */
    .friend-item { background: var(--bg-subtle); border-color: var(--border-subtle); }
    
    /* 暗色主题 — 股票交易输入 */
    .trading-select, .trading-input-code, .trading-input-price, .trading-input-shares {
        background: var(--input-bg); border-color: var(--border-subtle);
    }
    .stock-chat-input-row input { background: var(--input-bg); border-color: var(--border-subtle); }
    
    /* 暗色主题 — 回测输入 */
    .backtest-input, .backtest-input-small, .backtest-select {
        background: var(--bg-glass); border-color: var(--border-glow);
    }
}

/**
 * Edos AI - 高级视觉设计系统 v1.0.0
 * 增强型CSS设计库：毛玻璃、发光、自定义滚动条、高级排版
 */

/* ============================================================
   1. 毛玻璃效果系统 (Glassmorphism)
   ============================================================ */
.glass {
  background: rgba(26, 26, 62, 0.65);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(0, 212, 255, 0.1);
}
.glass-strong {
  background: rgba(18, 18, 42, 0.85);
  backdrop-filter: blur(24px) saturate(200%);
  -webkit-backdrop-filter: blur(24px) saturate(200%);
  border: 1px solid rgba(0, 212, 255, 0.15);
}
.glass-light {
  background: rgba(26, 26, 62, 0.35);
  backdrop-filter: blur(8px) saturate(150%);
  -webkit-backdrop-filter: blur(8px) saturate(150%);
  border: 1px solid rgba(0, 212, 255, 0.06);
}
.glass-accent {
  background: rgba(168, 85, 247, 0.08);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(168, 85, 247, 0.15);
}

/* ============================================================
   2. 发光效果系统 (Glow Effects)
   ============================================================ */
.glow-primary {
  box-shadow: 0 0 20px rgba(0, 212, 255, 0.15),
              0 0 40px rgba(0, 212, 255, 0.06),
              0 0 60px rgba(0, 212, 255, 0.03);
}
.glow-accent {
  box-shadow: 0 0 20px rgba(168, 85, 247, 0.15),
              0 0 40px rgba(168, 85, 247, 0.06),
              0 0 60px rgba(168, 85, 247, 0.03);
}
.glow-success {
  box-shadow: 0 0 16px rgba(34, 197, 94, 0.12),
              0 0 32px rgba(34, 197, 94, 0.04);
}
.glow-warning {
  box-shadow: 0 0 16px rgba(245, 158, 11, 0.12),
              0 0 32px rgba(245, 158, 11, 0.04);
}
.glow-error {
  box-shadow: 0 0 16px rgba(239, 68, 68, 0.12),
              0 0 32px rgba(239, 68, 68, 0.04);
}

/* 发光边框 */
.glow-border-primary {
  border: 1px solid rgba(0, 212, 255, 0.3);
  box-shadow: 0 0 10px rgba(0, 212, 255, 0.1), inset 0 0 10px rgba(0, 212, 255, 0.02);
}
.glow-border-accent {
  border: 1px solid rgba(168, 85, 247, 0.3);
  box-shadow: 0 0 10px rgba(168, 85, 247, 0.1), inset 0 0 10px rgba(168, 85, 247, 0.02);
}

/* 顶部发光线条 */
.glow-line-top {
  position: relative;
  overflow: hidden;
}
.glow-line-top::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7), transparent);
  animation: glowLineShift 3s ease-in-out infinite;
}
@keyframes glowLineShift {
  0%, 100% { opacity: 0.7; }
  50% { opacity: 1; }
}

/* ============================================================
   3. 自定义滚动条 (Custom Scrollbar)
   ============================================================ */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: var(--edos-bg-primary, #0a0a1a);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb {
  background: rgba(0, 212, 255, 0.2);
  border-radius: 4px;
  border: 2px solid var(--edos-bg-primary, #0a0a1a);
}
::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 212, 255, 0.35);
}
::-webkit-scrollbar-thumb:active {
  background: rgba(0, 212, 255, 0.5);
}
::-webkit-scrollbar-corner {
  background: transparent;
}

/* 窄滚动条变体 */
.scrollbar-thin::-webkit-scrollbar { width: 4px; height: 4px; }
.scrollbar-thin::-webkit-scrollbar-thumb { border-width: 1px; }

/* Firefox滚动条 */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 212, 255, 0.2) var(--edos-bg-primary, #0a0a1a);
}

/* ============================================================
   4. 渐变背景 (Gradient Backgrounds)
   ============================================================ */
.grad-primary {
  background: linear-gradient(135deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
}
.grad-cyan-purple {
  background: linear-gradient(135deg, #38bdf8, #a78bfa);
}
.grad-cyan-pink {
  background: linear-gradient(135deg, #38bdf8 0%, #a78bfa 40%, #f472b6 80%);
}
.grad-green-cyan {
  background: linear-gradient(135deg, var(--edos-success, #22c55e), var(--edos-cyan, #38bdf8));
}
.grad-orange-pink {
  background: linear-gradient(135deg, var(--edos-warning, #f59e0b), var(--edos-pink, #f472b6));
}
.grad-dark-overlay {
  background: linear-gradient(180deg, rgba(10,10,26,0) 0%, rgba(10,10,26,0.8) 60%, rgba(10,10,26,1) 100%);
}
.grad-radial-cyan {
  background: radial-gradient(ellipse at center, rgba(0, 212, 255, 0.08) 0%, transparent 70%);
}
.grad-radial-accent {
  background: radial-gradient(ellipse at center, rgba(168, 85, 247, 0.08) 0%, transparent 70%);
}

/* 渐变文字 */
.grad-text {
  background: linear-gradient(135deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.grad-text-warm {
  background: linear-gradient(135deg, var(--edos-warning, #f59e0b), var(--edos-pink, #f472b6));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ============================================================
   5. 排版增强 (Typography Enhancement)
   ============================================================ */
.text-gradient { 
  background: linear-gradient(135deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.text-mono { font-family: var(--edos-font-mono, 'SF Mono', 'Fira Code', monospace); }
.text-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.text-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.text-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.text-xs  { font-size: 0.75rem;  line-height: 1.4; }
.text-sm  { font-size: 0.8125rem; line-height: 1.5; }
.text-base { font-size: 0.875rem;  line-height: 1.6; }
.text-md  { font-size: 1rem;     line-height: 1.6; }
.text-lg  { font-size: 1.125rem; line-height: 1.5; }
.text-xl  { font-size: 1.25rem;  line-height: 1.4; }
.text-2xl { font-size: 1.5rem;   line-height: 1.3; }
.text-3xl { font-size: 1.875rem; line-height: 1.2; }
.text-4xl { font-size: 2.25rem;  line-height: 1.1; }

.font-light { font-weight: 300; }
.font-normal { font-weight: 400; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.font-extrabold { font-weight: 800; }

/* 字母间距 */
.tracking-tight { letter-spacing: -0.025em; }
.tracking-normal { letter-spacing: 0; }
.tracking-wide { letter-spacing: 0.025em; }
.tracking-wider { letter-spacing: 0.05em; }
.tracking-widest { letter-spacing: 0.1em; }

/* ============================================================
   6. 间距工具类 (Spacing Utilities)
   ============================================================ */
.gap-xs { gap: var(--edos-spacing-xs, 4px); }
.gap-sm { gap: var(--edos-spacing-sm, 8px); }
.gap-md { gap: var(--edos-spacing-md, 16px); }
.gap-lg { gap: var(--edos-spacing-lg, 24px); }
.gap-xl { gap: var(--edos-spacing-xl, 32px); }

.p-xs { padding: var(--edos-spacing-xs, 4px); }
.p-sm { padding: var(--edos-spacing-sm, 8px); }
.p-md { padding: var(--edos-spacing-md, 16px); }
.p-lg { padding: var(--edos-spacing-lg, 24px); }
.p-xl { padding: var(--edos-spacing-xl, 32px); }

.mt-auto { margin-top: auto; }
.mb-auto { margin-bottom: auto; }
.ml-auto { margin-left: auto; }
.mr-auto { margin-right: auto; }
.mx-auto { margin-left: auto; margin-right: auto; }

/* ============================================================
   7. Flex布局工具类
   ============================================================ */
.flex { display: flex; }
.inline-flex { display: inline-flex; }
.flex-col { flex-direction: column; }
.flex-row { flex-direction: row; }
.flex-wrap { flex-wrap: wrap; }
.flex-nowrap { flex-wrap: nowrap; }
.flex-1 { flex: 1; }
.flex-auto { flex: 1 1 auto; }
.flex-none { flex: none; }

.items-start { align-items: flex-start; }
.items-center { align-items: center; }
.items-end { align-items: flex-end; }
.items-stretch { align-items: stretch; }
.items-baseline { align-items: baseline; }

.justify-start { justify-content: flex-start; }
.justify-center { justify-content: center; }
.justify-end { justify-content: flex-end; }
.justify-between { justify-content: space-between; }
.justify-around { justify-content: space-around; }
.justify-evenly { justify-content: space-evenly; }

/* ============================================================
   8. 圆角工具类
   ============================================================ */
.rounded-none { border-radius: 0; }
.rounded-sm { border-radius: var(--edos-radius-sm, 6px); }
.rounded-md { border-radius: var(--edos-radius-md, 10px); }
.rounded-lg { border-radius: var(--edos-radius-lg, 16px); }
.rounded-xl { border-radius: var(--edos-radius-xl, 24px); }
.rounded-full { border-radius: var(--edos-radius-full, 9999px); }

/* ============================================================
   9. 过渡动效工具类
   ============================================================ */
.transition-base { transition: all var(--edos-transition-normal, 300ms ease); }
.transition-fast { transition: all var(--edos-transition-fast, 150ms ease); }
.transition-slow { transition: all var(--edos-transition-slow, 500ms ease); }
.transition-transform { transition: transform var(--edos-transition-normal, 300ms ease); }
.transition-opacity { transition: opacity var(--edos-transition-normal, 300ms ease); }

.hover-lift:hover { transform: translateY(-2px); }
.hover-scale:hover { transform: scale(1.02); }
.hover-glow:hover { box-shadow: 0 0 20px rgba(0, 212, 255, 0.15); }

/* ============================================================
   10. 响应式可见性 (Responsive Visibility)
   ============================================================ */
.hidden { display: none !important; }
.block { display: block !important; }
.inline { display: inline !important; }

@media screen and (max-width: 640px) {
  .hidden-xs { display: none !important; }
  .block-xs { display: block !important; }
}
@media screen and (max-width: 768px) {
  .hidden-sm { display: none !important; }
  .block-sm { display: block !important; }
}
@media screen and (min-width: 769px) and (max-width: 1024px) {
  .hidden-md { display: none !important; }
  .block-md { display: block !important; }
}
@media screen and (min-width: 1025px) {
  .hidden-lg { display: none !important; }
  .block-lg { display: block !important; }
}

/* ============================================================
   11. 状态指示器 (Status Indicators)
   ============================================================ */
.status-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.status-dot.online  { background: var(--edos-success, #22c55e); box-shadow: 0 0 6px rgba(34,197,94,0.5); }
.status-dot.offline { background: var(--edos-text-tertiary, #7e7eaa); }
.status-dot.warning { background: var(--edos-warning, #f59e0b); box-shadow: 0 0 6px rgba(245,158,11,0.5); }
.status-dot.error   { background: var(--edos-error, #ef4444); box-shadow: 0 0 6px rgba(239,68,68,0.5); }
.status-dot.busy    { background: var(--edos-accent, #a855f7); box-shadow: 0 0 6px rgba(168,85,247,0.5); animation: statusPulse 1.5s ease-in-out infinite; }

@keyframes statusPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* ============================================================
   12. 分割线增强
   ============================================================ */
.divider {
  border: none;
  height: 1px;
  background: var(--edos-border-default, rgba(0, 212, 255, 0.12));
  margin: var(--edos-spacing-md, 16px) 0;
}
.divider-glow {
  border: none;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--edos-primary, #00d4ff), transparent);
  margin: var(--edos-spacing-md, 16px) 0;
  opacity: 0.3;
}
.divider-accent {
  border: none;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--edos-accent, #a855f7), transparent);
  margin: var(--edos-spacing-md, 16px) 0;
  opacity: 0.3;
}

/* ============================================================
   13. 聚焦环增强
   ============================================================ */
.focus-ring:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.25);
}
.focus-ring-accent:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.25);
}

/* ============================================================
   14. 骨架屏增强
   ============================================================ */
.skeleton {
  background: linear-gradient(90deg,
    var(--edos-bg-elevated, #252552) 25%,
    var(--edos-bg-hover, #2a2a5a) 37%,
    var(--edos-bg-elevated, #252552) 63%
  );
  background-size: 400% 100%;
  animation: skeletonShimmer 1.8s ease-in-out infinite;
  border-radius: var(--edos-radius-md, 10px);
}
.skeleton-text { height: 14px; margin-bottom: 8px; width: 100%; }
.skeleton-title { height: 20px; width: 60%; margin-bottom: 12px; }
.skeleton-avatar { width: 40px; height: 40px; border-radius: 50%; }
.skeleton-btn { height: 36px; width: 80px; border-radius: var(--edos-radius-md, 10px); }
.skeleton-card { height: 120px; width: 100%; }

@keyframes skeletonShimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* ============================================================
   15. 脉冲动画工具类
   ============================================================ */
.animate-pulse { animation: softPulse 2s ease-in-out infinite; }
@keyframes softPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}
.animate-spin { animation: spin 1s linear infinite; }
@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.animate-float { animation: float 3s ease-in-out infinite; }
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* ============================================================
   16. 背景装饰图案
   ============================================================ */
.bg-noise {
  position: relative;
}
.bg-noise::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.015;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  pointer-events: none;
}

.bg-grid {
  position: relative;
}
.bg-grid::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.03;
  background-image:
    linear-gradient(rgba(0, 212, 255, 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 212, 255, 0.1) 1px, transparent 1px);
  background-size: 40px 40px;
  pointer-events: none;
}

.bg-dots {
  position: relative;
}
.bg-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.05;
  background-image: radial-gradient(circle, rgba(0, 212, 255, 0.5) 1px, transparent 1px);
  background-size: 24px 24px;
  pointer-events: none;
}

/**
 * Edos AI - 深色主题视觉增强系统 v1.0.0
 * 赛博朋克/空间主题装饰元素、动态边框、粒子特效、霓虹风格
 */

/* ============================================================
   1. 霓虹文字效果 (Neon Text)
   ============================================================ */
.text-neon-cyan {
  color: var(--edos-primary, #00d4ff);
  text-shadow: 0 0 10px rgba(0, 212, 255, 0.5),
               0 0 20px rgba(0, 212, 255, 0.3),
               0 0 40px rgba(0, 212, 255, 0.15);
}
.text-neon-purple {
  color: var(--edos-accent, #a855f7);
  text-shadow: 0 0 10px rgba(168, 85, 247, 0.5),
               0 0 20px rgba(168, 85, 247, 0.3),
               0 0 40px rgba(168, 85, 247, 0.15);
}
.text-neon-pink {
  color: var(--edos-pink, #f472b6);
  text-shadow: 0 0 10px rgba(244, 114, 182, 0.5),
               0 0 20px rgba(244, 114, 182, 0.3),
               0 0 40px rgba(244, 114, 182, 0.15);
}

/* ============================================================
   2. 动态光晕边框 (Animated Glow Border)
   ============================================================ */
.border-glow-animated {
  position: relative;
  border: 1px solid transparent;
  background-clip: padding-box;
}
.border-glow-animated::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(
    135deg,
    var(--edos-primary, #00d4ff),
    var(--edos-accent, #a855f7),
    var(--edos-primary, #00d4ff)
  );
  background-size: 200% 200%;
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: borderGlowRotate 3s linear infinite;
}
@keyframes borderGlowRotate {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* 静态渐变边框 */
.border-gradient {
  position: relative;
  border: 1px solid transparent;
  background-clip: padding-box;
}
.border-gradient::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, var(--edos-primary, #00d4ff), var(--edos-accent, #a855f7));
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

/* ============================================================
   3. 脉冲光环效果 (Pulse Ring)
   ============================================================ */
.pulse-ring {
  position: relative;
}
.pulse-ring::before,
.pulse-ring::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  border: 1px solid rgba(0, 212, 255, 0.3);
  animation: pulseRing 2s ease-out infinite;
}
.pulse-ring::after {
  animation-delay: 0.5s;
}
@keyframes pulseRing {
  0% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1.08); opacity: 0; }
}

/* ============================================================
   4. 扫描线效果 (Scan Line)
   ============================================================ */
.scan-line {
  position: relative;
  overflow: hidden;
}
.scan-line::after {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg,
    transparent,
    rgba(0, 212, 255, 0.3),
    rgba(0, 212, 255, 0.6),
    rgba(0, 212, 255, 0.3),
    transparent
  );
  animation: scanLineMove 3s ease-in-out infinite;
}
@keyframes scanLineMove {
  0% { top: 0; }
  100% { top: 100%; }
}

/* ============================================================
   5. 网格背景 (Grid Background)
   ============================================================ */
.bg-tech-grid {
  background-image:
    linear-gradient(rgba(0, 212, 255, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 212, 255, 0.06) 1px, transparent 1px);
  background-size: 40px 40px;
}
.bg-tech-grid-sm {
  background-image:
    linear-gradient(rgba(0, 212, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 212, 255, 0.04) 1px, transparent 1px);
  background-size: 20px 20px;
}

/* ============================================================
   6. 星空背景 (Starfield Background)
   ============================================================ */
.bg-starfield {
  position: relative;
}
.bg-starfield::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.4;
  background-image:
    radial-gradient(1px 1px at 20px 30px, rgba(255,255,255,0.4), transparent),
    radial-gradient(1px 1px at 40px 70px, rgba(255,255,255,0.3), transparent),
    radial-gradient(1px 1px at 50px 160px, rgba(255,255,255,0.5), transparent),
    radial-gradient(1px 1px at 90px 40px, rgba(255,255,255,0.3), transparent),
    radial-gradient(1px 1px at 130px 80px, rgba(255,255,255,0.4), transparent),
    radial-gradient(1px 1px at 160px 120px, rgba(255,255,255,0.3), transparent),
    radial-gradient(1px 1px at 200px 50px, rgba(0,212,255,0.5), transparent),
    radial-gradient(1px 1px at 250px 150px, rgba(168,85,247,0.4), transparent),
    radial-gradient(1px 1px at 300px 30px, rgba(255,255,255,0.3), transparent);
  background-size: 360px 200px;
  pointer-events: none;
  animation: starfieldShift 60s linear infinite;
}
@keyframes starfieldShift {
  0% { background-position: 0 0; }
  100% { background-position: 360px 0; }
}

/* ============================================================
   7. 彩虹光晕装饰 (Iridescent Glow Decoration)
   ============================================================ */
.decor-glow-top-right {
  position: absolute;
  top: -100px; right: -100px;
  width: 300px; height: 300px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 212, 255, 0.1), transparent 70%);
  pointer-events: none;
  filter: blur(40px);
}
.decor-glow-bottom-left {
  position: absolute;
  bottom: -100px; left: -100px;
  width: 280px; height: 280px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(168, 85, 247, 0.1), transparent 70%);
  pointer-events: none;
  filter: blur(40px);
}
.decor-glow-center {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 400px; height: 400px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 212, 255, 0.04), transparent 60%);
  pointer-events: none;
  filter: blur(60px);
}

/* ============================================================
   8. 数据流线条 (Data Flow Lines)
   ============================================================ */
.data-flow {
  position: relative;
}
.data-flow::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg,
    transparent,
    rgba(0, 212, 255, 0.04),
    transparent
  );
  animation: dataFlow 4s ease-in-out infinite;
}
@keyframes dataFlow {
  0% { left: -100%; }
  100% { left: 200%; }
}

/* ============================================================
   9. 霓虹输入框 (Neon Input)
   ============================================================ */
.input-neon {
  background: rgba(10, 16, 40, 0.6);
  border: 1px solid rgba(0, 212, 255, 0.2);
  border-radius: var(--edos-radius-md, 10px);
  padding: 10px 16px;
  color: var(--edos-text-primary, #f0f0ff);
  font-size: 0.875rem;
  outline: none;
  transition: all var(--edos-transition-fast, 150ms ease);
  width: 100%;
}
.input-neon:focus {
  border-color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 15px rgba(0, 212, 255, 0.15),
              0 0 30px rgba(0, 212, 255, 0.06),
              inset 0 0 15px rgba(0, 212, 255, 0.02);
}
.input-neon::placeholder {
  color: var(--edos-text-tertiary, #7e7eaa);
}

/* ============================================================
   10. 霓虹按钮 (Neon Button)
   ============================================================ */
.btn-neon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 24px;
  border: 1px solid rgba(0, 212, 255, 0.4);
  border-radius: var(--edos-radius-md, 10px);
  background: transparent;
  color: var(--edos-primary, #00d4ff);
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--edos-transition-fast, 150ms ease);
  position: relative;
  overflow: hidden;
}
.btn-neon::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(0, 212, 255, 0.1), rgba(168, 85, 247, 0.1));
  opacity: 0;
  transition: opacity var(--edos-transition-fast, 150ms ease);
}
.btn-neon:hover {
  border-color: var(--edos-primary, #00d4ff);
  box-shadow: 0 0 20px rgba(0, 212, 255, 0.2),
              0 0 40px rgba(0, 212, 255, 0.08);
  transform: translateY(-1px);
}
.btn-neon:hover::before { opacity: 1; }
.btn-neon:active { transform: translateY(0); }

.btn-neon-purple {
  border-color: rgba(168, 85, 247, 0.4);
  color: var(--edos-accent, #a855f7);
}
.btn-neon-purple::before {
  background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(244, 114, 182, 0.1));
}
.btn-neon-purple:hover {
  border-color: var(--edos-accent, #a855f7);
  box-shadow: 0 0 20px rgba(168, 85, 247, 0.2),
              0 0 40px rgba(168, 85, 247, 0.08);
}

/* ============================================================
   11. 终端风格窗口 (Terminal Window)
   ============================================================ */
.terminal-window {
  background: rgba(10, 16, 40, 0.95);
  border: 1px solid rgba(0, 212, 255, 0.15);
  border-radius: var(--edos-radius-lg, 16px);
  overflow: hidden;
  box-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
}
.terminal-window .terminal-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  background: rgba(255, 255, 255, 0.03);
  border-bottom: 1px solid rgba(0, 212, 255, 0.08);
}
.terminal-window .terminal-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
}
.terminal-window .terminal-dot.red   { background: #ff5f56; }
.terminal-window .terminal-dot.yellow { background: #ffbd2e; }
.terminal-window .terminal-dot.green  { background: #27c93f; }
.terminal-window .terminal-title {
  flex: 1;
  text-align: center;
  font-size: 0.75rem;
  color: var(--edos-text-tertiary, #7e7eaa);
  font-family: var(--edos-font-mono, monospace);
}
.terminal-window .terminal-body {
  padding: 16px;
  font-family: var(--edos-font-mono, 'SF Mono', 'Fira Code', monospace);
  font-size: 0.8125rem;
  color: var(--edos-primary, #00d4ff);
  line-height: 1.7;
  min-height: 100px;
  max-height: 300px;
  overflow-y: auto;
}
.terminal-window .terminal-body .prompt {
  color: var(--edos-success, #22c55e);
  margin-right: 8px;
}
.terminal-window .terminal-body .output {
  color: var(--edos-text-secondary, #a0a0cc);
}

/* ============================================================
   12. 卡牌翻转效果 (Card Flip)
   ============================================================ */
.card-flip {
  perspective: 1000px;
}
.card-flip-inner {
  position: relative;
  width: 100%; height: 100%;
  transition: transform 0.6s;
  transform-style: preserve-3d;
}
.card-flip:hover .card-flip-inner {
  transform: rotateY(180deg);
}
.card-flip-front,
.card-flip-back {
  position: absolute;
  width: 100%; height: 100%;
  backface-visibility: hidden;
  border-radius: var(--edos-radius-lg, 16px);
}
.card-flip-front {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0, 212, 255, 0.12));
}
.card-flip-back {
  background: var(--edos-bg-elevated, #252552);
  border: 1px solid var(--edos-border-glow, rgba(0, 212, 255, 0.15));
  transform: rotateY(180deg);
}

/* ============================================================
   13. 浮动粒子装饰 (Floating Particle Orbs)
   ============================================================ */
.particle-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(30px);
}
.particle-orb.cyan {
  background: rgba(0, 212, 255, 0.08);
  animation: orbFloat1 8s ease-in-out infinite;
}
.particle-orb.purple {
  background: rgba(168, 85, 247, 0.08);
  animation: orbFloat2 10s ease-in-out infinite;
}
.particle-orb.pink {
  background: rgba(244, 114, 182, 0.06);
  animation: orbFloat3 12s ease-in-out infinite;
}
@keyframes orbFloat1 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  25% { transform: translate(20px, -15px) scale(1.05); }
  50% { transform: translate(-10px, -30px) scale(0.95); }
  75% { transform: translate(-25px, -10px) scale(1.03); }
}
@keyframes orbFloat2 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  25% { transform: translate(-20px, -20px) scale(1.04); }
  50% { transform: translate(15px, -25px) scale(0.96); }
  75% { transform: translate(10px, -5px) scale(1.02); }
}
@keyframes orbFloat3 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33% { transform: translate(15px, -10px) scale(1.03); }
  66% { transform: translate(-15px, -20px) scale(0.97); }
}

/* ============================================================
   14. 闪烁光标 (Blinking Cursor)
   ============================================================ */
.cursor-blink::after {
  content: '|';
  color: var(--edos-primary, #00d4ff);
  animation: cursorBlink 1s step-end infinite;
  font-weight: 300;
}
@keyframes cursorBlink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

/* ============================================================
   15. 六角形网格背景 (Hex Grid Background)
   ============================================================ */
.bg-hex {
  position: relative;
}
.bg-hex::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cpath fill='none' stroke='%2300d4ff' stroke-width='0.5' d='M13.99 0L0 8.08v16.16L13.99 32.3 28 24.24V8.08L13.99 0zm0 16.15L7 12.12l6.99-4.04L21 12.12l-7.01 4.03z'/%3E%3C/svg%3E");
  pointer-events: none;
}

/* ============================================================
   16. 深度阴影层级 (Depth Shadows)
   ============================================================ */
.shadow-depth-1 { box-shadow: 0 2px 4px rgba(0,0,0,0.3); }
.shadow-depth-2 { box-shadow: 0 4px 12px rgba(0,0,0,0.4); }
.shadow-depth-3 { box-shadow: 0 8px 24px rgba(0,0,0,0.5); }
.shadow-depth-4 { box-shadow: 0 12px 36px rgba(0,0,0,0.55); }
.shadow-depth-5 { box-shadow: 0 20px 60px rgba(0,0,0,0.6); }

/* 带色偏的阴影 */
.shadow-cyan { box-shadow: 0 8px 32px rgba(0, 212, 255, 0.1); }
.shadow-purple { box-shadow: 0 8px 32px rgba(168, 85, 247, 0.1); }
.shadow-cyan-lg { box-shadow: 0 16px 48px rgba(0, 212, 255, 0.12); }

/* ============================================================
   17. 事件时间线 (Event Timeline)
   ============================================================ */
.timeline {
  position: relative;
  padding-left: 30px;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 11px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(180deg,
    var(--edos-primary, #00d4ff),
    var(--edos-accent, #a855f7),
    rgba(168, 85, 247, 0.3)
  );
}
.timeline-item {
  position: relative;
  padding-bottom: var(--edos-spacing-lg, 24px);
}
.timeline-item:last-child { padding-bottom: 0; }
.timeline-item::before {
  content: '';
  position: absolute;
  left: -23px;
  top: 4px;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--edos-primary, #00d4ff);
  border: 2px solid var(--edos-bg-secondary, #12122a);
  box-shadow: 0 0 8px rgba(0, 212, 255, 0.4);
}
.timeline-item.milestone::before {
  background: var(--edos-accent, #a855f7);
  box-shadow: 0 0 8px rgba(168, 85, 247, 0.4);
  width: 14px; height: 14px;
  left: -25px;
  top: 2px;
}
.timeline-item .timeline-time {
  font-size: 0.75rem;
  color: var(--edos-text-tertiary, #7e7eaa);
  margin-bottom: 4px;
}
.timeline-item .timeline-content {
  font-size: 0.875rem;
  color: var(--edos-text-primary, #f0f0ff);
  line-height: 1.5;
}

/* ============================================================
   18. 代码块样式 (Code Block)
   ============================================================ */
.code-block {
  background: rgba(10, 16, 40, 0.8);
  border: 1px solid rgba(0, 212, 255, 0.12);
  border-radius: var(--edos-radius-md, 10px);
  padding: var(--edos-spacing-md, 16px);
  font-family: var(--edos-font-mono, 'SF Mono', 'Fira Code', monospace);
  font-size: 0.8125rem;
  line-height: 1.7;
  overflow-x: auto;
  color: var(--edos-text-secondary, #a0a0cc);
}
.code-block .keyword { color: var(--edos-accent, #a855f7); }
.code-block .string  { color: var(--edos-success, #22c55e); }
.code-block .number  { color: var(--edos-warning, #f59e0b); }
.code-block .comment { color: var(--edos-text-tertiary, #7e7eaa); font-style: italic; }
.code-block .function { color: var(--edos-primary, #00d4ff); }

/**
 * Edos AI - 状态反馈与动画系统 v1.0.0
 * 空状态、加载状态、错误状态、成功状态、页面过渡、微交互动画
 */

/* ============================================================
   1. 空状态 (Empty States)
   ============================================================ */
.edos-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 48px 24px;
  min-height: 200px;
}
.edos-empty-icon {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: rgba(255,255,255,.03);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  margin-bottom: 16px;
  color: var(--edos-text-tertiary, #7e7eaa);
}
.edos-empty-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
  margin-bottom: 8px;
}
.edos-empty-description {
  font-size: 0.875rem;
  color: var(--edos-text-secondary, #a0a0cc);
  max-width: 360px;
  line-height: 1.5;
  margin-bottom: 20px;
}
.edos-empty-action {
  margin-top: 4px;
}

/* 空状态变体 */
.edos-empty-state.compact {
  padding: 24px 16px;
  min-height: 120px;
}
.edos-empty-state.compact .edos-empty-icon {
  width: 48px;
  height: 48px;
  font-size: 1.25rem;
  margin-bottom: 8px;
}
.edos-empty-state.compact .edos-empty-title {
  font-size: 0.9375rem;
}
.edos-empty-state.card {
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.08));
  border-radius: var(--edos-radius-lg, 16px);
}

/* ============================================================
   2. 加载状态 (Loading States)
   ============================================================ */

/* 基础旋转加载器 */
.edos-spinner {
  display: inline-block;
  width: 24px;
  height: 24px;
  border: 3px solid rgba(255,255,255,.1);
  border-top-color: var(--edos-primary, #00d4ff);
  border-radius: 50%;
  animation: spinnerRotate .7s linear infinite;
}
@keyframes spinnerRotate {
  to { transform: rotate(360deg); }
}

/* 加载器尺寸 */
.edos-spinner-sm { width: 16px; height: 16px; border-width: 2px; }
.edos-spinner-lg { width: 40px; height: 40px; border-width: 4px; }
.edos-spinner-xl { width: 56px; height: 56px; border-width: 5px; }

/* 加载器颜色变体 */
.edos-spinner.accent { border-top-color: var(--edos-accent, #a855f7); }
.edos-spinner.success { border-top-color: var(--edos-success, #22c55e); }
.edos-spinner.white { border-color: rgba(255,255,255,.15); border-top-color: #fff; }

/* 点状加载器 */
.edos-dots-loader {
  display: inline-flex;
  gap: 6px;
  align-items: center;
}
.edos-dots-loader .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--edos-primary, #00d4ff);
  animation: dotsBounce 1.4s ease-in-out infinite both;
}
.edos-dots-loader .dot:nth-child(1) { animation-delay: 0s; }
.edos-dots-loader .dot:nth-child(2) { animation-delay: .16s; }
.edos-dots-loader .dot:nth-child(3) { animation-delay: .32s; }
@keyframes dotsBounce {
  0%, 80%, 100% { transform: scale(0); opacity: .3; }
  40% { transform: scale(1); opacity: 1; }
}

/* 脉冲加载器 */
.edos-pulse-loader {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--edos-primary, #00d4ff);
  animation: pulseLoader 1.2s ease-in-out infinite;
}
@keyframes pulseLoader {
  0%, 100% { transform: scale(.7); opacity: .4; }
  50% { transform: scale(1.2); opacity: 1; }
}

/* 进度条加载器 */
.edos-progress-loader {
  width: 100%;
  height: 3px;
  background: rgba(255,255,255,.06);
  border-radius: 3px;
  overflow: hidden;
  position: relative;
}
.edos-progress-loader::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 30%;
  background: linear-gradient(90deg, transparent, var(--edos-primary, #00d4ff), transparent);
  border-radius: 3px;
  animation: progressSlide 1.5s ease-in-out infinite;
}
@keyframes progressSlide {
  0% { left: -30%; }
  100% { left: 100%; }
}

/* 完整页面加载 */
.edos-page-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 300px;
  gap: 16px;
  color: var(--edos-text-secondary, #a0a0cc);
  font-size: 0.875rem;
}

/* 按钮内加载 */
.edos-btn-loading {
  position: relative;
  pointer-events: none;
  opacity: .8;
}
.edos-btn-loading::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  border: 2px solid transparent;
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spinnerRotate .7s linear infinite;
}
.edos-btn-loading .btn-text {
  visibility: hidden;
}

/* ============================================================
   3. 错误状态 (Error States)
   ============================================================ */
.edos-error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 24px;
}
.edos-error-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: rgba(239,68,68,.1);
  color: var(--edos-error, #ef4444);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin-bottom: 12px;
}
.edos-error-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--edos-error, #ef4444);
  margin-bottom: 6px;
}
.edos-error-message {
  font-size: 0.8125rem;
  color: var(--edos-text-secondary, #a0a0cc);
  max-width: 320px;
  line-height: 1.5;
  margin-bottom: 16px;
}
.edos-error-retry {
  margin-top: 4px;
}

/* 内联错误提示 */
.edos-inline-error {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  background: rgba(239,68,68,.08);
  border: 1px solid rgba(239,68,68,.2);
  border-radius: var(--edos-radius-md, 10px);
  font-size: 0.8125rem;
  color: var(--edos-error, #ef4444);
  line-height: 1.5;
}
.edos-inline-error .error-icon {
  flex-shrink: 0;
  margin-top: 1px;
}

/* ============================================================
   4. 成功状态 (Success States)
   ============================================================ */
.edos-success-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 24px;
}
.edos-success-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: rgba(34,197,94,.1);
  color: var(--edos-success, #22c55e);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin-bottom: 12px;
  animation: successPopIn .4s ease;
}
@keyframes successPopIn {
  0% { transform: scale(0); opacity: 0; }
  60% { transform: scale(1.15); }
  100% { transform: scale(1); opacity: 1; }
}
.edos-success-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--edos-text-primary, #f0f0ff);
  margin-bottom: 6px;
}
.edos-success-message {
  font-size: 0.8125rem;
  color: var(--edos-text-secondary, #a0a0cc);
  max-width: 320px;
  line-height: 1.5;
}

/* 成功勾选动画 */
.edos-checkmark {
  width: 24px;
  height: 24px;
  position: relative;
}
.edos-checkmark::before {
  content: '';
  position: absolute;
  top: 2px;
  left: 7px;
  width: 10px;
  height: 17px;
  border: solid var(--edos-success, #22c55e);
  border-width: 0 3px 3px 0;
  transform: rotate(45deg);
  animation: checkmarkDraw .4s ease;
}
@keyframes checkmarkDraw {
  0% { clip-path: inset(100% 0 0 0); }
  100% { clip-path: inset(0 0 0 0); }
}

/* ============================================================
   5. 信息提示状态 (Info / Warning States)
   ============================================================ */
.edos-info-state {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  background: rgba(59,130,246,.08);
  border: 1px solid rgba(59,130,246,.2);
  border-radius: var(--edos-radius-md, 10px);
  font-size: 0.8125rem;
  color: var(--edos-info, #3b82f6);
  line-height: 1.5;
}

.edos-warning-state {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  background: rgba(245,158,11,.08);
  border: 1px solid rgba(245,158,11,.2);
  border-radius: var(--edos-radius-md, 10px);
  font-size: 0.8125rem;
  color: var(--edos-warning, #f59e0b);
  line-height: 1.5;
}

/* 提示横幅 (Banner) */
.edos-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  border-radius: var(--edos-radius-md, 10px);
  font-size: 0.875rem;
  line-height: 1.5;
  margin-bottom: var(--edos-spacing-md, 16px);
}
.edos-banner.info {
  background: rgba(59,130,246,.1);
  border: 1px solid rgba(59,130,246,.2);
  color: var(--edos-info, #3b82f6);
}
.edos-banner.warning {
  background: rgba(245,158,11,.1);
  border: 1px solid rgba(245,158,11,.2);
  color: var(--edos-warning, #f59e0b);
}
.edos-banner.error {
  background: rgba(239,68,68,.1);
  border: 1px solid rgba(239,68,68,.2);
  color: var(--edos-error, #ef4444);
}
.edos-banner.success {
  background: rgba(34,197,94,.1);
  border: 1px solid rgba(34,197,94,.2);
  color: var(--edos-success, #22c55e);
}
.edos-banner-close {
  background: none;
  border: none;
  color: inherit;
  opacity: .6;
  cursor: pointer;
  font-size: 1.25rem;
  padding: 0;
  line-height: 1;
  flex-shrink: 0;
}
.edos-banner-close:hover {
  opacity: 1;
}

/* ============================================================
   6. 页面过渡动画 (Page Transitions)
   ============================================================ */
.edos-page-enter {
  animation: pageEnter .35s ease;
}
@keyframes pageEnter {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.edos-page-exit {
  animation: pageExit .25s ease forwards;
}
@keyframes pageExit {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-8px);
  }
}

/* 元素进入动画 */
.edos-fade-in {
  animation: fadeIn .3s ease;
}
.edos-fade-in-up {
  animation: fadeInUp .4s ease;
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 交错动画 (用于列表) */
.edos-stagger-list > * {
  opacity: 0;
  animation: fadeInUp .4s ease forwards;
}
.edos-stagger-list > *:nth-child(1) { animation-delay: 0s; }
.edos-stagger-list > *:nth-child(2) { animation-delay: .05s; }
.edos-stagger-list > *:nth-child(3) { animation-delay: .1s; }
.edos-stagger-list > *:nth-child(4) { animation-delay: .15s; }
.edos-stagger-list > *:nth-child(5) { animation-delay: .2s; }
.edos-stagger-list > *:nth-child(6) { animation-delay: .25s; }
.edos-stagger-list > *:nth-child(7) { animation-delay: .3s; }
.edos-stagger-list > *:nth-child(8) { animation-delay: .35s; }
.edos-stagger-list > *:nth-child(9) { animation-delay: .4s; }
.edos-stagger-list > *:nth-child(10) { animation-delay: .45s; }

/* ============================================================
   7. 微交互动画 (Micro-interactions)
   ============================================================ */

/* 悬停抬升 */
.edos-hover-lift {
  transition: transform var(--edos-transition-fast), box-shadow var(--edos-transition-fast);
}
.edos-hover-lift:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0,0,0,.3);
}

/* 悬停缩放 */
.edos-hover-scale {
  transition: transform var(--edos-transition-fast);
}
.edos-hover-scale:hover {
  transform: scale(1.04);
}

/* 点击反馈 */
.edos-tap-active:active {
  transform: scale(.97);
  transition: transform .1s ease;
}

/* 波纹效果 */
.edos-ripple {
  position: relative;
  overflow: hidden;
}
.edos-ripple::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, rgba(255,255,255,.15) 10%, transparent 10%);
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  transition: all .5s;
}
.edos-ripple:active::after {
  background-size: 0;
  opacity: 1;
  transition: 0s;
}

/* 抖动效果 */
.edos-shake {
  animation: shake .5s ease;
}
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

/* 弹跳效果 */
.edos-bounce-in {
  animation: bounceIn .5s ease;
}
@keyframes bounceIn {
  0% { transform: scale(.3); opacity: 0; }
  50% { transform: scale(1.05); }
  70% { transform: scale(.95); }
  100% { transform: scale(1); opacity: 1; }
}

/* 滑入效果 */
.edos-slide-in-left {
  animation: slideInLeft .4s ease;
}
.edos-slide-in-right {
  animation: slideInRight .4s ease;
}
@keyframes slideInLeft {
  from { transform: translateX(-30px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
@keyframes slideInRight {
  from { transform: translateX(30px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

/* ============================================================
   8. 状态指示器 (Status Indicators)
   ============================================================ */
.edos-status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.edos-status-dot.online  { background: var(--edos-success, #22c55e); }
.edos-status-dot.offline { background: var(--edos-text-tertiary, #7e7eaa); }
.edos-status-dot.busy    { background: var(--edos-error, #ef4444); }
.edos-status-dot.idle    { background: var(--edos-warning, #f59e0b); }

/* 在线状态脉冲点 */
.edos-status-dot.pulse {
  position: relative;
}
.edos-status-dot.pulse::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: inherit;
  animation: statusPulse 1.5s ease-out infinite;
}
@keyframes statusPulse {
  0% { transform: scale(1); opacity: .7; }
  100% { transform: scale(2.5); opacity: 0; }
}

/* 状态标签 */
.edos-status-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: 0.75rem;
  font-weight: 600;
}
.edos-status-label.active   { background: rgba(34,197,94,.12); color: var(--edos-success, #22c55e); }
.edos-status-label.inactive { background: rgba(120,140,180,.12); color: var(--edos-text-tertiary, #7e7eaa); }
.edos-status-label.pending  { background: rgba(245,158,11,.12); color: var(--edos-warning, #f59e0b); }
.edos-status-label.error    { background: rgba(239,68,68,.12); color: var(--edos-error, #ef4444); }
.edos-status-label.running  { background: rgba(59,130,246,.12); color: var(--edos-info, #3b82f6); }

/* ============================================================
   9. 骨架屏系统 (Skeleton System)
   ============================================================ */
.edos-skeleton {
  background: linear-gradient(90deg, rgba(255,255,255,.04) 25%, rgba(255,255,255,.08) 50%, rgba(255,255,255,.04) 75%);
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes skeletonShimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* 骨架屏变体 */
.edos-skeleton-text {
  height: 14px;
  margin-bottom: 8px;
}
.edos-skeleton-title {
  height: 20px;
  width: 60%;
  margin-bottom: 12px;
}
.edos-skeleton-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
}
.edos-skeleton-card {
  height: 120px;
  border-radius: var(--edos-radius-md, 10px);
}
.edos-skeleton-circle {
  width: 64px;
  height: 64px;
  border-radius: 50%;
}

/* ============================================================
   10. 结果/反馈状态组合 (Result Patterns)
   ============================================================ */

/* 操作结果卡片 */
.edos-result-card {
  text-align: center;
  padding: 48px 24px;
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.1));
  border-radius: var(--edos-radius-xl, 24px);
  max-width: 480px;
  margin: 0 auto;
}

/* 复制成功提示 */
.edos-copied-tooltip {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 10px 24px;
  background: var(--edos-success, #22c55e);
  color: #000;
  font-size: 0.875rem;
  font-weight: 600;
  border-radius: 8px;
  z-index: 99999;
  animation: copiedPopIn .3s ease, copiedFadeOut .3s ease 1.7s forwards;
  pointer-events: none;
}
@keyframes copiedPopIn {
  from { opacity: 0; transform: translate(-50%, -50%) scale(.8); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes copiedFadeOut {
  to { opacity: 0; transform: translate(-50%, -50%) translateY(-10px); }
}

/* ============================================================
   11. 滚动相关动画 (Scroll Animations)
   ============================================================ */
.edos-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .6s ease, transform .6s ease;
}
.edos-reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

/* 回到顶部按钮 */
.edos-back-to-top {
  position: fixed;
  bottom: 32px;
  right: 32px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--edos-bg-card, rgba(255, 255, 255, 0.92));
  border: 1px solid var(--edos-border-default, rgba(0,212,255,.15));
  color: var(--edos-primary, #00d4ff);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 1.25rem;
  box-shadow: 0 4px 16px rgba(0,0,0,.3);
  transition: all var(--edos-transition-fast);
  z-index: 999;
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
}
.edos-back-to-top.visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.edos-back-to-top:hover {
  background: var(--edos-primary, #00d4ff);
  color: #000;
  box-shadow: 0 0 20px rgba(0,212,255,.2);
}

/* ============================================================
   12. 打印样式
   ============================================================ */
@media print {
  .edos-sidebar,
  .edos-header,
  .edos-back-to-top,
  .edos-toast-container,
  .edos-modal-overlay,
  .edos-drawer-overlay {
    display: none !important;
  }
  .edos-main {
    margin-left: 0 !important;
  }
  body {
    background: #fff !important;
    color: #000 !important;
  }
}

/* ============================================================
   13. 减少动画 (Reduced Motion) - 无障碍
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

