You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openrank/front/frontend/styles.css

1437 lines
31 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* 基础样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%);
color: #ffffff;
min-height: 100vh;
overflow-x: hidden;
}
/* 模式切换(全局 / 项目) */
.mode-switch {
display: flex;
background: rgba(255, 255, 255, 0.06);
padding: 4px;
border-radius: 14px;
gap: 4px;
margin: 0 1.5rem;
backdrop-filter: blur(8px);
border: 1px solid rgba(255,255,255,0.15);
}
.mode-btn {
border: none;
background: transparent;
color: rgba(255,255,255,0.7);
font-size: 0.85rem;
padding: 0.5rem 1rem;
border-radius: 10px;
cursor: pointer;
font-weight: 600;
letter-spacing: .5px;
transition: all .25s ease;
}
.mode-btn:hover { color:#fff; background: rgba(255,255,255,0.08); }
.mode-btn.active { background: linear-gradient(135deg,#00d4ff,#0099cc); color:#fff; box-shadow:0 4px 15px rgba(0,212,255,.35); }
.hidden { display: none !important; }
/* 项目模式布局 */
.project-mode { margin-bottom: 2rem; }
.project-layout { display: flex; gap: 1.25rem; }
.project-sidebar {
width: 280px;
flex-shrink: 0;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 16px;
padding: 1rem 1rem 1.25rem;
max-height: 70vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.project-sidebar-header { margin-bottom: .75rem; }
.project-sidebar-header h3 { margin:0 0 .5rem 0; font-size:1rem; font-weight:600; color:#fff; }
.project-sidebar-header input {
width: 100%;
background: rgba(255,255,255,0.1);
border: 1px solid rgba(255,255,255,0.2);
color:#fff; padding:.5rem .75rem; border-radius:8px; outline:none; font-size:.85rem;
}
.project-sidebar-header input:focus { border-color:#00d4ff; box-shadow:0 0 0 2px rgba(0,212,255,.25); }
.project-list { list-style:none; margin:0; padding:0; overflow-y:auto; scrollbar-width:thin; flex:1; }
.project-list li { padding:.55rem .6rem; font-size:.85rem; border-radius:8px; display:flex; align-items:center; justify-content:space-between; gap:.5rem; cursor:pointer; transition:background .2s ease; }
.project-list li:hover { background: rgba(255,255,255,0.08); }
.project-list li.active { background: linear-gradient(135deg,#00d4ff,#0099cc); box-shadow:0 4px 15px rgba(0,212,255,.3); }
.project-list li .repo-name { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.project-list li .repo-mini-score { font-weight:600; font-size:.75rem; color:#00d4ff; }
.project-list li.active .repo-mini-score { color:#fff; }
.project-content {
flex: 1;
min-height: 400px;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 16px;
padding: 1.25rem 1.5rem 1.75rem;
position: relative;
width: 100%;
}
/* 让主体容器在项目模式下可拉伸利用剩余空间 */
.container { max-width: 100%; }
.project-placeholder { text-align:center; padding:3rem 1rem; color:rgba(255,255,255,0.6); }
.project-placeholder h3 { font-size:1.15rem; font-weight:600; margin-bottom:.75rem; color:#fff; }
.project-header-inline { display:flex; align-items:flex-start; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:1rem; }
.project-header-inline h2 { margin:0; font-size:1.25rem; font-weight:700; }
.badge { display:inline-block; padding:.25rem .6rem; font-size:.65rem; letter-spacing:.5px; background:rgba(0,212,255,.15); border:1px solid rgba(0,212,255,.4); border-radius:6px; color:#00d4ff; font-weight:600; }
.badge.approx { background:rgba(255,193,7,.15); border-color:rgba(255,193,7,.4); color:#ffc107; }
.badge.full { background:rgba(0,255,136,.15); border-color:rgba(0,255,136,.4); color:#00ff88; }
.split-panels { display:grid; grid-template-columns: repeat(auto-fit,minmax(300px,1fr)); gap:1.25rem; margin-top:.5rem; }
.panel-box { background:rgba(255,255,255,0.05); border:1px solid rgba(255,255,255,0.08); border-radius:14px; padding:1rem 1.1rem; position:relative; }
.panel-box h4 { margin:0 0 .75rem 0; font-size:.95rem; font-weight:600; letter-spacing:.5px; color:#fff; }
.mini-table { width:100%; border-collapse:collapse; font-size:.75rem; }
.mini-table th, .mini-table td { padding:.4rem .5rem; border-bottom:1px solid rgba(255,255,255,0.06); text-align:left; }
.mini-table th { background:rgba(255,255,255,0.05); font-weight:600; }
.mini-table tbody tr:hover { background:rgba(255,255,255,0.05); }
.chart-slot { height:200px; }
/* 新版项目模式扩展布局 */
/* 项目模式核心网格:三列均衡 + 时间序列占满第二行 */
/* 保留旧类兼容暂不删除,但现在用 flex 顶行 */
.project-grid-expanded { display:none; }
.project-top-row {
display:flex;
gap:1.15rem;
width:100%;
align-items:stretch;
}
.project-top-row .panel-box { flex:1 1 0; display:flex; flex-direction:column; }
/* 三块等宽 */
.project-top-row .panel-ranking,
.project-top-row .panel-activity,
.project-top-row .panel-metrics { flex:1 1 0; }
/* 贡献者排名表滚动限制(之前只在 .project-grid-expanded 下生效,这里为新布局补齐) */
.project-top-row .panel-ranking .table-wrap-scroll {
max-height: 480px; /* 可根据需要再调,如 400 / 440 */
overflow-y: auto;
overflow-x: hidden;
padding-right: 2px; /* 给滚动条留空间避免遮住数据 */
}
.project-top-row .panel-ranking .table-wrap-scroll::-webkit-scrollbar { width: 6px; }
.project-top-row .panel-ranking .table-wrap-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.25); border-radius: 3px; }
.project-top-row .panel-ranking .table-wrap-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.45); }
@media (max-width: 1200px){
.project-top-row { flex-wrap:wrap; }
.project-top-row .panel-box { flex:1 1 calc(50% - 1.15rem); }
.project-top-row .panel-metrics { order:3; }
}
@media (max-width: 820px){
.project-top-row .panel-box { flex:1 1 100%; }
}
.project-grid-expanded .panel-box { height:100%; display:flex; flex-direction:column; }
.project-grid-expanded .panel-box .table-wrap-scroll { overflow:auto; max-height:380px; }
/* 时间序列面板在新布局下全宽 */
.panel-timeseries { width:100%; }
/* Remove residual span sizing influence when using template areas */
.project-grid-expanded .panel-box.span-2,
.project-grid-expanded .panel-box.span-3,
.project-grid-expanded .panel-box.span-4 { grid-column: auto; }
/* 原响应式网格规则移除,改由 flex wrap 控制 */
/* 项目模式宽度限制防止过宽拉伸最小1200px最大1680px中间按视口92% */
body.project-mode-active .container { max-width: clamp(1200px, 92vw, 1680px); margin:0 auto; padding-left:1.2rem; padding-right:1.2rem; }
body.project-mode-active .project-content { padding-right: 2rem; }
body.project-mode-active .project-grid-expanded .panel-box { min-height: 260px; }
body.project-mode-active .panel-ranking { padding-right: .75rem; }
body.project-mode-active .panel-ranking .table-wrap-scroll { max-height: 420px; }
@media (min-width:1400px){
.project-grid-expanded { grid-template-columns: repeat(8, 1fr); }
.project-grid-expanded .panel-box.span-2 { grid-column: span 3; }
.project-grid-expanded .panel-box.span-4 { grid-column: span 5; }
}
.metric-list { list-style:none; margin:0; padding:0; display:grid; grid-template-columns:1fr; gap:.55rem; font-size:.7rem; }
.metric-list li { display:flex; justify-content:space-between; background:rgba(255,255,255,0.04); border:1px solid rgba(255,255,255,0.06); padding:.45rem .6rem; border-radius:8px; }
.metric-list li span { opacity:.7; }
.metric-list li strong { font-weight:600; color:#00d4ff; }
.mini-table thead th { position:sticky; top:0; background:rgba(255,255,255,0.08); backdrop-filter:blur(6px); }
.mini-table tbody tr td { white-space:nowrap; }
/* 滚动条微调表内 */
.table-wrap-scroll::-webkit-scrollbar { width:6px; }
.table-wrap-scroll::-webkit-scrollbar-thumb { background:rgba(255,255,255,0.25); border-radius:3px; }
.table-wrap-scroll::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,0.4); }
@media (max-width: 980px){
.project-layout { flex-direction:column; }
.project-sidebar { width:100%; max-height:220px; flex-direction:column; }
.project-content { min-height:300px; }
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 0 20px;
}
/* 头部导航 */
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1.5rem 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
margin-bottom: 2rem;
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 1.5rem;
font-weight: 700;
color: #00d4ff;
}
.logo i {
font-size: 2rem;
background: linear-gradient(135deg, #00d4ff, #0099cc);
-webkit-background-clip: text;
background-clip: text; /* 标准属性,提升兼容性 */
-webkit-text-fill-color: transparent;
}
.nav {
display: flex;
gap: 1rem;
}
.nav-btn {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.2);
color: rgba(255, 255, 255, 0.7);
padding: 0.75rem 1.5rem;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
}
.nav-btn:hover {
background: rgba(255, 255, 255, 0.1);
color: #ffffff;
}
.nav-btn.active {
background: linear-gradient(135deg, #00d4ff, #0099cc);
border-color: transparent;
color: #ffffff;
box-shadow: 0 4px 15px rgba(0, 212, 255, 0.3);
}
.header-actions {
display: flex;
gap: 1rem;
}
/* 按钮样式 */
.btn-primary {
background: linear-gradient(135deg, #00d4ff, #0099cc);
border: none;
color: white;
padding: 0.75rem 1.5rem;
border-radius: 12px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 212, 255, 0.4);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 0.5rem 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.2);
}
/* 主要内容区域 */
.main-content {
margin-bottom: 2rem;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 统计卡片网格 */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat-card {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
border-color: rgba(0, 212, 255, 0.3);
}
.stat-icon {
font-size: 2rem;
margin-bottom: 1rem;
color: #00d4ff;
}
.stat-info h3 {
font-size: 0.9rem;
font-weight: 500;
color: rgba(255, 255, 255, 0.7);
margin-bottom: 0.5rem;
}
.stat-value {
font-size: 2rem;
font-weight: 700;
color: #ffffff;
display: block;
margin-bottom: 0.25rem;
}
.stat-change {
font-size: 0.875rem;
font-weight: 500;
}
.stat-change.positive {
color: #00ff88;
}
.stat-change.negative {
color: #ff4757;
}
/* 图表网格 */
.charts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 1.5rem;
}
.chart-card {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
backdrop-filter: blur(10px);
}
.chart-card.full-width {
grid-column: 1 / -1;
}
.chart-card h3 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 1rem;
color: #ffffff;
}
.chart-container {
height: 300px;
position: relative;
}
/* 排名表格 */
.ranking-table {
background: rgba(255, 255, 255, 0.02);
border-radius: 12px;
overflow: hidden;
}
.table-header {
display: grid;
grid-template-columns: 80px 1fr 120px 100px;
padding: 1rem 1.5rem;
background: rgba(255, 255, 255, 0.1);
font-weight: 600;
color: rgba(255, 255, 255, 0.8);
}
.table-body {
max-height: 400px;
overflow-y: auto;
}
.ranking-item {
display: grid;
grid-template-columns: 80px 1fr 120px 100px;
padding: 1rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background 0.3s ease;
}
.ranking-item:hover {
background: rgba(255, 255, 255, 0.05);
}
.ranking-item:last-child {
border-bottom: none;
}
.rank {
font-weight: 700;
color: #00d4ff;
}
.rank-1 { color: #ffd700; }
.rank-2 { color: #c0c0c0; }
.rank-3 { color: #cd7f32; }
/* 面板头部 */
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.panel-header h2 {
font-size: 1.5rem;
font-weight: 700;
color: #ffffff;
}
.filter-controls select {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 0.5rem 1rem;
border-radius: 8px;
outline: none;
}
.search-box {
position: relative;
display: flex;
align-items: center;
}
.search-box input {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 0.5rem 1rem 0.5rem 2.5rem;
border-radius: 8px;
outline: none;
width: 250px;
}
.search-box i {
position: absolute;
left: 1rem;
color: rgba(255, 255, 255, 0.7);
}
/* 仓库网格 - 增强版 */
.repo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 1.5rem;
}
.repo-card {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.repo-card:hover {
transform: translateY(-6px) scale(1.02);
box-shadow:
0 20px 40px rgba(0, 0, 0, 0.4),
0 0 0 1px rgba(0, 212, 255, 0.4);
border-color: rgba(0, 212, 255, 0.3);
}
.repo-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #00d4ff, #0099cc);
opacity: 0.8;
}
.repo-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
}
.repo-icon {
width: 50px;
height: 50px;
border-radius: 12px;
background: linear-gradient(135deg, #00d4ff, #0099cc);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
}
.repo-info {
flex: 1;
}
.repo-info h3 {
font-size: 1.2rem;
font-weight: 700;
color: #ffffff;
margin-bottom: 0.25rem;
}
.repo-rank {
font-size: 0.9rem;
color: rgba(255, 255, 255, 0.7);
}
.repo-score {
font-size: 1.5rem;
font-weight: 800;
color: #00d4ff;
background: rgba(0, 212, 255, 0.1);
padding: 0.5rem 1rem;
border-radius: 12px;
border: 1px solid rgba(0, 212, 255, 0.2);
}
.repo-metrics {
margin-bottom: 1.5rem;
}
.metric-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.metric {
text-align: center;
padding: 1rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.metric i {
font-size: 1.2rem;
color: #00d4ff;
margin-bottom: 0.5rem;
display: block;
}
.metric-value {
display: block;
font-size: 1.4rem;
font-weight: 700;
color: #ffffff;
margin-bottom: 0.25rem;
}
.metric-label {
display: block;
font-size: 0.8rem;
color: rgba(255, 255, 255, 0.7);
}
.repo-progress {
margin-bottom: 1.5rem;
}
.progress-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
font-size: 0.9rem;
color: rgba(255, 255, 255, 0.8);
}
.repo-tags {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-bottom: 1.5rem;
}
.repo-actions {
display: flex;
gap: 0.75rem;
}
.repo-actions .btn-secondary {
flex: 1;
padding: 0.75rem;
font-size: 0.9rem;
}
/* 仓库卡片动画 */
.repo-card:nth-child(odd) {
border-left: 4px solid rgba(0, 212, 255, 0.5);
}
.repo-card:nth-child(even) {
border-left: 4px solid rgba(0, 255, 136, 0.5);
}
.repo-card:nth-child(3n) {
border-left: 4px solid rgba(255, 193, 7, 0.5);
}
/* 响应式调整 */
@media (max-width: 768px) {
.repo-grid {
grid-template-columns: 1fr;
}
.metric-row {
grid-template-columns: 1fr;
gap: 0.75rem;
}
.repo-header {
flex-direction: column;
text-align: center;
gap: 0.75rem;
}
.repo-actions {
flex-direction: column;
}
}
/* 特殊效果 */
.repo-card:hover .repo-icon {
transform: rotate(10deg) scale(1.1);
transition: transform 0.3s ease;
}
.repo-card:hover .repo-score {
background: rgba(0, 212, 255, 0.2);
transform: scale(1.05);
transition: all 0.3s ease;
}
/* 设置网格 */
.settings-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 1.5rem;
}
.setting-card {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
backdrop-filter: blur(10px);
}
.setting-card h3 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 1rem;
color: #ffffff;
}
.setting-item {
margin-bottom: 1rem;
}
.setting-item label {
display: block;
margin-bottom: 0.5rem;
color: rgba(255, 255, 255, 0.8);
font-weight: 500;
}
.setting-item input {
width: 100%;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 0.75rem;
border-radius: 8px;
outline: none;
}
.setting-item input:focus {
border-color: #00d4ff;
box-shadow: 0 0 0 2px rgba(0, 212, 255, 0.2);
}
/* 网络图谱 */
.graph-container {
height: 600px;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
position: relative;
overflow: hidden;
}
.graph-controls {
display: flex;
gap: 0.5rem;
}
/* 页脚 */
.footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 0;
border-top: 1px solid rgba(255, 255, 255, 0.1);
margin-top: 2rem;
}
.status-info {
display: flex;
align-items: center;
gap: 0.5rem;
color: rgba(255, 255, 255, 0.7);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #00ff88;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.footer-info {
display: flex;
gap: 1rem;
color: rgba(255, 255, 255, 0.5);
font-size: 0.875rem;
}
/* 加载覆盖层 */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(15, 15, 35, 0.95);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
backdrop-filter: blur(10px);
}
.loading-overlay.active {
display: flex;
}
.loading-spinner {
text-align: center;
color: #00d4ff;
}
.loading-spinner i {
font-size: 3rem;
margin-bottom: 1rem;
}
.loading-spinner p {
font-size: 1.1rem;
font-weight: 500;
}
/* 响应式设计 */
@media (max-width: 768px) {
.header {
flex-direction: column;
gap: 1rem;
}
.nav {
flex-wrap: wrap;
justify-content: center;
}
.stats-grid {
grid-template-columns: 1fr;
}
.charts-grid {
grid-template-columns: 1fr;
}
.panel-header {
flex-direction: column;
gap: 1rem;
align-items: stretch;
}
.footer {
flex-direction: column;
gap: 1rem;
text-align: center;
}
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.5);
}
/* 动画效果 */
@keyframes glow {
0%, 100% { box-shadow: 0 0 5px rgba(0, 212, 255, 0.3); }
50% { box-shadow: 0 0 20px rgba(0, 212, 255, 0.6); }
}
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
}
@keyframes pulse-glow {
0%, 100% {
box-shadow: 0 0 5px rgba(0, 212, 255, 0.3),
0 0 10px rgba(0, 212, 255, 0.2);
}
50% {
box-shadow: 0 0 20px rgba(0, 212, 255, 0.6),
0 0 30px rgba(0, 212, 255, 0.4);
}
}
@keyframes slide-in {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.glow-effect {
animation: glow 2s ease-in-out infinite;
}
.float-effect {
animation: float 3s ease-in-out infinite;
}
.pulse-glow {
animation: pulse-glow 2s ease-in-out infinite;
}
.slide-in {
animation: slide-in 0.6s ease-out;
}
.fade-in-up {
animation: fade-in-up 0.8s ease-out;
}
/* 增强的卡片悬停效果 */
.stat-card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow:
0 20px 40px rgba(0, 0, 0, 0.4),
0 0 0 1px rgba(0, 212, 255, 0.4);
}
.chart-card:hover {
transform: translateY(-4px);
box-shadow:
0 15px 35px rgba(0, 0, 0, 0.3),
0 0 0 1px rgba(0, 212, 255, 0.3);
}
.repo-card:hover {
transform: translateY(-6px) rotate(1deg);
box-shadow:
0 18px 38px rgba(0, 0, 0, 0.35),
0 0 0 1px rgba(0, 255, 136, 0.3);
}
/* 增强的按钮效果 */
.btn-primary:hover {
transform: translateY(-3px) scale(1.05);
box-shadow:
0 12px 25px rgba(0, 212, 255, 0.5),
0 0 15px rgba(0, 212, 255, 0.3);
}
.nav-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 15px rgba(255, 255, 255, 0.2);
}
/* 进度条样式 */
.progress-bar {
width: 100%;
height: 8px;
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
overflow: hidden;
margin: 0.5rem 0;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #00d4ff, #0099cc);
border-radius: 4px;
transition: width 0.3s ease;
position: relative;
}
.progress-fill::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg,
transparent 0%,
rgba(255, 255, 255, 0.3) 50%,
transparent 100%);
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* 标签样式 */
.tag {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
margin: 0.25rem;
}
.tag-primary {
background: rgba(0, 212, 255, 0.2);
color: #00d4ff;
border: 1px solid rgba(0, 212, 255, 0.3);
}
.tag-success {
background: rgba(0, 255, 136, 0.2);
color: #00ff88;
border: 1px solid rgba(0, 255, 136, 0.3);
}
.tag-warning {
background: rgba(255, 193, 7, 0.2);
color: #ffc107;
border: 1px solid rgba(255, 193, 7, 0.3);
}
/* 时间线样式 */
.timeline {
position: relative;
padding-left: 2rem;
}
.timeline::before {
content: '';
position: absolute;
left: 0.75rem;
top: 0;
bottom: 0;
width: 2px;
background: rgba(255, 255, 255, 0.2);
}
.timeline-item {
position: relative;
margin-bottom: 1.5rem;
}
.timeline-item::before {
content: '';
position: absolute;
left: -2rem;
top: 0.5rem;
width: 12px;
height: 12px;
border-radius: 50%;
background: #00d4ff;
border: 2px solid rgba(255, 255, 255, 0.3);
}
.timeline-content {
background: rgba(255, 255, 255, 0.05);
padding: 1rem;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
/* 网格布局增强 */
.grid-responsive {
display: grid;
gap: 1.5rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
/* 响应式设计增强 */
@media (max-width: 1024px) {
.charts-grid {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 640px) {
.stats-grid {
grid-template-columns: 1fr;
}
.header {
padding: 1rem 0;
}
.logo {
font-size: 1.25rem;
}
.nav {
flex-wrap: wrap;
gap: 0.5rem;
}
.nav-btn {
padding: 0.5rem 1rem;
font-size: 0.875rem;
}
}
/* 暗色模式优化 */
@media (prefers-color-scheme: dark) {
body {
background: linear-gradient(135deg, #0a0a1a 0%, #141428 50%, #1e1e3e 100%);
}
}
/* 开发者分析样式 */
.developer-analysis-header {
margin-bottom: 2rem;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.analysis-summary {
display: flex;
gap: 2rem;
margin-top: 1rem;
}
.summary-item {
display: flex;
align-items: center;
gap: 0.5rem;
color: rgba(255, 255, 255, 0.8);
font-weight: 500;
}
.summary-item i {
color: #00d4ff;
}
.developers-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.developer-card {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.developer-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
border-color: rgba(0, 212, 255, 0.3);
}
.developer-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.developer-avatar {
width: 50px;
height: 50px;
border-radius: 50%;
background: linear-gradient(135deg, #00d4ff, #0099cc);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
}
.developer-info h4 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.25rem;
color: #ffffff;
}
.developer-rank {
font-size: 0.9rem;
color: rgba(255, 255, 255, 0.7);
}
.rank-badge {
margin-left: auto;
padding: 0.25rem 0.75rem;
background: rgba(0, 212, 255, 0.2);
color: #00d4ff;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
}
.developer-stats {
margin-bottom: 1rem;
}
.stat-row {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.stat-label {
min-width: 80px;
font-size: 0.9rem;
color: rgba(255, 255, 255, 0.7);
}
.stat-value {
min-width: 40px;
font-weight: 600;
color: #ffffff;
}
.developer-metrics {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-bottom: 1rem;
}
.metric {
text-align: center;
padding: 0.75rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
}
.metric-label {
display: block;
font-size: 0.8rem;
color: rgba(255, 255, 255, 0.7);
margin-bottom: 0.25rem;
}
.metric-value {
display: block;
font-size: 1.2rem;
font-weight: 700;
color: #ffffff;
}
.metric-value.positive {
color: #00ff88;
}
.metric-value.negative {
color: #ff4757;
}
.developer-tags {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.developer-charts {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
margin-top: 2rem;
}
.chart-section {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
}
.chart-section h4 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 1rem;
color: #ffffff;
}
.no-results {
text-align: center;
padding: 3rem;
color: rgba(255, 255, 255, 0.5);
}
.no-results i {
font-size: 3rem;
margin-bottom: 1rem;
color: rgba(255, 255, 255, 0.3);
}
.no-results h3 {
font-size: 1.2rem;
margin-bottom: 0.5rem;
color: rgba(255, 255, 255, 0.7);
}
/* 打印样式优化 */
@media print {
.header-actions,
.nav,
.footer {
display: none;
}
body {
background: white;
color: black;
}
.stat-card,
.chart-card {
border: 1px solid #ddd;
background: white;
}
}
/* 模态窗口 (仓库详情) */
.modal {
position: fixed;
inset: 0; /* top:0; right:0; bottom:0; left:0 */
display: none;
align-items: center;
justify-content: center;
background: rgba(0,0,0,0.55);
z-index: 1200;
padding: 2rem;
}
.modal.open {
display: flex;
}
.modal .modal-content {
background: linear-gradient(180deg, rgba(20,20,35,0.98), rgba(16,16,28,0.98));
color: #fff;
border-radius: 12px;
max-width: 1100px;
width: 100%;
max-height: 80vh;
overflow: auto;
box-shadow: 0 20px 60px rgba(0,0,0,0.6);
border: 1px solid rgba(255,255,255,0.06);
padding: 1rem 1.25rem;
}
.modal .modal-close {
position: absolute;
right: 1rem;
top: 1rem;
background: transparent;
border: none;
color: #ffffff;
font-size: 1.6rem;
cursor: pointer;
opacity: 0.9;
}
.modal #repo-detail-title {
margin: 0 0 0.5rem 0;
padding-right: 2.5rem; /* to avoid overlap with close btn */
}
.modal #repo-detail-summary {
margin-bottom: 1rem;
color: rgba(255,255,255,0.9);
font-size: 0.95rem;
}
.modal #repo-detail-contributors {
margin-bottom: 1rem;
}
/* 简单表格样式,用于贡献者列表 */
.simple-table {
width: 100%;
border-collapse: collapse;
margin-top: 0.5rem;
font-size: 0.95rem;
}
.simple-table thead th {
text-align: left;
padding: 0.6rem 0.75rem;
background: rgba(255,255,255,0.03);
border-bottom: 1px solid rgba(255,255,255,0.06);
color: rgba(255,255,255,0.9);
}
.simple-table tbody td {
padding: 0.55rem 0.75rem;
border-bottom: 1px solid rgba(255,255,255,0.03);
color: rgba(255,255,255,0.85);
}
.simple-table tbody tr:hover td {
background: rgba(255,255,255,0.02);
}
/* ensure the repo timeseries canvas has a minimum height */
#repo-detail-timeseries {
width: 100% !important;
height: 220px !important;
}
@media (max-width: 768px) {
.modal .modal-content { padding: 0.75rem; max-width: 100%; }
.modal #repo-detail-title { font-size: 1rem; }
}