美化首页样式,同时小小设计了一下文章和评论的样式

This commit is contained in:
2026-02-08 23:18:56 +08:00
parent a36c91a762
commit 3a19f3c311
13 changed files with 1407 additions and 1047 deletions
+383
View File
@@ -0,0 +1,383 @@
/* =========================================
GitHub "Pro" Blog Style Layout
========================================= */
.single-post-gh-pro {
padding-bottom: 4rem;
}
/* --- Pro Header (Clean Geek Style) --- */
.gh-pro-header {
padding-bottom: 24px;
margin-bottom: 24px;
text-align: center; /* Center alignment looks more like a blog title */
}
.gh-pro-meta-top {
margin-bottom: 16px;
}
.gh-label-category {
display: inline-block;
font-size: 13px;
font-weight: 600;
color: var(--color-primary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.gh-pro-header .entry-title {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 16px;
line-height: 1.25;
}
.gh-pro-meta-bar {
display: flex;
justify-content: center;
align-items: center;
gap: 24px;
font-size: 14px;
color: var(--text-secondary);
font-family: var(--font-mono);
}
.gh-author-lockup {
display: flex;
align-items: center;
gap: 8px;
}
.gh-author-lockup img {
width: 24px;
height: 24px;
border-radius: 50%;
border: 1px solid var(--border-muted);
}
.gh-author-lockup .author-name {
font-weight: 600;
color: var(--text-primary);
}
.meta-divider {
color: var(--border-default);
}
/* --- File Box Body (The Article) --- */
.gh-pro-body-container {
max-width: 900px; /* Slightly wider read area */
margin: 0 auto 48px;
}
.gh-file-box {
border: 1px solid var(--border-default);
border-radius: 6px;
background-color: var(--bg-card);
overflow: hidden;
}
.gh-file-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 16px;
background-color: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
font-family: var(--font-mono);
font-size: 13px;
color: var(--text-secondary);
}
.gh-file-header .file-info {
display: flex;
align-items: center;
gap: 8px;
}
.gh-file-header .octicon {
fill: currentColor;
}
.gh-file-header strong {
color: var(--text-primary);
font-weight: 600;
}
.gh-file-content {
padding: 32px 40px;
background-color: var(--bg-card);
}
/* Entry Content Typography (Markdown Style) */
.gh-file-content {
font-size: 16px;
line-height: 1.7;
color: var(--text-primary);
overflow-wrap: break-word; /* 自动换行 */
word-wrap: break-word;
}
.gh-file-content p { margin-bottom: 1.5em; }
.gh-file-content h2 { border-bottom: 1px solid var(--border-muted); padding-bottom: 0.3em; margin-top: 1.5em; margin-bottom: 1em; }
.gh-file-content code { background-color: rgba(175, 184, 193, 0.2); padding: 0.2em 0.4em; border-radius: 6px; font-size: 85%; font-family: var(--font-mono); }
.gh-file-content pre { padding: 16px; overflow: auto; line-height: 1.45; background-color: var(--bg-surface); border-radius: 6px; }
.gh-file-footer {
margin-top: 32px;
padding-top: 16px;
border-top: 1px solid var(--border-muted);
}
/* --- Comments Section (Pro Timeline) --- */
.gh-pro-comments {
max-width: 900px;
margin: 0 auto;
}
.timeline-header h3 {
font-size: 1.25rem;
margin-bottom: 24px;
border-bottom: 1px solid var(--border-default);
padding-bottom: 8px;
}
/* Reuse existing gh-timeline styles from previous step but center align */
.gh-timeline {
margin-top: 0;
margin-left: 0; /* Clear previous offset */
}
/* Vertical Timeline Line - NEW FIX */
.gh-timeline::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 20px; /* Center of 40px avatar */
width: 2px;
background-color: var(--border-muted);
z-index: 0;
display: block; /* Ensure it is displayed */
}
/* Fix z-index for items so line is behind */
.gh-timeline-item {
position: relative;
z-index: 1;
}
ol.comment-list {
list-style: none; /* 去掉列表默认样式 */
padding: 0;
margin: 0;
}
/* Timeline Item (Main Post & Comments) */
.gh-timeline-item,
.gh-comment-item {
display: flex;
gap: 16px;
margin-bottom: 24px;
position: relative;
z-index: 1;
}
/* Avatar Column */
.gh-avatar,
.gh-comment-avatar {
flex-shrink: 0;
width: 40px;
}
.gh-avatar img,
.gh-comment-avatar img {
width: 40px;
height: 40px;
border-radius: 50%;
border: 1px solid var(--border-muted);
}
/* Content Box (Speech Bubble) */
.gh-item-box,
.gh-comment-box {
flex-grow: 1;
min-width: 0;
border: 1px solid var(--border-default);
border-radius: 6px;
background-color: var(--bg-card);
position: relative;
}
/* Speech Bubble Beak (Arrow) - Desktop Only */
@media (min-width: 768px) {
.gh-item-box::before, .gh-item-box::after,
.gh-comment-box::before, .gh-comment-box::after {
content: " ";
position: absolute;
top: 11px;
right: 100%;
height: 0;
width: 0;
border: solid transparent;
pointer-events: none;
}
.gh-item-box::after,
.gh-comment-box::after {
border-right-color: var(--bg-surface); /* Header BG color */
border-width: 7px;
margin-top: -7px;
}
.gh-item-box::before,
.gh-comment-box::before {
border-right-color: var(--border-default);
border-width: 8px;
margin-top: -8px;
}
}
/* Box Header */
.gh-box-header,
.gh-comment-header {
padding: 8px 16px;
background-color: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
border-top-left-radius: 6px;
border-top-right-radius: 6px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
color: var(--text-secondary);
}
.gh-header-meta {
display: flex;
align-items: center;
gap: 4px;
flex-wrap: wrap;
}
.gh-comment-meta,
.gh-header-meta {
display: flex;
align-items: center;
gap: 4px;
flex-wrap: wrap;
}
.gh-header-meta strong,
.gh-author-name a {
color: var(--text-primary);
font-weight: 600;
text-decoration: none;
}
.gh-header-meta a,
.gh-comment-meta time,
.gh-comment-meta a {
color: var(--text-secondary);
text-decoration: none;
font-size: 0.85rem;
}
.gh-header-meta a:hover,
.gh-comment-meta time:hover,
.gh-comment-meta a:hover {
color: var(--color-primary);
text-decoration: underline;
}
/* Badge (Author/Member) */
.gh-badge {
display: inline-block;
padding: 2px 7px;
font-size: 12px;
font-weight: 500;
line-height: 18px;
border-radius: 2em;
border: 1px solid var(--border-default);
color: var(--text-secondary);
margin-left: 8px;
}
/* Box Body */
.gh-box-body,
.gh-comment-body {
padding: 16px;
background-color: var(--bg-card);
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
overflow-wrap: break-word;
}
.gh-box-body .entry-content,
.gh-comment-body {
font-size: 15px;
line-height: 1.6;
}
/* Comment Form Styles */
.gh-comment-form textarea {
display: block;
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border-default);
border-radius: 6px;
background-color: var(--bg-surface);
color: var(--text-primary);
font-family: inherit;
resize: vertical;
min-height: 100px;
}
.gh-comment-form textarea:focus {
border-color: var(--color-primary);
outline: none;
box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.3);
}
.form-submit {
text-align: right;
margin-top: 10px;
}
.gh-comment-form input[type="submit"] {
background-color: var(--color-success);
color: #fff;
border: 1px solid rgba(27, 31, 36, 0.15);
border-radius: 6px;
padding: 5px 16px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
}
.gh-comment-form input[type="submit"]:hover {
background-color: #2c974b;
}
/* Buttons */
.btn-sm {
font-size: 12px;
padding: 3px 8px;
border: 1px solid var(--border-default);
border-radius: 6px;
color: var(--text-secondary);
background-color: var(--bg-body);
font-weight: 500;
}
.btn-sm:hover {
background-color: var(--bg-surface);
color: var(--color-primary);
text-decoration: none;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.gh-file-content { padding: 20px; }
.gh-pro-header .entry-title { font-size: 1.75rem; }
}
+66
View File
@@ -0,0 +1,66 @@
/* =========================================
页脚布局 (Footer)
========================================= */
.site-footer {
background-color: var(--bg-surface);
border-top: 1px solid var(--border-default);
padding: 4rem 0 2rem;
margin-top: auto; /* 确保置底 */
flex-shrink: 0; /* 防止Footer被压缩 */
}
/* --- 页脚内容网格 --- */
.footer-content {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 4列布局 */
gap: 2rem;
margin-bottom: 3rem;
}
.footer-section h3 {
font-size: 1rem;
font-weight: 600;
margin-bottom: 1rem;
color: var(--text-primary);
}
.footer-links li {
margin-bottom: 0.5rem;
}
.footer-links a {
color: var(--text-secondary);
font-size: 0.9rem;
}
.footer-links a:hover {
color: var(--color-primary);
text-decoration: underline;
}
/* --- 底部版权区 --- */
.footer-bottom {
border-top: 1px solid var(--border-muted);
padding-top: 2rem;
text-align: center;
color: var(--text-secondary);
font-size: 0.85rem;
}
/* --- 响应式适配 --- */
@media (max-width: 768px) {
.footer-content {
grid-template-columns: repeat(2, 1fr); /* 平板 2列 */
}
}
@media (max-width: 480px) {
.footer-content {
grid-template-columns: 1fr; /* 手机 1列 */
}
.site-footer {
padding: 3rem 0 1.5rem;
}
}
+158
View File
@@ -0,0 +1,158 @@
/* =========================================
首页独有样式 (Front Page / Hero)
========================================= */
/* --- Hero 区域 --- */
.hero-section {
padding: 120px 0 80px;
background-color: var(--bg-body);
position: relative;
overflow: hidden;
/* 科技网格背景 */
background-image:
linear-gradient(var(--border-muted) 1px, transparent 1px),
linear-gradient(90deg, var(--border-muted) 1px, transparent 1px);
background-size: 40px 40px;
background-position: center top;
}
/* 底部渐变遮罩 */
.hero-section::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 120px;
background: linear-gradient(to bottom, transparent, var(--bg-body));
pointer-events: none;
}
.hero-content {
max-width: 800px;
margin: 0 auto;
text-align: center;
position: relative;
z-index: 1;
}
/* 大标题 */
.hero-content h1 {
font-size: 3.5rem;
font-weight: 800;
letter-spacing: -0.02em;
margin-bottom: 1.5rem;
background: linear-gradient(135deg, var(--text-primary) 0%, var(--color-primary) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
line-height: 1.2;
}
/* 描述文本 (代码风格) */
.hero-description {
font-size: 1.25rem;
color: var(--text-secondary);
margin-bottom: 3rem;
font-family: var(--font-mono);
min-height: 3.6em; /* 预留高度防止抖动 */
}
/* --- 流式输出字符样式 --- */
.stream-char {
transition: opacity 0.4s ease; /* 平滑淡入 */
}
/* --- 服务展示区 (Services) --- */
.services-provided {
margin-top: 5rem;
position: relative;
z-index: 2;
}
/* 标题带有命令提示符风格 */
.services-provided h2 {
font-size: 1.5rem;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: none;
color: var(--text-primary);
display: flex; /* 改为 flex 以支持全宽下划线 */
align-items: center;
}
.services-provided h2::before {
content: "$";
color: var(--color-primary); /* 统一使用蓝色,保持与 blog h2 风格一致 */
margin-right: 10px; /* 保持与 blog h2 一致的间距 */
font-family: var(--font-mono);
font-weight: 800;
}
/* 服务卡片网格 */
.services-grid-box {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
padding: 0 10px;
}
.service-item {
background: var(--bg-card);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
padding: 32px 24px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
transition: all var(--duration-fast);
text-decoration: none;
}
.service-item:hover {
transform: translateY(-4px);
border-color: var(--color-primary-light);
box-shadow: var(--shadow-lg);
}
.service-icon {
margin-bottom: 1.5rem;
color: var(--color-primary);
/* 确保 SVG 继承颜色 */
}
.service-icon svg {
width: 80px;
height: 80px;
display: block;
}
.service-item span {
font-weight: 600;
color: var(--text-primary);
font-size: 1.1rem;
}
/* --- 响应式适配 --- */
@media (max-width: 1100px) {
.services-grid-box {
grid-template-columns: repeat(2, 1fr); /* 平板/小屏变 2 列 */
}
}
@media (max-width: 768px) {
.hero-content h1 {
font-size: 2.25rem;
}
.hero-description {
font-size: 1rem;
}
}
@media (max-width: 600px) {
.services-grid-box {
grid-template-columns: 1fr; /* 手机端单列 */
}
}
+244
View File
@@ -0,0 +1,244 @@
/* =========================================
页眉布局 (Header & Navigation)
========================================= */
.site-header {
height: 70px;
background-color: var(--bg-body);
border-bottom: 1px solid var(--border-muted);
position: sticky; /* 粘性定位,确保始终置顶 */
top: 0;
z-index: 1000;
backdrop-filter: blur(12px); /* 毛玻璃效果 */
-webkit-backdrop-filter: blur(12px);
/* 使用半透明背景以增强毛玻璃效果 */
background-color: rgba(255, 255, 255, 0.85);
transition: background-color var(--duration-normal), border-color var(--duration-normal);
flex-shrink: 0; /* 防止被父容器 Flex 布局压缩 */
}
.site-header .container {
height: 100%; /* 关键修复:让容器撑满 Header 高度,使内部 flex 垂直居中生效 */
}
[data-theme="dark"] .site-header {
background-color: rgba(13, 17, 23, 0.85);
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
}
/* --- Logo 区域 --- */
.logo-container,
.logo-link {
display: flex;
align-items: center;
height: 100%;
}
.logo-main {
height: 52px; /* 增大 Logo 尺寸 */
width: auto;
color: var(--text-primary);
}
/* --- 主导航 (Navigation) --- */
.main-navigation {
display: flex;
align-items: center;
gap: 24px;
}
.nav-menu {
display: flex;
list-style: none;
gap: 8px; /* 菜单项间距 */
margin: 0;
padding: 0;
}
.nav-menu a {
color: var(--text-secondary);
font-weight: 500;
font-size: 15px;
padding: 8px 16px;
border-radius: var(--radius-sm);
transition: all var(--duration-fast);
display: flex;
align-items: center;
}
.nav-menu a:hover,
.nav-menu a:focus {
color: var(--text-primary);
background-color: var(--bg-surface);
}
/* --- 社交链接与工具 (Social & Tools) --- */
.social-links {
display: flex;
align-items: center;
gap: 12px;
padding-left: 12px;
margin-left: 12px;
border-left: 1px solid var(--border-muted);
}
.social-links a,
.theme-toggle,
.lang-toggle {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
background: transparent;
border: 1px solid transparent; /* 预留边框位置防止抖动 */
border-radius: var(--radius-sm);
cursor: pointer;
transition: all var(--duration-fast);
}
.social-links a:hover,
.theme-toggle:hover,
.lang-toggle:hover {
background-color: var(--bg-surface);
color: var(--color-primary);
border-color: var(--border-default);
}
/* --- 主题切换动画 (Theme Toggle) --- */
.theme-toggle {
position: relative; /* 为内部 SVG 绝对定位做准备 */
overflow: hidden;
}
.theme-toggle svg {
position: absolute;
transition: transform 0.5s var(--ease-in-out), opacity 0.5s;
}
/* 默认 / 浅色模式状态: 显示月亮 (提示切换到深色) */
/* 修正逻辑:通常浅色模式下,按钮为了表示“点击切换到深色”,会显示月亮;
但也有一种逻辑是显示“当前是太阳”。
根据之前的代码意图,我们从 CSS 变量来看:
浅色模式下,.moon-icon 显示,.sun-icon 隐藏 */
/* 浅色模式下:太阳隐藏 */
html:not([data-theme="dark"]) .sun-icon {
opacity: 0;
transform: rotate(90deg) scale(0);
}
/* 浅色模式下:月亮显示 */
html:not([data-theme="dark"]) .moon-icon {
opacity: 1;
transform: rotate(0) scale(1);
}
/* 深色模式下:太阳显示 */
[data-theme="dark"] .sun-icon {
opacity: 1;
transform: rotate(0) scale(1);
}
/* 深色模式下:月亮隐藏 */
[data-theme="dark"] .moon-icon {
opacity: 0;
transform: rotate(-90deg) scale(0);
}
/* 语言切换按钮文字 */
.lang-toggle {
font-weight: 600;
font-size: 14px;
width: auto;
padding: 0 10px;
}
/* --- 移动端菜单开关 (Hamburger) --- */
.mobile-menu-toggle {
display: none; /* 默认隐藏 */
flex-direction: column;
justify-content: space-between;
width: 24px;
height: 18px;
background: transparent;
border: none;
cursor: pointer;
z-index: 1100;
padding: 0;
}
.mobile-menu-toggle span {
display: block;
width: 100%;
height: 2px;
background-color: var(--text-secondary);
border-radius: 2px;
transition: all 0.3s var(--ease-in-out);
transform-origin: left center;
}
/* 激活状态 (X 形状) */
.mobile-menu-toggle.active span:nth-child(1) {
transform: rotate(45deg) translate(0px, -2px);
width: 115%;
}
.mobile-menu-toggle.active span:nth-child(2) {
opacity: 0;
transform: translateX(-10px);
}
.mobile-menu-toggle.active span:nth-child(3) {
transform: rotate(-45deg) translate(0px, 2px);
width: 115%;
}
/* --- 响应式适配 --- */
@media (max-width: 900px) {
.mobile-menu-toggle {
display: flex;
}
.nav-menu {
position: absolute;
top: 100%;
left: 0;
right: 0;
background-color: var(--bg-body);
border-bottom: 1px solid var(--border-default);
flex-direction: column;
padding: 1rem;
gap: 0;
/* 默认收起状态 */
opacity: 0;
transform: translateY(-10px);
pointer-events: none;
transition: all var(--duration-normal) var(--ease-in-out);
box-shadow: var(--shadow-md);
}
.nav-menu.active {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
.nav-menu a {
width: 100%;
padding: 12px 16px;
justify-content: flex-start;
}
/* 移动端隐藏社交分割线 */
.social-links {
border-left: none;
margin-left: auto; /* 推到右侧 */
}
}
-832
View File
@@ -1,832 +0,0 @@
.site-header {
background-color: var(--header-bg);
border-bottom: 1px solid var(--border-color);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 1000;
transition: background-color var(--transition-speed), border-color var(--transition-speed);
}
.site-header .container {
max-width: 100%;
padding: 0 40px;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 0;
width: 100%;
}
.logo-container {
display: flex;
align-items: center;
gap: 1rem;
}
.logo-main {
height: 60px;
width: auto;
color: var(--text-color);
}
.main-navigation {
display: flex;
align-items: center;
gap: 2rem;
}
.nav-menu {
display: flex;
list-style: none;
gap: 2rem;
margin: 0;
padding: 0;
}
.nav-menu a {
color: var(--text-color);
font-weight: 500;
transition: color var(--transition-speed);
}
.nav-menu a:hover {
color: var(--accent-color);
}
.social-links {
display: flex;
align-items: center;
gap: 1rem;
}
.social-links a,
.theme-toggle,
.lang-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
color: var(--text-color);
background: transparent;
border: none;
cursor: pointer;
border-radius: 50%;
transition: background-color var(--transition-speed), color var(--transition-speed);
}
.lang-toggle {
width: 40px;
font-weight: 600;
font-size: 14px;
}
.social-links a:hover,
.theme-toggle:hover,
.lang-toggle:hover {
background-color: var(--gray-200);
}
[data-theme="dark"] .social-links a:hover,
[data-theme="dark"] .theme-toggle:hover,
[data-theme="dark"] .lang-toggle:hover {
background-color: var(--gray-700);
}
.theme-toggle .sun-icon {
display: none;
}
.theme-toggle .moon-icon {
display: block;
}
[data-theme="dark"] .theme-toggle .sun-icon {
display: block;
}
[data-theme="dark"] .theme-toggle .moon-icon {
display: none;
}
.mobile-menu-toggle {
display: none;
flex-direction: column;
gap: 4px;
background: transparent;
border: none;
cursor: pointer;
padding: 8px;
}
.mobile-menu-toggle span {
display: block;
width: 24px;
height: 2px;
background-color: var(--text-color);
transition: all var(--transition-speed);
}
.hero-section {
padding: 4rem 0;
text-align: center;
}
.hero-content h1 {
font-size: 3rem;
margin-bottom: 1.5rem;
color: var(--accent-color);
}
body[lang="en"] .hero-content h1::before {
content: attr(data-en);
}
body:not([lang="en"]) .hero-content h1::before {
content: attr(data-cn);
}
.hero-content h1 {
font-size: 0;
}
.hero-content h1::before {
font-size: 3rem;
}
.hero-description {
font-size: 1.125rem;
line-height: 1.8;
max-width: 800px;
margin: 0 auto;
color: var(--text-color);
}
body[lang="en"] .hero-description::before {
content: attr(data-en);
}
body:not([lang="en"]) .hero-description::before {
content: attr(data-cn);
}
.hero-description {
font-size: 0;
}
.hero-description::before {
font-size: 1.125rem;
}
.services-provided {
margin-top: 4rem;
margin-bottom: 2rem;
}
.services-provided h2 {
font-size: 1.75rem;
margin-bottom: 1.5rem;
color: var(--text-color);
text-align: left;
}
body[lang="en"] .services-provided h2::before {
content: attr(data-en);
}
body:not([lang="en"]) .services-provided h2::before {
content: attr(data-cn);
}
.services-provided h2 {
font-size: 0;
}
.services-provided h2::before {
font-size: 1.75rem;
}
.services-grid-box {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 2rem;
}
.service-item {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 1.5rem;
text-decoration: none;
}
.service-icon {
margin-bottom: 1rem;
}
.service-icon svg {
width: 96px;
height: 96px;
}
.service-item span {
font-size: 1.5rem;
font-weight: 500;
color: var(--text-color);
}
body[lang="en"] .service-item span::before {
content: attr(data-en);
}
body:not([lang="en"]) .service-item span::before {
content: attr(data-cn);
}
.service-item span {
font-size: 0;
}
.service-item span::before {
font-size: 1.5rem;
}
@media (max-width: 1024px) {
.services-grid-box {
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
}
}
@media (max-width: 768px) {
.services-grid-box {
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.service-icon svg {
width: 80px;
height: 80px;
}
}
@media (max-width: 480px) {
.services-grid-box {
grid-template-columns: 1fr;
}
}
.content-section {
padding: 3rem 0;
}
.content-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
}
.announcements-column h2,
.blog-column h2 {
font-size: 1.75rem;
margin-bottom: 1.5rem;
color: var(--text-color);
}
body[lang="en"] .nav-menu a::before,
body[lang="en"] h2[data-en]::before {
content: attr(data-en);
}
body:not([lang="en"]) .nav-menu a::before,
body:not([lang="en"]) h2[data-cn]::before {
content: attr(data-cn);
}
.nav-menu a {
font-size: 0;
}
.nav-menu a::before {
font-size: 1rem;
}
.post-list {
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.post-item {
padding: 1.25rem;
background-color: var(--header-bg);
border-radius: 8px;
border: 1px solid var(--border-color);
transition: transform var(--transition-speed), box-shadow var(--transition-speed);
}
.post-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.post-item h3 {
font-size: 1.125rem;
margin-bottom: 0.5rem;
}
.post-item h3 a {
color: var(--text-color);
}
.post-item time {
font-size: 0.875rem;
color: var(--gray-500);
}
.site-main {
background-color: var(--bg-color);
flex: 1;
min-height: calc(100vh - 100px);
padding-top: 70px;
}
.site-footer {
background-color: var(--footer-bg);
border-top: 1px solid var(--border-color);
padding: 3rem 0 1.5rem;
margin-top: 4rem;
}
.footer-content {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
margin-bottom: 2rem;
}
.footer-section h3 {
font-size: 1.125rem;
margin-bottom: 1rem;
color: var(--text-color);
}
body[lang="en"] .footer-section h3::before {
content: attr(data-en);
}
body:not([lang="en"]) .footer-section h3::before {
content: attr(data-cn);
}
.footer-section h3 {
font-size: 0;
}
.footer-section h3::before {
font-size: 1.125rem;
}
.footer-links {
list-style: none;
}
.footer-links li {
margin-bottom: 0.5rem;
}
.footer-links a {
color: var(--text-color);
font-size: 0.9rem;
}
body[lang="en"] .footer-links a::before {
content: attr(data-en);
}
body:not([lang="en"]) .footer-links a::before {
content: attr(data-cn);
}
.footer-links a[data-cn] {
font-size: 0;
}
.footer-links a[data-cn]::before {
font-size: 0.9rem;
}
.footer-bottom {
text-align: center;
padding-top: 2rem;
border-top: 1px solid var(--border-color);
}
.footer-bottom p {
font-size: 0.875rem;
color: var(--gray-500);
}
body[lang="en"] .footer-bottom p::before {
content: attr(data-en);
}
body:not([lang="en"]) .footer-bottom p::before {
content: attr(data-cn);
}
.footer-bottom p {
font-size: 0;
}
.footer-bottom p::before {
font-size: 0.875rem;
}
@media (max-width: 1024px) {
.nav-menu {
gap: 1.5rem;
}
.content-grid {
gap: 2rem;
}
.footer-content {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.mobile-menu-toggle {
display: flex;
}
.site-header .container {
padding: 0 20px;
}
.main-navigation {
position: relative;
}
.nav-menu {
position: absolute;
top: 100%;
right: 0;
background-color: var(--header-bg);
flex-direction: column;
padding: 1rem;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
display: none;
min-width: 200px;
}
.nav-menu.active {
display: flex;
}
.hero-content h1 {
font-size: 2rem;
}
.hero-description {
font-size: 1rem;
}
.content-grid {
grid-template-columns: 1fr;
gap: 2rem;
}
.footer-content {
grid-template-columns: 1fr;
gap: 1.5rem;
}
}
@media (max-width: 480px) {
.logo-main {
height: 50px;
}
.hero-content h1 {
font-size: 1.5rem;
}
.social-links a,
.theme-toggle {
width: 32px;
height: 32px;
}
}
.single-post,
.page-content {
padding: 3rem 0;
}
.entry-header {
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--border-color);
}
.entry-title {
font-size: 2.5rem;
line-height: 1.2;
margin-bottom: 1rem;
color: var(--text-color);
}
.entry-meta {
font-size: 0.9rem;
color: var(--gray-500);
}
.entry-meta .separator {
margin: 0 0.5rem;
}
.entry-thumbnail {
margin-bottom: 2rem;
}
.entry-thumbnail img {
width: 100%;
height: auto;
border-radius: 8px;
}
.entry-content {
font-size: 1.125rem;
line-height: 1.8;
color: var(--text-color);
}
.entry-content h2,
.entry-content h3,
.entry-content h4 {
margin-top: 2rem;
margin-bottom: 1rem;
color: var(--text-color);
}
.entry-content p {
margin-bottom: 1.5rem;
}
.entry-content a {
color: var(--accent-color);
text-decoration: underline;
}
.entry-content img {
max-width: 100%;
height: auto;
border-radius: 8px;
margin: 1.5rem 0;
}
.entry-content ul,
.entry-content ol {
margin-bottom: 1.5rem;
padding-left: 2rem;
}
.entry-content li {
margin-bottom: 0.5rem;
}
.entry-content code {
background-color: var(--gray-200);
padding: 0.2rem 0.4rem;
border-radius: 4px;
font-size: 0.9em;
font-family: 'Consolas', 'Monaco', monospace;
}
[data-theme="dark"] .entry-content code {
background-color: var(--gray-700);
}
.entry-content pre {
background-color: var(--gray-200);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
margin-bottom: 1.5rem;
}
[data-theme="dark"] .entry-content pre {
background-color: var(--gray-800);
}
.entry-content pre code {
background-color: transparent;
padding: 0;
}
.entry-footer {
margin-top: 3rem;
padding-top: 2rem;
border-top: 1px solid var(--border-color);
}
.entry-categories,
.entry-tags {
margin-bottom: 1rem;
}
.entry-categories a,
.entry-tags a {
display: inline-block;
padding: 0.25rem 0.75rem;
margin-right: 0.5rem;
background-color: var(--gray-200);
border-radius: 4px;
font-size: 0.9rem;
color: var(--text-color);
}
[data-theme="dark"] .entry-categories a,
[data-theme="dark"] .entry-tags a {
background-color: var(--gray-700);
}
.archive-header {
margin-bottom: 3rem;
text-align: center;
}
.archive-title {
font-size: 2.5rem;
margin-bottom: 1rem;
color: var(--text-color);
}
.archive-description {
font-size: 1.125rem;
color: var(--gray-500);
}
.posts-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
}
.archive-item {
background-color: var(--header-bg);
border-radius: 8px;
border: 1px solid var(--border-color);
overflow: hidden;
transition: transform var(--transition-speed), box-shadow var(--transition-speed);
}
.archive-item:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
.archive-thumbnail img {
width: 100%;
height: 200px;
object-fit: cover;
}
.archive-content {
padding: 1.5rem;
}
.archive-item-title {
font-size: 1.25rem;
margin-bottom: 0.75rem;
}
.archive-item-title a {
color: var(--text-color);
}
.archive-meta {
font-size: 0.875rem;
color: var(--gray-500);
margin-bottom: 1rem;
}
.archive-meta .separator {
margin: 0 0.5rem;
}
.archive-excerpt {
font-size: 0.95rem;
line-height: 1.6;
color: var(--text-color);
margin-bottom: 1rem;
}
.read-more {
color: var(--accent-color);
font-weight: 500;
font-size: 0.9rem;
}
.pagination {
display: flex;
justify-content: center;
gap: 0.5rem;
}
.pagination .nav-links {
display: flex;
gap: 0.5rem;
}
.pagination a,
.pagination span {
padding: 0.5rem 1rem;
background-color: var(--header-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
color: var(--text-color);
transition: background-color var(--transition-speed);
}
.pagination a:hover {
background-color: var(--accent-color);
color: var(--white);
}
.pagination .current {
background-color: var(--accent-color);
color: var(--white);
}
.error-404 {
padding: 6rem 0;
}
.error-content {
text-align: center;
max-width: 600px;
margin: 0 auto;
}
.error-title {
font-size: 8rem;
color: var(--accent-color);
margin-bottom: 1rem;
}
.error-content h2 {
font-size: 2rem;
margin-bottom: 1rem;
color: var(--text-color);
}
.error-content p {
font-size: 1.125rem;
color: var(--gray-500);
margin-bottom: 2rem;
}
.btn-home {
display: inline-block;
padding: 0.75rem 2rem;
background-color: var(--accent-color);
color: var(--white);
border-radius: 8px;
font-weight: 500;
transition: opacity var(--transition-speed);
}
.btn-home:hover {
opacity: 0.9;
}
@media (max-width: 768px) {
.entry-title {
font-size: 2rem;
}
.archive-title {
font-size: 2rem;
}
.posts-grid {
grid-template-columns: 1fr;
}
.error-title {
font-size: 5rem;
}
}
+43
View File
@@ -0,0 +1,43 @@
const langToggle = document.querySelector('.lang-toggle');
const body = document.body;
function getPreferredLang() {
const savedLang = localStorage.getItem('language');
if (savedLang) {
return savedLang;
}
return 'zh';
}
function setLang(lang) {
if (lang === 'en') {
body.setAttribute('lang', 'en');
if (langToggle) {
langToggle.querySelector('.lang-text').textContent = '中';
}
} else {
body.setAttribute('lang', 'zh');
if (langToggle) {
langToggle.querySelector('.lang-text').textContent = 'EN';
}
}
// 处理 Input 元素的值切换 (input[type=submit] cannot use CSS content replacement)
const inputs = document.querySelectorAll('input[type="submit"][data-cn][data-en]');
inputs.forEach(input => {
input.value = lang === 'en' ? input.getAttribute('data-en') : input.getAttribute('data-cn');
});
localStorage.setItem('language', lang);
}
const initialLang = getPreferredLang();
setLang(initialLang);
if (langToggle) {
langToggle.addEventListener('click', () => {
const currentLang = body.getAttribute('lang');
const newLang = currentLang === 'en' ? 'zh' : 'en';
setLang(newLang);
});
}
+100
View File
@@ -0,0 +1,100 @@
document.addEventListener('DOMContentLoaded', function() {
const container = document.querySelector('.hero-description');
if (!container) return;
const cnText = container.getAttribute('data-cn') || '';
const enText = container.getAttribute('data-en') || '';
// 标记动画是否已经完整播放过一次
let hasPlayedOnce = false;
// 存储当前的定时器,以便清理
let timeouts = [];
function getCurrentText() {
return document.body.getAttribute('lang') === 'en' ? enText : cnText;
}
function clearTimeouts() {
timeouts.forEach(t => clearTimeout(t));
timeouts = [];
}
// 渲染文本的核心函数
// text: 要显示的文本
// animate: 是否需要逐字流式动画
function render(text, animate) {
clearTimeouts();
// 使用 Array.from 正确处理 Unicode 字符
const chars = Array.from(text);
// 生成 HTML:每个字符包裹在 span 中
// 如果需要动画,初始透明度为 0
// 如果不需要动画(切换语言时),初始透明度直接为 1
const initialOpacity = animate ? '0' : '1';
// 生成 spans 字符串
const html = chars.map(char => {
// 对空格也可以处理,虽然空格看不见
return `<span class="stream-char" style="opacity: ${initialOpacity};">${char}</span>`;
}).join('');
// 一次性插入 DOM,这时容器会被透明字符撑开,布局位置固定
container.innerHTML = html;
// 如果不需要动画,直接结束
if (!animate) {
return;
}
// 开始执行流式淡入动画
const spans = container.querySelectorAll('.stream-char');
// 基础延迟累加器
let accumulatedDelay = 0;
spans.forEach((span, index) => {
// 模拟流式生成的随机节奏
// 基础 20ms,随机增加 0-30ms
const step = 20 + Math.random() * 30;
accumulatedDelay += step;
// 遇到标点符号稍微停顿一下
if (/[,.。;!?:]/.test(span.textContent)) {
accumulatedDelay += 100;
}
const t = setTimeout(() => {
span.style.opacity = '1';
// 当最后一个字符显示完毕,标记动画已播放
if (index === spans.length - 1) {
hasPlayedOnce = true;
}
}, accumulatedDelay);
timeouts.push(t);
});
}
// 监听语言切换
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'attributes' && mutation.attributeName === 'lang') {
const newText = getCurrentText();
// 需求:如果动画已经播放完成过一次,切换语言就不再播放
// 注意:如果用户在动画还没播放完时就切换语言,为了体验,通常也应该直接显示新语言(视为打断),防止混乱
// 所以只要是切换语言,我们将动画设为 false (除非你想每次刷新页面都看)
// 既然用户强调 "如果动画已经播放完成过一次...就不应该再播放",隐含初次加载要播放。
// 我们这里处理逻辑:切换语言时,强制不播放动画 (直接显示),并标记 hasPlayedOnce = true (以防万一)
hasPlayedOnce = true;
render(newText, false);
}
});
});
observer.observe(document.body, { attributes: true });
// 页面首次加载:播放动画
render(getCurrentText(), true);
});
+66
View File
@@ -0,0 +1,66 @@
<?php
if (post_password_required()) {
return;
}
?>
<div id="comments" class="comments-area">
<?php if (have_comments()) : ?>
<div class="comments-header">
<h3 class="comments-title">
<?php
$comment_count = get_comments_number();
if ($comment_count === 1) {
printf(esc_html__('1个回复', 'itstudio'));
} else {
printf(
/* translators: 1: comment count number */
esc_html(_n('%1$s个回复', '%1$s个回复', $comment_count, 'itstudio')),
number_format_i18n($comment_count)
);
}
?>
</h3>
</div>
<ol class="comment-list">
<?php
wp_list_comments(array(
'style' => 'ol',
'short_ping' => true,
'avatar_size' => 48,
'callback' => 'itstudio_comment_callback' // We will need to define this in functions.php or handle logic here if simple
));
?>
</ol>
<?php
the_comments_navigation();
// If comments are closed and there are comments, let's leave a little note, shall we?
if (!comments_open()) :
?>
<p class="no-comments"><?php esc_html_e('评论已关闭。', 'itstudio'); ?></p>
<?php
endif;
endif; // Check for have_comments().
?>
<div class="comment-form-wrapper">
<?php
comment_form(array(
'class_form' => 'gh-comment-form',
'title_reply_before' => '<h3 id="reply-title" class="comment-reply-title" data-cn="发表回复" data-en="Leave a comment">',
'title_reply_after' => '</h3>',
'title_reply' => '', // Handled by data-cn/en in before tag
'label_submit' => __('发表评论', 'itstudio'), // This submits button text, harder to change via attr, usually needs JS or just leave as is if acceptable
'submit_button' => '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="" data-cn="发表评论" data-en="Comment" />',
'comment_notes_before' => '',
'comment_field' => '<div class="comment-form-comment"><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true"></textarea></div>',
));
?>
</div>
</div><!-- #comments -->
+1 -1
View File
@@ -5,7 +5,7 @@
<h3 data-cn="友情链接" data-en="Links"></h3>
<ul class="footer-links">
<li><a href="https://www.ouc.edu.cn" target="_blank" rel="noopener" data-cn="中国海洋大学" data-en="Ocean University of China"></a></li>
<li><a href="https://cst.ouc.edu.cn" target="_blank" rel="noopener" data-cn="信息科学与工程学部" data-en="College of Computer Science"></a></li>
<li><a href="https://it.ouc.edu.cn" target="_blank" rel="noopener" data-cn="信息科学与工程学部" data-en="Faculty of Information Science and Engineering"></a></li>
</ul>
</div>
+91 -3
View File
@@ -21,12 +21,25 @@ function itstudio_theme_setup() {
add_action('after_setup_theme', 'itstudio_theme_setup');
function itstudio_enqueue_scripts() {
wp_enqueue_style('itstudio-style', get_stylesheet_uri(), array(), '1.0.0');
wp_enqueue_style('itstudio-main', get_template_directory_uri() . '/assets/css/main.css', array(), '1.0.0');
// 基础样式 (Style.css)
wp_enqueue_style('itstudio-style', get_stylesheet_uri(), array(), '2.1.2');
wp_enqueue_style('itstudio-header', get_template_directory_uri() . '/assets/css/header.css', array('itstudio-style'), '2.1.2');
wp_enqueue_style('itstudio-footer', get_template_directory_uri() . '/assets/css/footer.css', array('itstudio-style'), '2.1.2');
wp_enqueue_style('itstudio-content', get_template_directory_uri() . '/assets/css/content.css', array('itstudio-style'), '2.1.2');
// 仅在首页加载 Hero 样式
if (is_front_page() || is_home()) {
wp_enqueue_style('itstudio-front-page', get_template_directory_uri() . '/assets/css/front-page.css', array('itstudio-style'), '2.1.2');
}
// Scripts
wp_enqueue_script('itstudio-theme-toggle', get_template_directory_uri() . '/assets/js/theme-toggle.js', array(), '1.0.0', true);
wp_enqueue_script('itstudio-lang-toggle', get_template_directory_uri() . '/assets/js/lang-toggle.js', array(), '1.0.0', true);
wp_enqueue_script('itstudio-footer-slide', get_template_directory_uri() . '/assets/js/footer-slide.js', array(), '1.0.0', true);
// 注册并加载打字机效果脚本 - 仅在首页
if (is_front_page() || is_home()) {
wp_enqueue_script('itstudio-stream', get_template_directory_uri() . '/assets/js/stream.js', array(), '1.0.0', true);
}
wp_enqueue_script('itstudio-main', get_template_directory_uri() . '/assets/js/main.js', array(), '1.0.0', true);
}
add_action('wp_enqueue_scripts', 'itstudio_enqueue_scripts');
@@ -68,3 +81,78 @@ function itstudio_custom_post_types() {
));
}
add_action('init', 'itstudio_custom_post_types');
/**
* GitHub 风格评论
*/
function itstudio_comment_callback($comment, $args, $depth) {
?>
<li id="comment-<?php comment_ID(); ?>" <?php comment_class('gh-comment-item'); ?>>
<div class="gh-comment-avatar">
<?php if ($args['avatar_size'] != 0) echo get_avatar($comment, $args['avatar_size']); ?>
</div>
<div class="gh-comment-box">
<div class="gh-comment-header">
<div class="gh-comment-meta">
<span class="gh-author-name"><?php echo get_comment_author_link(); ?></span>
<!-- 双语支持: commented on / 评论于 -->
<span class="gh-action-text" data-cn="评论于" data-en="commented on"></span>
<a href="<?php echo htmlspecialchars(get_comment_link($comment->comment_ID)); ?>">
<time datetime="<?php comment_time('c'); ?>">
<?php
// 处理时间双语
$time_diff = human_time_diff(get_comment_time('U'), current_time('timestamp'));
// 简单的替换逻辑,或者直接输出两个 span
printf(
'<span data-cn="%s前" data-en="%s ago"></span>',
$time_diff, // 中文环境通常也是数字+单位(如 5 分钟),这里简化处理,假设 time_diff 本身已本地化或接受英文
$time_diff
);
// 注意:WP的 human_time_diff 返回的是翻译后的字符串(如果后台是中文),
// 要实现完美的前端双语切换,需要一种不依赖后台语言设置的方式,或者接受后台返回当前语言的时间。
// 鉴于切换是纯前端的,最佳方式是让 PHP 输出特定格式,前端解析,但这里为了简单,
// 我们假设 time_diff 主要是数字+单位。
// 更稳妥的方式是直接显示标准日期格式,或者接受当前状态。
// 这里先简单处理结构。
?>
</time>
</a>
<?php
// Author Badge
$post = get_post();
if ($comment->user_id === $post->post_author) {
// 双语支持: Author / 作者
echo '<span class="gh-badge author" data-cn="作者" data-en="Author"></span>';
}
?>
</div>
<div class="gh-header-actions">
<?php edit_comment_link('', '', '', null, 'gh-edit-link'); /* 获取链接URL逻辑较复杂,这里直接用 edit_comment_link 输出,但内容需要自定义 */ ?>
<span class="edit-link-wrapper">
<?php
// 为了支持双语,我们不仅需要 URL,还需要在这里手动构造 A 标签,或者利用 PHP 里的 filter
// 但 edit_comment_link 直接输出 HTML。
// 简单方案:输出时内容留空,用 CSS 伪元素填充。
// edit_comment_link( $text, $before, $after )
// 我们可以把 $text 设为空字符串,并给 wrapper 加 data 属性? 不行,A标签内部是空的。
// 我们可以让 A 标签带上 data 属性吗? edit_comment_link 没有直接参数加属性到 A 标签。
// 替代方案:手动构建
if (current_user_can('edit_comment', $comment->comment_ID)) {
$edit_url = get_edit_comment_link($comment->comment_ID);
echo '<a class="comment-edit-link" href="' . esc_url($edit_url) . '" data-cn="编辑" data-en="Edit"></a>';
}
?>
</span>
</div>
</div>
<div class="gh-comment-body">
<?php if ($comment->comment_approved == '0') : ?>
<em class="comment-awaiting-moderation" data-cn="您的评论正在等待审核。" data-en="Your comment is awaiting moderation."></em>
<br />
<?php endif; ?>
<?php comment_text(); ?>
</div>
</div>
</li>
<?php
}
+77 -109
View File
@@ -10,22 +10,15 @@
<!-- 服务提供模块 -->
<div class="services-provided">
<h2 data-cn="@服务提供" data-en="@Our Services"></h2>
<h2 data-cn="# 服务提供" data-en="# Our Services"></h2>
<div class="services-grid-box">
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-res" x1="0" y1="64" x2="64" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<path d="M4,16 L24,16 L30,22 L60,22 L60,54 L4,54 Z" fill="#bab5ec" opacity="0.5"/>
<rect x="10" y="10" width="40" height="40" fill="#f8d1d9" rx="2" />
<rect x="16" y="18" width="20" height="2" fill="#bab5ec" />
<rect x="16" y="24" width="28" height="2" fill="#bab5ec" />
<path d="M4,28 L60,28 L60,54 A4,4 0 0,1 56,58 L8,58 A4,4 0 0,1 4,54 Z" fill="url(#grad-res)"/>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M10 14L24 14L28 20H54C56.2091 20 58 21.7909 58 24V50C58 52.2091 56.2091 54 54 54H10C7.79086 54 6 52.2091 6 50V18C6 15.7909 7.79086 14 10 14Z" stroke="#ccd6f6"/>
<path d="M22 34H42" stroke="#64ffda"/>
<path d="M22 42H34" stroke="#64ffda"/>
<circle cx="48" cy="42" r="2" fill="#64ffda" stroke="none"/>
</svg>
</div>
<span data-cn="资源站" data-en="Resources"></span>
@@ -33,19 +26,14 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="mirror-gradient" x1="10" y1="60" x2="54" y2="4" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<path d="M32,4 A28,28 0 1,1 4,32 A28,28 0 0,1 32,4 M32,22 A10,10 0 1,0 42,32 A10,10 0 0,0 32,22 Z" fill="url(#mirror-gradient)" stroke="#bab5ec" stroke-width="1" opacity="0.95"/>
<path d="M32,4 A28,28 0 0,1 60,32 L42,32 A10,10 0 0,0 32,22 Z" fill="#f8d1d9" opacity="0.8"/>
<circle cx="32" cy="32" r="7" fill="none" stroke="#f8d1d9" stroke-width="2" opacity="0.6" />
<rect x="14" y="42" width="4" height="4" rx="1" fill="#bab5ec" transform="rotate(45 16 44)" />
<rect x="50" y="14" width="3" height="3" rx="0.5" fill="#f8d1d9" />
<path d="M16,46 A22,22 0 0,0 48,46" fill="none" stroke="#f8d1d9" stroke-width="2" stroke-linecap="round" stroke-dasharray="4 4" opacity="0.5" />
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="32" cy="32" r="24" stroke="#ccd6f6"/>
<circle cx="32" cy="32" r="8" stroke="#ccd6f6"/>
<path d="M32 24V8" stroke="#64ffda"/>
<path d="M32 40V56" stroke="#233554"/>
<path d="M49 32H56" stroke="#64ffda"/>
<path d="M8 32H15" stroke="#233554"/>
<path d="M44 14C48 18 50 24 50 32" stroke="#64ffda" stroke-dasharray="4 4"/>
</svg>
</div>
<span data-cn="校内镜像站" data-en="Mirror Site"></span>
@@ -53,22 +41,13 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-code" x1="10" y1="60" x2="50" y2="10" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<rect x="8" y="8" width="48" height="48" rx="3" fill="none" stroke="#bab5ec" stroke-width="2"/>
<rect x="12" y="14" width="40" height="10" rx="1" fill="url(#grad-code)"/>
<circle cx="46" cy="19" r="2" fill="#f8d1d9"/>
<circle cx="40" cy="19" r="2" fill="#fff" opacity="0.5"/>
<rect x="12" y="27" width="40" height="10" rx="1" fill="url(#grad-code)"/>
<circle cx="46" cy="32" r="2" fill="#f8d1d9"/>
<rect x="12" y="40" width="40" height="10" rx="1" fill="url(#grad-code)"/>
<circle cx="46" cy="45" r="2" fill="#f8d1d9"/>
<circle cx="40" cy="45" r="2" fill="#fff" opacity="0.5"/>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="16" y1="12" x2="16" y2="52" stroke="#ccd6f6"/>
<circle cx="16" cy="12" r="4" stroke="#ccd6f6"/>
<circle cx="16" cy="32" r="4" stroke="#ccd6f6"/>
<circle cx="16" cy="52" r="4" stroke="#ccd6f6"/>
<path d="M16 32C26 32 36 36 36 44V48" stroke="#64ffda"/>
<circle cx="36" cy="48" r="4" stroke="#64ffda"/>
</svg>
</div>
<span data-cn="代码托管" data-en="Git Hosting"></span>
@@ -76,17 +55,12 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-mc" x1="0" y1="64" x2="64" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<path d="M32,6 L58,21 L32,36 L6,21 Z" fill="#f8d1d9"/>
<path d="M58,21 L58,51 L32,66 L32,36 Z" fill="#bab5ec"/>
<path d="M6,21 L32,36 L32,66 L6,51 Z" fill="url(#grad-mc)"/>
<rect x="28" y="30" width="8" height="8" transform="rotate(30 32 34) skewX(-30)" fill="#bab5ec" opacity="0.3"/>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M32 8L54 20V44L32 56L10 44V20L32 8Z" stroke="#ccd6f6"/>
<path d="M10 20L32 32L54 20" stroke="#ccd6f6"/>
<path d="M32 56V32" stroke="#ccd6f6"/>
<path d="M26 16L32 20L38 16" stroke="#64ffda"/>
<path d="M46 29L46 38" stroke="#64ffda"/>
</svg>
</div>
<span data-cn="Minecraft服务器" data-en="Minecraft Server"></span>
@@ -94,17 +68,11 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-chat" x1="0" y1="50" x2="50" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<path d="M28,10 L54,10 C56.2,10 58,11.8 58,14 L58,36 C58,38.2 56.2,40 54,40 L44,40 L44,46 L36,40 L28,40 C25.8,40 24,38.2 24,36 L24,14 C24,11.8 25.8,10 28,10 Z" fill="#bab5ec" opacity="0.4"/>
<path d="M8,20 L42,20 C44.2,20 46,21.8 46,24 L46,48 C46,50.2 44.2,52 42,52 L18,52 L10,58 L10,52 L8,52 C5.8,52 4,50.2 4,48 L4,24 C4,21.8 5.8,20 8,20 Z" fill="url(#grad-chat)"/>
<rect x="14" y="30" width="22" height="3" rx="1.5" fill="#f8d1d9"/>
<rect x="14" y="38" width="14" height="3" rx="1.5" fill="#f8d1d9"/>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 16H42V40H20L12 48V16Z" stroke="#ccd6f6"/>
<path d="M26 10H56V34H44L38 40V34H26V10Z" stroke="#64ffda"/>
<line x1="32" y1="20" x2="50" y2="20" stroke="#64ffda"/>
<line x1="32" y1="26" x2="44" y2="26" stroke="#64ffda"/>
</svg>
</div>
<span data-cn="OUC论坛" data-en="OUC Forum"></span>
@@ -112,20 +80,13 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-fix" x1="10" y1="50" x2="50" y2="10" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<circle cx="40" cy="24" r="14" fill="none" stroke="#bab5ec" stroke-width="4" stroke-dasharray="6 3"/>
<circle cx="40" cy="24" r="5" fill="#bab5ec" opacity="0.5"/>
<g transform="translate(-5, 5)">
<rect x="16" y="34" width="30" height="10" rx="2" transform="rotate(-45 31 39)" fill="url(#grad-fix)"/>
<path d="M12,12 C16,8 22,8 26,12 L22,16 C20,14 18,14 16,16 L12,12 Z" fill="url(#grad-fix)" transform="rotate(-45 19 14)"/>
<circle cx="14" cy="48" r="3" fill="#f8d1d9"/>
</g>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M46 14L50 18L26 42L22 38L46 14Z" stroke="#ccd6f6"/>
<path d="M22 38L14 46L18 50L26 42" stroke="#ccd6f6"/>
<path d="M14 46L10 54" stroke="#ccd6f6"/>
<path d="M45 28L36 19" stroke="#64ffda"/>
<path d="M20 44L14 50" stroke="#233554"/>
<path d="M50 15C53 12 58 12 60 14C62 16 62 21 59 24L34 49C32 51 29 51 27 49L25 47C23 45 23 42 25 40L50 15Z" stroke="#64ffda"/>
</svg>
</div>
<span data-cn="电脑维修" data-en="PC Repair"></span>
@@ -133,17 +94,14 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-58" x1="0" y1="60" x2="60" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<path d="M8,12 L30,12 L28,20 L16,20 L14,28 C16,26 20,26 24,28 C28,30 28,36 24,40 C20,44 12,42 10,38" fill="none" stroke="url(#grad-58)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M44,12 C38,12 36,20 44,24 C52,28 52,38 44,42 C36,38 36,28 44,24 C52,20 50,12 44,12 Z" fill="none" stroke="#bab5ec" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="54" cy="12" r="3" fill="#f8d1d9"/>
<rect x="4" y="46" width="6" height="6" transform="rotate(20)" fill="#bab5ec" opacity="0.6"/>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="10" y="12" width="44" height="40" rx="4" stroke="#ccd6f6"/>
<path d="M10 24H54" stroke="#ccd6f6"/>
<path d="M20 6V16" stroke="#ccd6f6"/>
<path d="M44 6V16" stroke="#ccd6f6"/>
<circle cx="32" cy="38" r="6" stroke="#64ffda"/>
<path d="M32 38L36 34" stroke="#64ffda"/>
<circle cx="32" cy="38" r="2" fill="#64ffda" stroke="none"/>
</svg>
</div>
<span data-cn="五八工坊预约" data-en="Workshop Booking"></span>
@@ -151,18 +109,12 @@
<a href="#" class="service-item">
<div class="service-icon">
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad-heart" x1="10" y1="50" x2="54" y2="10" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#bab5ec"/>
<stop offset="1" stop-color="#f1b7bf"/>
</linearGradient>
</defs>
<path d="M32,54 L12,34 C6,28 6,18 16,14 C22,12 28,16 32,22" fill="url(#grad-heart)"/>
<path d="M32,54 L52,34 C58,28 58,18 48,14 C42,12 36,16 32,22" fill="#bab5ec" opacity="0.8"/>
<path d="M32,8 L32,14" stroke="#f8d1d9" stroke-width="3" stroke-linecap="round"/>
<path d="M12,10 L16,14" stroke="#f8d1d9" stroke-width="2" stroke-linecap="round"/>
<path d="M52,10 L48,14" stroke="#f8d1d9" stroke-width="2" stroke-linecap="round"/>
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M32 56C32 56 56 44 56 26C56 16 46 10 38 16C35 18 32 22 32 22C32 22 29 18 26 16C18 10 8 16 8 26C8 44 32 56 32 56Z" stroke="#ccd6f6"/>
<path d="M32 22V36" stroke="#64ffda"/>
<circle cx="32" cy="40" r="3" stroke="#64ffda"/>
<path d="M18 28H24L26 32" stroke="#233554"/>
<path d="M46 28H40L38 32" stroke="#64ffda"/>
</svg>
</div>
<span data-cn="OUC便民服务" data-en="OUC Services"></span>
@@ -176,7 +128,7 @@
<div class="container">
<div class="content-grid">
<div class="announcements-column">
<h2 data-cn="@公告通知" data-en="@Announcements"></h2>
<h2 data-cn="# 公告通知" data-en="# Announcements"></h2>
<div class="post-list">
<?php
$announcements = new WP_Query(array(
@@ -190,21 +142,29 @@
while ($announcements->have_posts()) : $announcements->the_post();
?>
<article class="post-item">
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date(); ?></time>
<div class="post-content-wrapper">
<h3 class="post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<div class="post-excerpt">
<?php the_excerpt(); ?>
</div>
<div class="post-meta">
<span class="post-author"><?php echo get_the_author(); ?></span>
<time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date('Y年m月d日'); ?></time>
</div>
</div>
</article>
<?php
endwhile;
wp_reset_postdata();
else :
?>
<p><?php _e('暂无公告', 'itstudio'); ?></p>
<p data-cn="暂无公告" data-en="No announcements found."></p>
<?php endif; ?>
</div>
</div>
<div class="blog-column">
<h2 data-cn="@技术博客" data-en="@Blog"></h2>
<h2 data-cn="# 技术博客" data-en="# Blog"></h2>
<div class="post-list">
<?php
$blogs = new WP_Query(array(
@@ -218,15 +178,23 @@
while ($blogs->have_posts()) : $blogs->the_post();
?>
<article class="post-item">
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date(); ?></time>
<div class="post-content-wrapper">
<h3 class="post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<div class="post-excerpt">
<?php the_excerpt(); ?>
</div>
<div class="post-meta">
<span class="post-author"><?php echo get_the_author(); ?></span>
<time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date('Y年m月d日'); ?></time>
</div>
</div>
</article>
<?php
endwhile;
wp_reset_postdata();
else :
?>
<p><?php _e('暂无博客文章', 'itstudio'); ?></p>
<p data-cn="暂无博客文章" data-en="No blog posts found."></p>
<?php endif; ?>
</div>
</div>
+73 -39
View File
@@ -1,73 +1,107 @@
<?php get_header(); ?>
<main class="site-main single-post">
<main class="site-main single-post-gh-pro">
<div class="container">
<?php
while (have_posts()) :
the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<!-- 1. 文章头部:极简极客风,去掉 Issue 编号等干扰 -->
<header class="gh-pro-header">
<div class="gh-pro-meta-top">
<?php
$categories = get_the_category();
if ($categories) :
$cat = $categories[0];
echo '<a href="' . get_category_link($cat->term_id) . '" class="gh-label-category">' . $cat->name . '</a>';
endif;
?>
</div>
<h1 class="entry-title"><?php the_title(); ?></h1>
<div class="entry-meta">
<time datetime="<?php echo get_the_date('c'); ?>">
<?php echo get_the_date(); ?>
</time>
<?php if (get_post_type() === 'post') : ?>
<span class="separator">|</span>
<span class="author"><?php the_author(); ?></span>
<?php endif; ?>
<div class="gh-pro-meta-bar">
<div class="gh-author-lockup">
<?php echo get_avatar(get_the_author_meta('ID'), 32); ?>
<span class="author-name"><?php the_author(); ?></span>
<span class="meta-divider">/</span>
<span class="publish-date"><?php echo get_the_date('Y.m.d'); ?></span>
</div>
<div class="gh-stats">
<span class="stat-item" title="<?php esc_attr_e('Comments', 'itstudio'); ?>">
<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment"><path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg>
<?php comments_number('0', '1', '%'); ?>
</span>
</div>
</div>
</header>
<!-- 2. 正文容器:类似 GitHub File/Readme 的框体风格 -->
<div class="gh-pro-body-container">
<div class="gh-file-box">
<div class="gh-file-header">
<div class="file-info">
<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-book"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg>
<strong>readme.md</strong>
<span class="file-divider"></span>
<span class="file-size">
<?php
$read_time = round(str_word_count(strip_tags(get_the_content())) / 300, 1);
printf(
'<span data-cn="%s 分钟阅读" data-en="%s mins read"></span>',
$read_time,
$read_time
);
?>
</span>
</div>
<div class="file-actions">
<a href="#comments" class="btn-sm" data-cn="发表评论" data-en="Post Comment"></a>
</div>
</div>
<div class="gh-file-content markdown-body">
<?php if (has_post_thumbnail()) : ?>
<div class="entry-thumbnail">
<div class="entry-thumbnail-pro">
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
<div class="entry-content">
<?php the_content(); ?>
</div>
<?php if (get_post_type() === 'post') : ?>
<footer class="entry-footer">
<?php
$categories = get_the_category();
if ($categories) :
?>
<div class="entry-categories">
<strong><?php _e('分类:', 'itstudio'); ?></strong>
<?php
foreach ($categories as $category) {
echo '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '</a> ';
}
?>
</div>
<?php endif; ?>
<div class="gh-file-footer">
<?php
$tags = get_the_tags();
if ($tags) :
?>
<div class="entry-tags">
<strong><?php _e('标签:', 'itstudio'); ?></strong>
<?php
foreach ($tags as $tag) {
echo '<a href="' . get_tag_link($tag->term_id) . '">' . $tag->name . '</a> ';
echo '<span class="gh-tag tag-tag">#' . $tag->name . '</span> ';
}
endif;
?>
</div>
<?php endif; ?>
</footer>
<?php endif; ?>
</article>
</div>
</div>
</div>
<!-- 3. 评论区:保持 GitHub Timeline 风格 -->
<div class="gh-pro-comments">
<div class="timeline-header">
<h3 data-cn="文章讨论" data-en="Discussion"></h3>
</div>
<div class="gh-timeline">
<!-- Vertical Line -->
<div class="timeline-line"></div>
<?php
// 直接加载评论模板
if (comments_open() || get_comments_number()) :
comments_template();
endif;
?>
</div>
</div>
<?php endwhile; ?>
</div>
+88 -46
View File
@@ -2,7 +2,7 @@
Theme Name: IT Studio Theme
Theme URI: https://github.com/itstudio-2002/ITStudioMainSite
Description: 中国海洋大学爱特工作室官方网站主题 - A modern WordPress theme for IT Studio of Ocean University of China
Version: 1.0.0
Version: 2.1.0
Author: IT Studio
Author URI: https://it.ouc.edu.cn
License: MIT
@@ -11,75 +11,117 @@ Text Domain: itstudio
Tags: responsive, modern, dark-mode, bilingual
*/
/* =========================================
1. 设计令牌 (Design Tokens) - 全局变量
========================================= */
:root {
--ocean-light-blue: #f0f8ff;
--ocean-deep-blue: #0a1929;
--accent-color: #8e88c7;
--white: #ffffff;
--black: #000000;
--gray-100: #f5f5f5;
--gray-200: #e0e0e0;
--gray-300: #bdbdbd;
--gray-400: #9e9e9e;
--gray-500: #757575;
--gray-600: #616161;
--gray-700: #424242;
--gray-800: #303030;
--gray-900: #212121;
/* --- 调色板: 海洋与极客 --- */
--color-primary: #0969da; /* 核心蓝:用于链接、主按钮 */
--color-primary-light: #58a6ff; /* 亮蓝:用于深色模式主色 */
--color-success: #2dba4e; /* 成功绿:代码风格点缀 */
--color-purple: #8957e5; /* 极客紫:强调色 */
--color-danger: #cf222e; /* 警告红 */
--bg-color: var(--ocean-light-blue);
--text-color: var(--black);
--header-bg: var(--white);
--footer-bg: var(--gray-100);
--border-color: var(--gray-200);
/* --- 主题色: 浅色模式 (Light) --- */
--bg-body: #ffffff; /* 页面背景 */
--bg-surface: #f6f8fa; /* 次级背景 (Sidebar/Footer) */
--bg-card: #ffffff; /* 卡片背景 */
--text-primary: #24292f; /* 主要文字 */
--text-secondary: #343a40; /* 次要文字 */
--border-default: #d0d7de; /* 默认边框 */
--border-muted: #d8dee4; /* 淡边框 */
--transition-speed: 0.3s;
--shadow-sm: 0 1px 3px rgba(140, 149, 159, 0.12);
--shadow-md: 0 4px 12px rgba(140, 149, 159, 0.15);
--shadow-lg: 0 8px 24px rgba(140, 149, 159, 0.2);
/* --- 排版 (Typography) --- */
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", "Menlo", "Consolas", monospace;
/* --- 布局 (Layout) --- */
--header-height: 90px;
--container-width: 1400px;
--radius-sm: 6px;
--radius-md: 8px;
/* --- 动画 (Animation) --- */
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
--duration-fast: 0.2s;
--duration-normal: 0.3s;
}
/* --- 主题色: 深色模式 (Dark) --- */
[data-theme="dark"] {
--bg-color: var(--ocean-deep-blue);
--text-color: var(--white);
--header-bg: #0d1f30;
--footer-bg: #050f1a;
--border-color: var(--gray-700);
--color-primary: #58a6ff; /* 深色模式下蓝色需要更亮 */
--bg-body: #0d1117; /* 深邃蓝黑 (Github Dark) */
--bg-surface: #161b22;
--bg-card: #161b22;
--text-primary: #c9d1d9; /* 灰白 */
--text-secondary: #6d737c; /* 灰 */
--border-default: #30363d;
--border-muted: #21262d;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.8);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
/* =========================================
2. 全局重置 (Reset & Base)
========================================= */
* { box-sizing: border-box; margin: 0; padding: 0; }
html {
min-height: 100vh; /* 确保HTML高度撑满 */
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC', sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-sans);
background-color: var(--bg-body);
color: var(--text-primary);
line-height: 1.6;
transition: background-color var(--transition-speed), color var(--transition-speed);
min-height: 100vh;
transition: background-color var(--duration-normal), color var(--duration-normal);
-webkit-font-smoothing: antialiased;
display: flex;
flex-direction: column;
position: relative;
min-height: 100vh; /* 确保Body高度撑满并使用Flex布局 */
}
a {
color: var(--accent-color);
color: var(--color-primary);
text-decoration: none;
transition: opacity var(--transition-speed);
transition: opacity var(--duration-fast);
}
a:hover { opacity: 0.85; }
a:hover {
opacity: 0.8;
}
ul { list-style: none; }
button { font-family: inherit; }
img { max-width: 100%; height: auto; display: block; }
svg { fill: currentColor; }
/* =========================================
3. 全局工具类 (Global Utilities)
========================================= */
.container {
max-width: 1200px;
max-width: var(--container-width);
margin: 0 auto;
padding: 0 20px;
padding: 0 24px;
width: 100%;
}
@media (max-width: 768px) {
.container {
padding: 0 15px;
/* 双语内容自动填充系统 */
/* 中文模式:填充 data-cn 到伪元素 */
body:not([lang="en"]) [data-cn]:not(.hero-description):not(.gh-state):empty::before {
content: attr(data-cn);
}
/* 英文模式:填充 data-en 到伪元素 */
body[lang="en"] [data-en]:not(.hero-description):not(.gh-state):empty::before {
content: attr(data-en);
}
/* WordPress Admin Bar 兼容性修复 */
body.admin-bar .site-header { top: 32px; }
@media screen and (max-width: 782px) { body.admin-bar .site-header { top: 46px; } }