{boardCards.map((card) => (
-
+
{card.dark && (
@@ -240,7 +248,8 @@ const L = {
display: flex;
gap: var(--space-2);
list-style: none;
- margin: var(--space-2) 0 0;
+ /* 光学对齐:.tap 的 44px 热区带左右 padding,整体左移使图标视觉左缘对齐正文列 */
+ margin: var(--space-2) 0 0 -0.55rem;
padding: 0;
}
.pf-socials a { color: var(--ink-3); display: inline-flex; }
@@ -281,7 +290,6 @@ const L = {
padding: 0;
display: grid;
gap: 0.35rem;
- max-width: 32rem;
}
.pf-lang {
display: grid;
@@ -323,9 +331,11 @@ const L = {
letter-spacing: 0.04em;
margin-bottom: var(--space-2);
}
+ /* 自适应列:只有 1 张卡时自动占满整行(避免右半空档),≥2 张时并排;
+ 320px 下限保证车卡内 SVG 不被压到字号过小 */
.pf-board-grid {
display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: var(--space-2);
}
.pf-card {
@@ -339,7 +349,7 @@ const L = {
align-items: center;
gap: 4px;
}
- .pf-card-wide { grid-column: 1 / -1; }
+ .pf-card-wide, .pf-card-solo { grid-column: 1 / -1; }
.pf-card-img { max-width: 100%; height: auto; display: block; }
.pf-card figcaption {
font-size: 11px;
@@ -349,9 +359,12 @@ const L = {
/* 明暗两版自托管 SVG:默认只显示亮色,暗色主题切到暗色版 */
/* 贡献蛇:SVG 内部用自带 CSS 变量(绿阶 + #ebedf0 空格),
无法改写内部配色 →
滤镜归一到站点灰阶;暗色下反相,避免浅灰格子贴在深底上刺眼(想去掉绿→灰只改这一行) */
+ /* streak 卡的环/火苗是写死的品牌蓝:亮色下去色以贴合灰阶数据卡;暗色保留原卡 */
+ .pf-card-streak .pf-card-img { filter: grayscale(1); }
.pf-card-snake .pf-card-img { filter: grayscale(1) contrast(1.03); }
+ /* 暗色蛇:只 invert 会把空格色压得与页面底色接近、矩阵骨架消失 → 叠加 contrast/brightness 找回网格 */
:global([data-theme='dark']) .pf-card-snake .pf-card-img {
- filter: grayscale(1) invert(1) contrast(0.92);
+ filter: grayscale(1) invert(1) contrast(1.18) brightness(1.06);
}
.only-dark { display: none; }
diff --git a/src/components/geek/ProjectWall.astro b/src/components/geek/ProjectWall.astro
index bcc1f38..68afdb2 100644
--- a/src/components/geek/ProjectWall.astro
+++ b/src/components/geek/ProjectWall.astro
@@ -88,8 +88,9 @@ try {
.repo-desc {
font-size: 13px;
color: var(--ink-3);
- /* 居中后长描述限行宽,避免整行摊平散架 */
+ /* 居中后长描述限行宽,避免整行摊平散架;pretty 减少末行孤词 */
max-width: 34em;
+ text-wrap: pretty;
}
.repo-meta { display: flex; gap: var(--space-3); font-size: 12px; color: var(--ink-3); margin-top: 4px; }
.lang { display: inline-flex; align-items: center; gap: 4px; }
diff --git a/src/components/geek/TypingLines.astro b/src/components/geek/TypingLines.astro
index e2af038..a12145c 100644
--- a/src/components/geek/TypingLines.astro
+++ b/src/components/geek/TypingLines.astro
@@ -85,14 +85,17 @@ const first = safe[0] ?? '';
margin: 0 0 var(--space-2);
min-height: 1.6em; /* 固定行高,打字期间不推挤下方内容 */
display: flex;
- align-items: center;
- gap: 1px;
+ /* baseline:光标与末行基线对齐(center 会在两行时把光标拉到中间) */
+ align-items: baseline;
+ gap: 2px;
}
.typing-text { white-space: pre-wrap; }
.typing-caret {
display: inline-block;
- width: 0.5em;
+ width: 2px; /* 细竖条:不参与折行计算 */
height: 1em;
+ align-self: baseline;
+ transform: translateY(0.12em);
background: var(--accent);
animation: caret-blink 1.05s steps(1) infinite;
}
@@ -100,6 +103,10 @@ const first = safe[0] ?? '';
0%, 49% { opacity: 1; }
50%, 100% { opacity: 0; }
}
+ /* 窄屏预留两行高度:长句折行时不再每轮下推再弹回(实测 390 视口曾推挤 ~21px) */
+ @media (max-width: 560px) {
+ .typing { min-height: calc(1.6em * 2); }
+ }
@media (prefers-reduced-motion: reduce) {
.typing-caret { animation: none; opacity: 0.6; }
}