diff --git a/templates/public/base.html b/templates/public/base.html
index 846dafe..7bb2142 100644
--- a/templates/public/base.html
+++ b/templates/public/base.html
@@ -36,7 +36,7 @@
* forest 墨绿 + 青绿
* dark 深色背景
*/
- :root, [data-theme="default"] {
+ :root, html[data-theme="default"] {
--brand: #16baaa;
--brand-2: #2e8de8;
--bg: #f5f7fa;
@@ -50,7 +50,7 @@
--shadow-hover: 0 8px 24px rgba(22, 186, 170, 0.18);
}
/* 暮色橙(暖色系) */
- [data-theme="sunset"] {
+ html[data-theme="sunset"] {
--brand: #ff7043;
--brand-2: #e91e63;
--bg: #fff8f3;
@@ -64,7 +64,7 @@
--shadow-hover: 0 8px 24px rgba(255,112,67,0.25);
}
/* 森林绿(自然系) */
- [data-theme="forest"] {
+ html[data-theme="forest"] {
--brand: #2e7d32;
--brand-2: #00897b;
--bg: #f3f8f4;
@@ -78,7 +78,7 @@
--shadow-hover: 0 8px 24px rgba(46,125,50,0.22);
}
/* 暗色(深色背景) */
- [data-theme="dark"] {
+ html[data-theme="dark"] {
--brand: #16baaa;
--brand-2: #2e8de8;
--bg: #0f1419;
@@ -92,7 +92,7 @@
--shadow-hover: 0 8px 24px rgba(22, 186, 170, 0.25);
}
/* 紫韵(优雅紫色) */
- [data-theme="lavender"] {
+ html[data-theme="lavender"] {
--brand: #8b5cf6;
--brand-2: #ec4899;
--bg: #faf5ff;
@@ -106,7 +106,7 @@
--shadow-hover: 0 8px 24px rgba(139,92,246,0.25);
}
/* 深海(深蓝 navy) */
- [data-theme="ocean"] {
+ html[data-theme="ocean"] {
--brand: #0ea5e9;
--brand-2: #06b6d4;
--bg: #f0f9ff;
@@ -120,7 +120,7 @@
--shadow-hover: 0 8px 24px rgba(14,165,233,0.28);
}
/* 青空(明亮天蓝) */
- [data-theme="sky"] {
+ html[data-theme="sky"] {
--brand: #38bdf8;
--brand-2: #3b82f6;
--bg: #f0f9ff;
@@ -134,7 +134,7 @@
--shadow-hover: 0 8px 24px rgba(59,130,246,0.28);
}
/* 玫红(热情玫红) */
- [data-theme="rose"] {
+ html[data-theme="rose"] {
--brand: #f43f5e;
--brand-2: #ec4899;
--bg: #fff1f2;
@@ -205,7 +205,38 @@
padding: 56px 0 40px;
position: relative;
}
- .topbar-inner { max-width: 100%; margin: 0 auto; padding: 0 24px; }
+ .topbar-inner {
+ max-width: 100%;
+ margin: 0 auto;
+ padding: 0 24px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 24px;
+ flex-wrap: wrap;
+ }
+ .topbar-brand { flex: 1 1 auto; min-width: 220px; }
+ .topbar-actions {
+ display: flex;
+ align-items: center;
+ gap: 14px;
+ flex: 0 1 auto;
+ justify-content: flex-end;
+ }
+ /* 顶栏右侧主题切换按钮(让原本藏在侧栏的入口在顶栏也可见,填充右侧空白) */
+ .top-theme-trigger { position: relative; }
+ .top-theme-toggle {
+ width: 44px; height: 44px;
+ border-radius: 50%;
+ border: 1px solid rgba(255,255,255,0.4);
+ background: rgba(255,255,255,0.18);
+ color: #fff; font-size: 20px;
+ cursor: pointer;
+ display: flex; align-items: center; justify-content: center;
+ flex-shrink: 0;
+ transition: background .2s;
+ }
+ .top-theme-toggle:hover { background: rgba(255,255,255,0.30); }
.topbar h1 { font-size: 36px; margin: 0 0 8px; font-weight: 600; line-height: 1.2; }
.topbar .sub { font-size: 15px; opacity: 0.92; }
/* 宽屏:标题与内边距同步放大,避免头重脚轻 */
@@ -213,7 +244,7 @@
.topbar { padding: 68px 0 52px; }
.topbar h1 { font-size: 44px; }
.topbar .sub { font-size: 17px; }
- .site-search { max-width: 760px; }
+ .site-search { max-width: 560px; }
/* 卡片描述放宽到 2 行,提升信息密度 */
.card .desc { -webkit-line-clamp: 2; min-height: 40px; }
}
@@ -256,7 +287,9 @@
}
.theme-menu.open { display: block; }
.theme-menu li {
- display: block;
+ display: flex;
+ align-items: center;
+ gap: 8px;
padding: 8px 12px;
font-size: 14px;
border-radius: 6px;
@@ -264,14 +297,39 @@
transition: background 0.12s;
color: var(--text);
}
+ /* 每项都带一枚同规格色块,保证「暗色」这类深底项不会视觉上落单 */
+ .theme-menu li::before {
+ content: '';
+ width: 12px; height: 12px;
+ border-radius: 50%;
+ flex-shrink: 0;
+ background: var(--sw, var(--brand));
+ box-shadow: 0 0 0 1px rgba(0,0,0,0.12) inset;
+ }
+ .theme-menu li[data-theme="default"] { --sw: #16baaa; }
+ .theme-menu li[data-theme="sunset"] { --sw: #ff7043; }
+ .theme-menu li[data-theme="forest"] { --sw: #2e7d32; }
+ .theme-menu li[data-theme="dark"] { --sw: #1a1f29; }
+ .theme-menu li[data-theme="lavender"] { --sw: #8b5cf6; }
+ .theme-menu li[data-theme="ocean"] { --sw: #0ea5e9; }
+ .theme-menu li[data-theme="sky"] { --sw: #38bdf8; }
+ .theme-menu li[data-theme="rose"] { --sw: #f43f5e; }
+ .theme-menu li[data-theme="auto"] { --sw: linear-gradient(135deg, #f5f7fa 50%, #1a1f29 50%); }
.theme-menu li:hover { background: rgba(22,186,170,0.10); }
.theme-menu li.active { background: rgba(22,186,170,0.18); font-weight: 600; }
+ .theme-menu li.active::after {
+ content: '✓';
+ margin-left: auto;
+ color: var(--brand);
+ font-weight: 700;
+ }
/* ===== 顶部全局搜索 ===== */
.site-search {
position: relative;
- max-width: 560px;
- margin-top: 22px;
+ max-width: 460px;
+ flex: 1 1 320px;
+ margin-top: 0;
display: flex;
align-items: center;
background: rgba(255,255,255,0.95);
@@ -433,11 +491,28 @@
top: 20px;
max-height: calc(100vh - 40px);
overflow-y: auto;
- overscroll-behavior: contain;
- padding: 8px 0 20px;
+ /* 不用 contain:contain 会阻断滚动链接,侧栏滚到底(或内容没超出)时
+ 鼠标在侧栏上滚轮会完全没反应,表现为"上下滚动没有呼应"。
+ 保持默认的 auto,滚到底后自然接力给页面滚动。 */
+ overscroll-behavior: auto;
+ /* 预留滚动条位置,出现滚动条时内容不横向抖动 */
+ scrollbar-gutter: stable;
+ scrollbar-width: thin;
+ scrollbar-color: var(--text-soft) transparent;
+ padding: 8px 6px 20px 0;
+ /* 关键:侧栏本身是 sticky,会生成独立层叠上下文。
+ 若不提升层级,内部弹出的主题菜单(z-index:50)会被锁在该上下文里,
+ 而内容区卡片图标带 z-index:1,反而会画到菜单之上。提到 20 即可压过内容区。 */
+ z-index: 20;
}
- .side-nav::-webkit-scrollbar { width: 4px; }
- .side-nav::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
+ /* 滚动条要看得见,否则内容被截断时用户不知道还能往下滚 */
+ .side-nav::-webkit-scrollbar { width: 6px; }
+ .side-nav::-webkit-scrollbar-track { background: transparent; }
+ .side-nav::-webkit-scrollbar-thumb {
+ background: var(--text-soft);
+ border-radius: 3px;
+ }
+ .side-nav::-webkit-scrollbar-thumb:hover { background: var(--brand); }
.side-block {
background: var(--card-bg);
@@ -597,8 +672,12 @@
box-shadow: 0 6px 20px rgba(139, 92, 246, 0.18);
}
.card-mine .visit-count { color: #8b5cf6; }
+
.cat-nav-inner a.cat-nav-mine { color: #8b5cf6; font-weight: 600; }
- .cat-drawer-list a.cat-drawer-mine { color: #8b5cf6; font-weight: 600; }
+ .cat-drawer-list a.cat-drawer-mine,
+ .cat-drawer-list a.cat-drawer-mine .cat-icon { color: #8b5cf6; font-weight: 600; }
+ .cat-drawer-list a.cat-drawer-hot,
+ .cat-drawer-list a.cat-drawer-hot .cat-icon { color: #ff6b35; font-weight: 600; }
.card .icon-wrap {
position: relative;
@@ -647,12 +726,39 @@
-webkit-box-orient: vertical;
min-height: 20px;
}
+ /* 描述与网址共用同一行:默认显示描述,悬停时交叉淡出为网址。
+ 两者用 grid 叠在同一格,卡片高度不再被两行文字撑开。 */
+ .card .meta-line {
+ display: grid;
+ min-height: 20px;
+ margin-top: 2px;
+ }
+ .card .meta-line > .desc,
+ .card .meta-line > .url {
+ grid-area: 1 / 1;
+ min-width: 0;
+ align-self: center;
+ transition: opacity 0.18s ease;
+ }
+ .card .meta-line > .url {
+ opacity: 0;
+ pointer-events: none;
+ }
+ .card:hover .meta-line > .desc,
+ .card:focus-visible .meta-line > .desc { opacity: 0; }
+ .card:hover .meta-line > .url,
+ .card:focus-visible .meta-line > .url { opacity: 1; }
.card .url {
- font-size: 12px; color: var(--text-muted);
+ font-size: 12px; color: var(--brand-2);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
direction: rtl;
text-align: left;
}
+ /* 触屏设备没有 hover,直接展示网址,避免描述永远盖住它 */
+ @media (hover: none) {
+ .card .meta-line > .desc { opacity: 0; }
+ .card .meta-line > .url { opacity: 1; }
+ }
.card .visit-count {
margin-top: auto;
font-size: 11px;
@@ -721,7 +827,7 @@
border-radius: 6px;
overflow-x: auto;
}
- [data-theme="dark"] .about-content pre { background: rgba(255,255,255,0.06); }
+ html[data-theme="dark"] .about-content pre { background: rgba(255,255,255,0.06); }
.about-content blockquote {
border-left: 4px solid var(--brand);
margin: 12px 0;
@@ -819,26 +925,58 @@
@media (max-width: 600px) {
body { font-size: 14px; }
.container { padding: 0 14px; }
- .topbar { padding: 12px 0; }
+ .topbar { padding: 10px 0 12px; }
.topbar-inner {
padding: 0 14px;
display: flex;
align-items: center;
- gap: 10px;
+ gap: 8px;
+ }
+ /* 手机顶栏:第一行 = 分类 + 搜索 + 主题;第二行 = 站点名 + 副标题。
+ 注意 flex 的换行发生在收缩之前,所以 .topbar-actions 必须用
+ flex-basis: 0 + min-width: 0;否则它会先按搜索框的固有宽度(约 280px)
+ 判定"放不下"而整块换行,之后再缩小——表现就是三个控件挤成两行。 */
+ .cat-trigger-mobile {
+ display: inline-flex;
+ width: 38px; height: 38px;
+ font-size: 18px;
+ order: 1;
+ }
+ .topbar-actions { flex: 1 1 0; min-width: 0; order: 2; gap: 8px; }
+ .topbar-brand {
+ display: flex;
+ align-items: baseline;
+ flex-wrap: nowrap;
+ gap: 8px;
+ flex: 1 1 100%;
+ min-width: 0;
+ order: 3;
+ margin-top: 8px;
+ }
+ .topbar h1 {
+ font-size: 17px; margin: 0; line-height: 1.3;
+ white-space: nowrap; flex-shrink: 0;
+ }
+ .topbar .sub {
+ font-size: 12px; opacity: 0.9; line-height: 1.3;
+ min-width: 0;
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
- .topbar-brand { display: none; } /* 手机顶部只保留分类按钮+搜索 */
- .cat-trigger-mobile { display: inline-flex; }
/* 顶部搜索框更紧凑,占满剩余空间 */
.site-search {
- flex: 1;
+ flex: 1 1 auto;
+ min-width: 0;
margin-top: 0;
max-width: none;
- padding: 3px 4px 3px 12px;
+ padding: 2px 2px 2px 12px;
}
- .site-search i { font-size: 16px; margin-right: 8px; }
- .site-search input[type="search"] { font-size: 14px; padding: 8px 0; }
- .site-search .search-btn { padding: 7px 14px; font-size: 13px; }
+ .site-search i { font-size: 16px; margin-right: 8px; cursor: pointer; }
+ .site-search input[type="search"] { font-size: 14px; padding: 8px 0; width: 100%; }
+ /* 手机端靠键盘的「搜索」键或左侧放大镜提交,把横向空间全留给输入框 */
+ .site-search .search-btn { display: none; }
+ .top-theme-trigger { flex-shrink: 0; }
+ .top-theme-toggle { width: 38px; height: 38px; font-size: 17px; }
/* 手机端:横向分类 Tab 隐藏(用抽屉替代) */
.cat-nav { display: none; }
@@ -883,8 +1021,12 @@
.cat-drawer-panel {
left: 0; right: auto; top: 0; bottom: 0;
border-radius: 0 16px 16px 0;
+ /* 必须给显式宽度:只写 max-width 时面板会被内容撑成一条窄条(实测 173px)。 */
+ width: min(280px, 84vw);
+ max-width: none;
max-height: 100vh;
- max-width: 280px;
+ overflow-y: auto;
+ overscroll-behavior: contain;
transform: translateX(-100%);
padding: 20px 16px 28px;
}
@@ -905,6 +1047,20 @@
}
.cat-drawer-list li a .arrow { margin-left: auto; }
+ /* 抽屉宽 280px,主题菜单(min-width 160px)作为 fixed 浮层无论贴左还是贴右
+ 都会被挤出可视区,所以手机端改成在「切换主题」父项下方内联展开。 */
+ .cat-drawer .theme-menu {
+ position: static !important;
+ top: auto !important;
+ left: auto !important;
+ width: auto;
+ min-width: 0;
+ max-width: none;
+ margin: 4px 10px 10px;
+ background: var(--bg);
+ box-shadow: none;
+ }
+
/* 抽屉分区 */
.cat-drawer-section { margin-bottom: 18px; }
.cat-drawer-title {
@@ -935,12 +1091,33 @@
{% block subtitle %}精选优质站点,按分类聚合展示 · 共 {{ total|default(0) }} 个链接{% endblock %}
- {# 全局搜索框(OneNav 风格) #}
-
+
+ {# 全局搜索框(OneNav 风格) #}
+
+
+ {# 顶栏主题切换:把原本藏在侧栏/抽屉的入口放到顶栏右侧,填充空白 #}
+
+
+
+
+
@@ -954,26 +1131,32 @@
{# ===== 左侧分类侧栏:桌面常驻(≥1025px);平板/手机隐藏,改用顶部横条 + 抽屉 ===== #}
- {{ item.description or '暂无描述' }}
- {{ item.url }}
+ {# 描述与网址共用同一行:默认显示描述,悬停时交叉淡出为网址 #}
+
{%- set vc = item.visit_count or 0 -%}
{%- if vc >= 3 -%}访问 {{ '{:,}'.format(vc) }}
diff --git a/templates/public/index.html b/templates/public/index.html
index f8e2de5..604c30f 100644
--- a/templates/public/index.html
+++ b/templates/public/index.html
@@ -23,8 +23,11 @@
{% endif %}
- {{ item.description or '暂无描述' }}
- {{ item.url }}
+ {# 描述与网址共用同一行:默认显示描述,悬停时交叉淡出为网址,避免两行同时占用卡片空间 #}
+
{%- if mine is not none -%}
我点过 {{ item.mine_count or 0 }} 次
@@ -69,7 +72,7 @@
{% for item in my_navs %}