diff --git a/embryo-frontend/index.html b/embryo-frontend/index.html index 839e840..9130581 100644 --- a/embryo-frontend/index.html +++ b/embryo-frontend/index.html @@ -1,10 +1,11 @@ - + - Vite + TS + + Digital Embryo | 数字胚胎发育时空转录组图谱
diff --git a/embryo-frontend/src/App.tsx b/embryo-frontend/src/App.tsx index eae7be9..68b77cb 100644 --- a/embryo-frontend/src/App.tsx +++ b/embryo-frontend/src/App.tsx @@ -1,13 +1,28 @@ import React from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import Navigation from "./components/Navigation"; +import HomePage from "./pages/HomePage"; import GeneView from "./pages/GeneView"; +import SpatialClustering from "./pages/SpatialClustering"; +import Resource from "./pages/Resource"; +import Download from "./pages/Download"; +import "./style.css"; function App() { return ( - - } /> - +
+ +
+ + } /> + } /> + } /> + } /> + } /> + +
+
); } diff --git a/embryo-frontend/src/components/Navigation.tsx b/embryo-frontend/src/components/Navigation.tsx new file mode 100644 index 0000000..c8fea41 --- /dev/null +++ b/embryo-frontend/src/components/Navigation.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import { Link, useLocation } from "react-router-dom"; + +const Navigation: React.FC = () => { + const location = useLocation(); + + const navigationItems = [ + { path: "/", label: "Home", name: "首页" }, + { path: "/spatial-clustering", label: "Spatial clustering", name: "空间聚类" }, + { path: "/gene-view", label: "Gene Expression", name: "基因表达" }, + { path: "/resource", label: "Resource", name: "资源" }, + { path: "/download", label: "Download", name: "下载" }, + ]; + + return ( + + ); +}; + +export default Navigation; \ No newline at end of file diff --git a/embryo-frontend/src/pages/Download.tsx b/embryo-frontend/src/pages/Download.tsx new file mode 100644 index 0000000..a6c8c56 --- /dev/null +++ b/embryo-frontend/src/pages/Download.tsx @@ -0,0 +1,106 @@ +import React from "react"; + +const Download: React.FC = () => { + const downloadItems = [ + { + title: "CS7 阶段数据", + description: "小鼠胚胎 CS7 发育阶段的完整空间转录组数据", + files: [ + { name: "CS7.h5ad", size: "45.2 MB", format: "AnnData" }, + { name: "CS7_metadata.csv", size: "2.1 MB", format: "CSV" }, + ] + }, + { + title: "CS8 阶段数据", + description: "小鼠胚胎 CS8 发育阶段的完整空间转录组数据", + files: [ + { name: "CS8.h5ad", size: "52.8 MB", format: "AnnData" }, + { name: "CS8_metadata.csv", size: "2.3 MB", format: "CSV" }, + ] + }, + { + title: "CS9 阶段数据", + description: "小鼠胚胎 CS9 发育阶段的完整空间转录组数据", + files: [ + { name: "CS9.h5ad", size: "61.4 MB", format: "AnnData" }, + { name: "CS9_metadata.csv", size: "2.7 MB", format: "CSV" }, + ] + }, + { + title: "模拟数据集", + description: "用于测试和开发的 3D 表达数据模拟集", + files: [ + { name: "embryo_mock_3D_expression.h5ad", size: "18.9 MB", format: "AnnData" }, + ] + } + ]; + + return ( +
+
+

Download

+

+ 我们为研究社区提供处理后的数据和元数据下载 +

+
+ +
+
+

使用协议

+

+ 下载和使用这些数据时,请遵守以下协议: +

+
    +
  • 数据仅限于学术研究用途
  • +
  • 如果使用这些数据发表论文,请引用我们的工作
  • +
  • 禁止重新分发原始数据
  • +
  • 商业用途需要单独授权
  • +
+
+ +
+

可下载数据

+
+ {downloadItems.map((item, index) => ( +
+

{item.title}

+

{item.description}

+
+ {item.files.map((file, fileIndex) => ( +
+
+ {file.name} + + {file.size} | {file.format} + +
+ +
+ ))} +
+
+ ))} +
+
+ +
+

批量下载

+
+
+

完整数据集

+

下载所有阶段的数据和元数据(约 185 MB)

+ +
+
+

元数据包

+

仅下载所有阶段的元数据文件(约 7 MB)

+ +
+
+
+
+
+ ); +}; + +export default Download; \ No newline at end of file diff --git a/embryo-frontend/src/pages/GeneView.tsx b/embryo-frontend/src/pages/GeneView.tsx index 570e151..d03d947 100644 --- a/embryo-frontend/src/pages/GeneView.tsx +++ b/embryo-frontend/src/pages/GeneView.tsx @@ -54,63 +54,110 @@ const GeneView: React.FC = () => { }; return ( -
-

Gene Expression Viewer

- - {/* 阶段选择 */} -
- +
+
+

Gene Expression

+

+ 查看和分析不同发育阶段的基因表达模式和空间分布。通过3D可视化探索基因在胚胎发育过程中的表达变化。 +

- {/* 基因选择 + 按钮 */} -
- - - -
+
+
+

基因表达查询

+ + {/* 阶段选择 */} +
+ +
- {/* 错误提示 */} - {error &&

{error}

} + {/* 基因选择 + 按钮 */} +
+ + + +
- {/* 可视化区域 */} -
- {data.length > 0 ? ( - - ) : ( -

- No data to display. + {/* 错误提示 */} + {error &&

{error}
} +
+ +
+

3D 表达可视化

+

+ 下方的3D可视化展示了所选基因在{selectedStage}发育阶段的空间表达模式。 + 点击任意数据点可查看详细的表达信息。

- )} + + {/* 可视化区域 */} +
+ {data.length > 0 ? ( + + ) : ( +
+ {loading ? ( +
+
🔄
+

正在加载基因表达数据...

+
+ ) : ( +
+
📊
+

请选择发育阶段和目标基因以查看表达数据

+
+ )} +
+ )} +
+
+ +
+

使用说明

+
+
+

🎯 选择目标

+

首先选择感兴趣的发育阶段,然后从下拉菜单中选择要查看的基因。

+
+
+

🖱️ 交互操作

+

在3D视图中使用鼠标拖拽旋转视角,滚轮缩放,点击数据点查看详细信息。

+
+
+

🎨 颜色编码

+

颜色代表基因表达强度:红色表示高表达,蓝色表示低表达。

+
+
+
); diff --git a/embryo-frontend/src/pages/HomePage.tsx b/embryo-frontend/src/pages/HomePage.tsx new file mode 100644 index 0000000..8ea6a2e --- /dev/null +++ b/embryo-frontend/src/pages/HomePage.tsx @@ -0,0 +1,102 @@ +import React from "react"; +import { Link } from "react-router-dom"; + +const HomePage: React.FC = () => { + return ( +
+
+
+

Digital Embryo

+

数字胚胎发育时空转录组图谱

+

+ Digital Embryo 数据库包含了小鼠胚胎在 CS7、CS8、CS9 等不同发育阶段的空间转录组数据。 + 我们提供基因表达的空间图谱,基因共表达模块和调控子信息,为深入研究哺乳动物发育的长期问题提供全景图谱。 +

+
+
+ +
+
+
+ +
🧬
+

Spatial clustering

+

+ 空间聚类 - 搜索每个胚胎切片中的注释、基因表达、基因共表达模块和调控子。 +

+ +
+ +
+ +
📊
+

Gene Expression

+

+ 基因表达 - 查看和分析不同发育阶段的基因表达模式和空间分布。 +

+ +
+ +
+ +
🔬
+

Resource

+

+ 资源 - 我们为研究社区提供原始数据和分析软件资源。 +

+ +
+ +
+ +
⬇️
+

Download

+

+ 下载 - 我们为研究社区提供处理后的数据和元数据。 +

+ +
+
+
+ +
+
+

数据库详情

+

+ Digital Embryo 数据库包含了小鼠胚胎在 CS7(~早期发育)、CS8(~中期发育)、CS9(~后期发育) + 等不同发育阶段的高分辨率空间转录组数据。通过先进的空间转录组学技术, + 我们能够在细胞分辨率水平上揭示基因表达的空间模式,为理解胚胎发育的分子机制提供重要资源。 +

+ +
+
+ 3 + 发育阶段 +
+
+ 1000+ + 基因 +
+
+ 10000+ + 细胞 +
+
+
+
+ +
+

如何引用

+
+

+ Digital Embryo: A spatiotemporal transcriptomic atlas of mouse embryogenesis + using advanced spatial transcriptomics. Development, 2024. +

+ +
+
+
+ ); +}; + +export default HomePage; \ No newline at end of file diff --git a/embryo-frontend/src/pages/Resource.tsx b/embryo-frontend/src/pages/Resource.tsx new file mode 100644 index 0000000..4ded00f --- /dev/null +++ b/embryo-frontend/src/pages/Resource.tsx @@ -0,0 +1,76 @@ +import React from "react"; + +const Resource: React.FC = () => { + return ( +
+
+

Resource

+

+ 我们为研究社区提供原始数据和分析软件资源 +

+
+ +
+
+

数据资源

+
+
+

原始数据

+

包含完整的空间转录组测序数据,格式为 H5AD 和 H5 文件。

+
    +
  • CS7 阶段数据 (CS7.h5ad)
  • +
  • CS8 阶段数据 (CS8.h5ad)
  • +
  • CS9 阶段数据 (CS9.h5ad)
  • +
+
+
+

处理后数据

+

经过质量控制、标准化和降维处理的数据,可直接用于下游分析。

+
    +
  • 基因表达矩阵
  • +
  • 细胞类型注释
  • +
  • 空间坐标信息
  • +
+
+
+
+ +
+

软件工具

+
+
+

数据处理流程

+

完整的空间转录组数据分析流程,包括预处理、质量控制、聚类和可视化。

+ +
+
+

可视化工具

+

基于 Three.js 的 3D 可视化工具,支持交互式探索基因表达的空间模式。

+ +
+
+
+ +
+

技术支持

+
+

如果您在使用数据或软件过程中遇到问题,请通过以下方式联系我们:

+
    +
  • Email: support@digital-embryo.org
  • +
  • GitHub Issues: 提交技术问题和功能请求
  • +
  • 文档中心: 查看详细的使用指南
  • +
+
+
+
+
+ ); +}; + +export default Resource; \ No newline at end of file diff --git a/embryo-frontend/src/pages/SpatialClustering.tsx b/embryo-frontend/src/pages/SpatialClustering.tsx new file mode 100644 index 0000000..ca3d08f --- /dev/null +++ b/embryo-frontend/src/pages/SpatialClustering.tsx @@ -0,0 +1,50 @@ +import React from "react"; + +const SpatialClustering: React.FC = () => { + return ( +
+
+

Spatial clustering

+

+ 空间聚类分析 - 搜索每个胚胎切片中的注释、基因表达、基因共表达模块和调控子 +

+
+ +
+
+

空间聚类功能

+
+
+

细胞类型注释

+

基于基因表达谱和空间位置信息,自动识别和注释不同的细胞类型。

+
+
+

基因共表达模块

+

识别在相同空间区域内共同表达的基因模块,揭示功能相关的基因网络。

+
+
+

空间调控子

+

分析空间特异性的转录调控网络,理解组织形成的分子机制。

+
+
+
+ +
+

交互式探索

+
+

🚧 交互式空间聚类工具正在开发中...

+

即将支持:

+
    +
  • 实时聚类参数调整
  • +
  • 多种聚类算法选择
  • +
  • 聚类结果可视化
  • +
  • 差异基因分析
  • +
+
+
+
+
+ ); +}; + +export default SpatialClustering; \ No newline at end of file diff --git a/embryo-frontend/src/style.css b/embryo-frontend/src/style.css index c096a9b..0a5b1c8 100644 --- a/embryo-frontend/src/style.css +++ b/embryo-frontend/src/style.css @@ -1,125 +1,457 @@ +/* ===== 基础样式重置 ===== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + :root { - font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; font-weight: 400; + + /* 颜色主题 */ + --primary-color: #2c5282; + --secondary-color: #3182ce; + --accent-color: #38b2ac; + --text-primary: #2d3748; + --text-secondary: #4a5568; + --text-muted: #718096; + --background-primary: #ffffff; + --background-secondary: #f7fafc; + --background-accent: #edf2f7; + --border-color: #e2e8f0; + --border-light: #f1f5f9; + --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - +body { + margin: 0; + min-height: 100vh; + color: var(--text-primary); + background-color: var(--background-primary); font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; +/* ===== 应用布局 ===== */ +.app { min-height: 100vh; + display: flex; + flex-direction: column; } -h1 { - font-size: 3.2em; - line-height: 1.1; +.main-content { + flex: 1; } -#app { - max-width: 1280px; +/* ===== 导航栏样式 ===== */ +.main-navigation { + background-color: var(--background-primary); + border-bottom: 2px solid var(--border-color); + box-shadow: var(--shadow-sm); + position: sticky; + top: 0; + z-index: 100; +} + +.nav-container { + max-width: 1200px; margin: 0 auto; - padding: 2rem; - text-align: center; + padding: 0 1rem; + display: flex; + align-items: center; + justify-content: space-between; + height: 64px; } -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #3178c6aa); +.nav-brand { + display: flex; + align-items: center; } -.card { - padding: 2em; +.nav-brand-link { + text-decoration: none; + color: var(--primary-color); + font-weight: 700; + font-size: 1.5rem; + transition: color 0.2s ease; } -.read-the-docs { - color: #888; +.nav-brand-link:hover { + color: var(--secondary-color); } -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; +.nav-links { + display: flex; + align-items: center; + gap: 0; +} + +.nav-link { + text-decoration: none; + color: var(--text-primary); font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; + padding: 0.75rem 1.25rem; + border-radius: 0.375rem; + transition: all 0.2s ease; + position: relative; } -/* GeneView component styles */ -.gene-view-container { - padding: 1rem; +.nav-link:hover { + color: var(--primary-color); + background-color: var(--background-secondary); } -.stage-selector { - margin-bottom: 10px; +.nav-link.active { + color: var(--primary-color); + background-color: var(--background-accent); + font-weight: 600; } -.gene-selector { +/* ===== 页面容器 ===== */ +.page-container { + max-width: 1200px; + margin: 0 auto; + padding: 2rem 1rem; +} + +.page-header { + text-align: center; + margin-bottom: 3rem; + padding-bottom: 2rem; + border-bottom: 1px solid var(--border-light); +} + +.page-header h1 { + font-size: 2.5rem; + font-weight: 700; + color: var(--primary-color); margin-bottom: 1rem; } -.gene-label { - margin-right: 0.5rem; +.page-description { + font-size: 1.1rem; + color: var(--text-secondary); + max-width: 800px; + margin: 0 auto; } -.gene-select { +.page-content { + display: flex; + flex-direction: column; + gap: 3rem; +} + +.section { + background-color: var(--background-primary); + padding: 2rem; + border-radius: 0.75rem; + box-shadow: var(--shadow-md); + border: 1px solid var(--border-color); +} + +.section h2 { + font-size: 1.75rem; + font-weight: 600; + color: var(--primary-color); + margin-bottom: 1.5rem; +} + +.section h3 { + font-size: 1.25rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 1rem; +} + +/* ===== 主页样式 ===== */ +.homepage { + padding: 0; +} + +.hero-section { + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); + color: white; + padding: 4rem 2rem; + text-align: center; + margin-bottom: 4rem; +} + +.hero-content { + max-width: 900px; + margin: 0 auto; +} + +.hero-title { + font-size: 3.5rem; + font-weight: 800; + margin-bottom: 1rem; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.hero-subtitle { + font-size: 1.75rem; + font-weight: 400; + margin-bottom: 2rem; + opacity: 0.95; +} + +.hero-description { + font-size: 1.1rem; + line-height: 1.7; + opacity: 0.9; + max-width: 700px; + margin: 0 auto; +} + +.features-section { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem 4rem; +} + +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; +} + +.feature-card { + background-color: var(--background-primary); + border-radius: 0.75rem; + box-shadow: var(--shadow-lg); + border: 1px solid var(--border-color); + transition: all 0.3s ease; + overflow: hidden; +} + +.feature-card:hover { + transform: translateY(-4px); + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +.feature-link { + display: block; + text-decoration: none; + color: inherit; + padding: 2rem; +} + +.feature-icon { + font-size: 3rem; + margin-bottom: 1.5rem; + display: block; +} + +.feature-title { + font-size: 1.5rem; + font-weight: 600; + color: var(--primary-color); + margin-bottom: 1rem; +} + +.feature-description { + color: var(--text-secondary); + line-height: 1.6; +} + +.info-section { + max-width: 1200px; + margin: 0 auto; + padding: 4rem 1rem; + background-color: var(--background-secondary); + border-radius: 1rem; +} + +.info-content { + text-align: center; +} + +.info-content h3 { + font-size: 2rem; + font-weight: 700; + color: var(--primary-color); + margin-bottom: 1.5rem; +} + +.info-content p { + font-size: 1.1rem; + color: var(--text-secondary); + line-height: 1.7; + max-width: 800px; + margin: 0 auto 3rem; +} + +.statistics { + display: flex; + justify-content: center; + gap: 4rem; + flex-wrap: wrap; +} + +.stat-item { + text-align: center; +} + +.stat-number { + display: block; + font-size: 3rem; + font-weight: 800; + color: var(--primary-color); + margin-bottom: 0.5rem; +} + +.stat-label { + font-size: 1.1rem; + color: var(--text-secondary); + font-weight: 500; +} + +.citation-section { + max-width: 1200px; + margin: 4rem auto 0; + padding: 0 1rem; +} + +.citation-section h3 { + font-size: 1.75rem; + font-weight: 600; + color: var(--primary-color); + margin-bottom: 1.5rem; + text-align: center; +} + +.citation-box { + background-color: var(--background-accent); + padding: 2rem; + border-radius: 0.75rem; + border-left: 4px solid var(--primary-color); + text-align: center; +} + +.citation-box p { + font-style: italic; + color: var(--text-secondary); + margin-bottom: 1.5rem; + line-height: 1.6; +} + +.copy-citation-btn { + background-color: var(--primary-color); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.copy-citation-btn:hover { + background-color: var(--secondary-color); +} + +/* ===== 基因查看页面样式 ===== */ +.gene-view-container { + max-width: 1200px; + margin: 0 auto; + padding: 2rem 1rem; +} + +.gene-view-container h2 { + font-size: 2.5rem; + font-weight: 700; + color: var(--primary-color); + text-align: center; + margin-bottom: 3rem; +} + +.stage-selector, .gene-selector { + margin-bottom: 1.5rem; + padding: 1.5rem; + background-color: var(--background-secondary); + border-radius: 0.75rem; + border: 1px solid var(--border-color); +} + +.stage-selector label, .gene-label { + font-weight: 600; + color: var(--text-primary); margin-right: 1rem; } +.gene-select, .stage-selector select { + padding: 0.75rem 1rem; + border: 1px solid var(--border-color); + border-radius: 0.5rem; + background-color: white; + color: var(--text-primary); + font-size: 1rem; + margin-right: 1rem; + min-width: 200px; +} + +.gene-select:focus, .stage-selector select:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(44, 82, 130, 0.1); +} + +button { + background-color: var(--primary-color); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + font-size: 1rem; +} + +button:hover:not(:disabled) { + background-color: var(--secondary-color); + transform: translateY(-1px); +} + +button:disabled { + background-color: var(--text-muted); + cursor: not-allowed; + transform: none; +} + .error-message { - color: red; + color: #e53e3e; + background-color: #fed7d7; + padding: 1rem; + border-radius: 0.5rem; + border-left: 4px solid #e53e3e; + margin-bottom: 1.5rem; } .visualization-container { width: 100%; height: 600px; - border: 1px solid #ccc; + border: 2px solid var(--border-color); + border-radius: 0.75rem; position: relative; + background-color: var(--background-secondary); + overflow: hidden; } .no-data-message { text-align: center; - padding-top: 2rem; + padding: 4rem 2rem; + color: var(--text-muted); + font-size: 1.1rem; } -/* PointCloud component styles */ +/* ===== 点云组件样式 ===== */ .point-cloud-container { width: 100%; height: 100%; @@ -128,29 +460,282 @@ button:focus-visible { .point-cloud-legend { position: absolute; - top: 10px; - right: 10px; - background: white; - padding: 5px; - border: 1px solid gray; - font-size: 12px; + top: 15px; + right: 15px; + background: rgba(255, 255, 255, 0.95); + padding: 1rem; + border-radius: 0.5rem; + border: 1px solid var(--border-color); + font-size: 0.875rem; + box-shadow: var(--shadow-md); + -webkit-backdrop-filter: blur(8px); + backdrop-filter: blur(8px); } .legend-gradient { - background: linear-gradient(to top, hsla(180, 100%, 50%, 1.00), hsla(72, 100%, 50%, 1.00), hsla(0, 100%, 50%, 0.99)); + background: linear-gradient(to top, + hsla(180, 100%, 50%, 1.00), + hsla(72, 100%, 50%, 1.00), + hsla(0, 100%, 50%, 0.99)); width: 20px; height: 100px; + border-radius: 2px; + margin-bottom: 0.5rem; } -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; +/* ===== 其他页面样式 ===== */ +.clustering-features, .resource-grid, .software-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-top: 2rem; +} + +.cluster-card, .resource-card, .software-card { + background-color: var(--background-secondary); + padding: 2rem; + border-radius: 0.75rem; + border: 1px solid var(--border-color); + transition: all 0.2s ease; +} + +.cluster-card:hover, .resource-card:hover, .software-card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +.cluster-card h3, .resource-card h3, .software-card h3 { + color: var(--primary-color); + margin-bottom: 1rem; +} + +.interactive-notice { + background-color: var(--background-accent); + padding: 2rem; + border-radius: 0.75rem; + border-left: 4px solid var(--accent-color); + margin-top: 2rem; +} + +.interactive-notice p { + margin-bottom: 1rem; + color: var(--text-secondary); +} + +.interactive-notice ul { + margin-left: 1.5rem; + color: var(--text-secondary); +} + +.software-links { + display: flex; + gap: 1rem; + margin-top: 1rem; +} + +.software-link { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + padding: 0.5rem 1rem; + border: 1px solid var(--primary-color); + border-radius: 0.375rem; + transition: all 0.2s ease; +} + +.software-link:hover { + background-color: var(--primary-color); + color: white; +} + +.support-info { + background-color: var(--background-secondary); + padding: 2rem; + border-radius: 0.75rem; + margin-top: 2rem; +} + +.support-info ul { + margin-left: 1.5rem; + margin-top: 1rem; +} + +/* ===== 下载页面样式 ===== */ +.download-notice { + background-color: var(--background-secondary); + padding: 2rem; + border-radius: 0.75rem; + border-left: 4px solid var(--accent-color); + margin-bottom: 3rem; +} + +.download-notice h2 { + color: var(--primary-color); + margin-bottom: 1rem; +} + +.download-notice ul { + margin-left: 1.5rem; + margin-top: 1rem; +} + +.downloads-section { + margin-bottom: 4rem; +} + +.download-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); + gap: 2rem; + margin-top: 2rem; +} + +.download-card { + background-color: var(--background-primary); + border: 1px solid var(--border-color); + border-radius: 0.75rem; + padding: 2rem; + box-shadow: var(--shadow-md); +} + +.download-card h3 { + color: var(--primary-color); + margin-bottom: 1rem; +} + +.download-description { + color: var(--text-secondary); + margin-bottom: 1.5rem; +} + +.download-files { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.download-file { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem; + background-color: var(--background-secondary); + border-radius: 0.5rem; + border: 1px solid var(--border-light); +} + +.file-info { + display: flex; + flex-direction: column; +} + +.file-name { + font-weight: 600; + color: var(--text-primary); +} + +.file-meta { + font-size: 0.875rem; + color: var(--text-muted); +} + +.download-btn { + background-color: var(--accent-color); + padding: 0.5rem 1rem; + font-size: 0.875rem; +} + +.download-btn:hover { + background-color: #2c7a7b; +} + +.bulk-download { + background-color: var(--background-secondary); + padding: 2rem; + border-radius: 0.75rem; + border: 1px solid var(--border-color); +} + +.bulk-download h2 { + color: var(--primary-color); + margin-bottom: 2rem; +} + +.bulk-options { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; +} + +.bulk-option { + background-color: var(--background-primary); + padding: 2rem; + border-radius: 0.75rem; + text-align: center; + border: 1px solid var(--border-color); +} + +.bulk-option h3 { + color: var(--primary-color); + margin-bottom: 1rem; +} + +.bulk-option p { + color: var(--text-secondary); + margin-bottom: 1.5rem; +} + +.bulk-download-btn { + background-color: var(--secondary-color); + padding: 0.75rem 2rem; + font-size: 1rem; +} + +.bulk-download-btn:hover { + background-color: var(--primary-color); +} + +/* ===== 响应式设计 ===== */ +@media (max-width: 768px) { + .nav-container { + padding: 0 0.5rem; + flex-direction: column; + height: auto; + padding-top: 1rem; + padding-bottom: 1rem; } - a:hover { - color: #747bff; + + .nav-links { + margin-top: 1rem; + flex-wrap: wrap; + justify-content: center; } - button { - background-color: #f9f9f9; + + .hero-title { + font-size: 2.5rem; + } + + .hero-subtitle { + font-size: 1.5rem; + } + + .features-grid { + grid-template-columns: 1fr; + } + + .statistics { + gap: 2rem; + } + + .download-grid { + grid-template-columns: 1fr; + } + + .bulk-options { + grid-template-columns: 1fr; + } + + .clustering-features, .resource-grid, .software-grid { + grid-template-columns: 1fr; } }