+
+
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;
}
}