From 0c6b3a68e102d4dcc3d1484bbc84f2d620588383 Mon Sep 17 00:00:00 2001 From: rbetree Date: Sat, 17 Jan 2026 00:59:24 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BE=A7?= =?UTF-8?q?=E8=BE=B9=E6=A0=8F=E5=B8=83=E5=B1=80=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E5=AD=90=E8=8F=9C=E5=8D=95=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: #36 --- assets/style.css | 4105 +++++++++-------- src/runtime/app/routing.js | 153 +- templates/components/navigation.hbs | 2 +- ...-submenu-panel-and-theme-mode.node-test.js | 30 + 4 files changed, 2282 insertions(+), 2008 deletions(-) create mode 100644 test/sidebar-submenu-panel-and-theme-mode.node-test.js diff --git a/assets/style.css b/assets/style.css index 015ef5e..ee4d998 100644 --- a/assets/style.css +++ b/assets/style.css @@ -1,1282 +1,1463 @@ /* 主题颜色变量 */ :root { - /* 深色主题(默认) */ - --bg-color: #1a1b1e; - --sidebar-bg: #2d2e32; - --card-bg-gradient-1: #2f3035; - --card-bg-gradient-2: #2b2c30; - --site-card-bg-gradient-1: #363940; - --site-card-bg-gradient-2: #31343a; - --site-card-hover-bg: linear-gradient(145deg, #3f434b, #353940); - --text-color: #e4e6eb; - --text-muted: #8b8c8f; - --text-bright: #ffffff; - --secondary-bg: #3a3b3f; - --border-color: rgba(255, 255, 255, 0.05); - --shadow-color: rgba(0, 0, 0, 0.15); - --highlight-bg: rgba(118, 148, 185, 0.3); - --scrollbar-color: rgba(255, 255, 255, 0.15); - --scrollbar-hover-color: rgba(255, 255, 255, 0.25); - --accent-color: #7694B9; - --accent-hover: #6684A9; - --accent-rgb: 118, 148, 185; - --nav-item-color: #a1a2a5; - --success-color: #4caf50; - --error-color: #f44336; - --white-color: #ffffff; - --gradient-color: linear-gradient(135deg, #7694B9 0%, #a855f7 50%, #ff6b6b 100%); - --gradient-color-simple: linear-gradient(135deg, #7694B9 0%, #a855f7 100%); - --sidebar-width: 240px; - --sidebar-collapsed-width: 60px; - /* 统一视口高度:由 JS 动态写入(移动端避免 100vh 被浏览器 UI 影响) */ - --app-height: 100vh; + /* 深色主题(默认) */ + --bg-color: #1a1b1e; + --sidebar-bg: #2d2e32; + --card-bg-gradient-1: #2f3035; + --card-bg-gradient-2: #2b2c30; + --site-card-bg-gradient-1: #363940; + --site-card-bg-gradient-2: #31343a; + --site-card-hover-bg: linear-gradient(145deg, #3f434b, #353940); + --text-color: #e4e6eb; + --text-muted: #8b8c8f; + --text-bright: #ffffff; + --secondary-bg: #3a3b3f; + --border-color: rgba(255, 255, 255, 0.05); + --shadow-color: rgba(0, 0, 0, 0.15); + --highlight-bg: rgba(118, 148, 185, 0.3); + --scrollbar-color: rgba(255, 255, 255, 0.15); + --scrollbar-hover-color: rgba(255, 255, 255, 0.25); + --accent-color: #7694b9; + --accent-hover: #6684a9; + --accent-rgb: 118, 148, 185; + --nav-item-color: #a1a2a5; + --success-color: #4caf50; + --error-color: #f44336; + --white-color: #ffffff; + --gradient-color: linear-gradient(135deg, #7694b9 0%, #a855f7 50%, #ff6b6b 100%); + --gradient-color-simple: linear-gradient(135deg, #7694b9 0%, #a855f7 100%); + --sidebar-width: 240px; + --sidebar-collapsed-width: 60px; + /* 统一视口高度:由 JS 动态写入(移动端避免 100vh 被浏览器 UI 影响) */ + --app-height: 100vh; - /* Spacing System */ - --spacing-xs: 0.25rem; - --spacing-sm: 0.5rem; - --spacing-md: 1rem; - --spacing-lg: 1.5rem; - --spacing-xl: 2rem; - --spacing-2xl: 3rem; + /* Spacing System */ + --spacing-xs: 0.25rem; + --spacing-sm: 0.5rem; + --spacing-md: 1rem; + --spacing-lg: 1.5rem; + --spacing-xl: 2rem; + --spacing-2xl: 3rem; - /* 页面内容最大宽度(用于各页边界一致性) */ - --page-max-width: 1300px; + /* 页面内容最大宽度(用于各页边界一致性) */ + --page-max-width: 1300px; - /* Border Radius */ - --radius-sm: 4px; - --radius-md: 8px; - --radius-lg: 12px; - --radius-xl: 16px; - --radius-full: 9999px; + /* Border Radius */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius-full: 9999px; - /* Transitions */ - --transition-fast: 0.2s ease; - --transition-normal: 0.3s ease; - --transition-slow: 0.5s ease; - --transition-bounce: cubic-bezier(0.4, 0, 0.2, 1); + /* Transitions */ + --transition-fast: 0.2s ease; + --transition-normal: 0.3s ease; + --transition-slow: 0.5s ease; + --transition-bounce: cubic-bezier(0.4, 0, 0.2, 1); - /* RGB Values for opacity manipulation */ - --card-bg-rgb: 47, 48, 53; + /* RGB Values for opacity manipulation */ + --card-bg-rgb: 47, 48, 53; } /* 浅色主题:预加载阶段同样应用变量,避免读取默认暗色值 */ html.theme-preload, body.light-theme { - --bg-color: #e0e0d8; - --sidebar-bg: #f0f0eb; - --card-bg-gradient-1: #f0f0eb; - --card-bg-gradient-2: #e9e9e4; - --site-card-bg-gradient-1: #ffffff; - --site-card-bg-gradient-2: #f4f5f0; - --site-card-hover-bg: linear-gradient(145deg, #fafaf8, #eef0eb); - --text-color: #333333; - --text-muted: #666666; - --text-bright: #000000; - --secondary-bg: #d9d9d4; - --border-color: rgba(0, 0, 0, 0.08); - --shadow-color: rgba(0, 0, 0, 0.1); - --highlight-bg: rgba(118, 148, 185, 0.15); - --scrollbar-color: rgba(0, 0, 0, 0.1); - --scrollbar-hover-color: rgba(0, 0, 0, 0.2); - --accent-color: #7694B9; - --accent-hover: #6684A9; - --accent-rgb: 118, 148, 185; - --nav-item-color: #666666; - --success-color: #4caf50; - --error-color: #f44336; - --white-color: #ffffff; - --gradient-color: linear-gradient(135deg, #7694B9 0%, #a855f7 50%, #ff6b6b 100%); - --gradient-color-simple: linear-gradient(135deg, #7694B9 0%, #a855f7 100%); - --card-bg-rgb: 240, 240, 235; + --bg-color: #e0e0d8; + --sidebar-bg: #f0f0eb; + --card-bg-gradient-1: #f0f0eb; + --card-bg-gradient-2: #e9e9e4; + --site-card-bg-gradient-1: #ffffff; + --site-card-bg-gradient-2: #f4f5f0; + --site-card-hover-bg: linear-gradient(145deg, #fafaf8, #eef0eb); + --text-color: #333333; + --text-muted: #666666; + --text-bright: #000000; + --secondary-bg: #d9d9d4; + --border-color: rgba(0, 0, 0, 0.08); + --shadow-color: rgba(0, 0, 0, 0.1); + --highlight-bg: rgba(118, 148, 185, 0.15); + --scrollbar-color: rgba(0, 0, 0, 0.1); + --scrollbar-hover-color: rgba(0, 0, 0, 0.2); + --accent-color: #7694b9; + --accent-hover: #6684a9; + --accent-rgb: 118, 148, 185; + --nav-item-color: #666666; + --success-color: #4caf50; + --error-color: #f44336; + --white-color: #ffffff; + --gradient-color: linear-gradient(135deg, #7694b9 0%, #a855f7 50%, #ff6b6b 100%); + --gradient-color-simple: linear-gradient(135deg, #7694b9 0%, #a855f7 100%); + --card-bg-rgb: 240, 240, 235; } /* 预加载主题 - 在JS完全加载前显示正确的主题 */ html.theme-preload body { - background-color: #e0e0d8; - /* 明亮主题背景色 */ - color: #333333; - /* 明亮主题文本色 */ + background-color: #e0e0d8; + /* 明亮主题背景色 */ + color: #333333; + /* 明亮主题文本色 */ } /* 预加载侧边栏状态 - 在JS完全加载前显示正确的侧边栏宽度 */ html.sidebar-collapsed-preload .sidebar { - width: var(--sidebar-collapsed-width); + width: var(--sidebar-collapsed-width); } html.sidebar-collapsed-preload .content { - margin-left: var(--sidebar-collapsed-width); + margin-left: var(--sidebar-collapsed-width); } /* 控制页面预加载状态 */ html.preload .layout { - opacity: 0; + opacity: 0; } html.preload * { - transition: none !important; + transition: none !important; } /* 可访问性:视觉隐藏但保留屏幕阅读器可读 */ .visually-hidden { - position: absolute !important; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; + position: absolute !important; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } /* 主题切换按钮 */ .theme-toggle { - position: fixed; - bottom: var(--spacing-xl); - right: var(--spacing-xl); - width: 2.5rem; - height: 2.5rem; - border-radius: var(--radius-lg); - background: rgba(var(--card-bg-rgb), 0.65); - border: 1px solid var(--border-color); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - color: var(--text-color); - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all var(--transition-normal); - transition-timing-function: var(--transition-bounce); - z-index: 100; - box-shadow: 0 4px 16px var(--shadow-color); + position: fixed; + bottom: var(--spacing-xl); + right: var(--spacing-xl); + width: 2.5rem; + height: 2.5rem; + border-radius: var(--radius-lg); + background: rgba(var(--card-bg-rgb), 0.65); + border: 1px solid var(--border-color); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + color: var(--text-color); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all var(--transition-normal); + transition-timing-function: var(--transition-bounce); + z-index: 100; + box-shadow: 0 4px 16px var(--shadow-color); } .theme-toggle:hover { - transform: translateY(-2px); - background: rgba(var(--card-bg-rgb), 0.75); - box-shadow: 0 6px 20px var(--shadow-color); - color: var(--accent-color); + transform: translateY(-2px); + background: rgba(var(--card-bg-rgb), 0.75); + box-shadow: 0 6px 20px var(--shadow-color); + color: var(--accent-color); } .theme-toggle:active { - transform: translateY(0); - box-shadow: 0 2px 8px var(--shadow-color); + transform: translateY(0); + box-shadow: 0 2px 8px var(--shadow-color); } /* 全局样式 */ * { - margin: 0; - padding: 0; - box-sizing: border-box; + margin: 0; + padding: 0; + box-sizing: border-box; } /* 通用滚动条样式 */ .custom-scrollbar { - scrollbar-width: thin; - /* Firefox */ - scrollbar-color: var(--scrollbar-color) transparent; - /* Firefox */ + scrollbar-width: thin; + /* Firefox */ + scrollbar-color: var(--scrollbar-color) transparent; + /* Firefox */ } /* Webkit滚动条样式(Chrome, Safari, Edge等) */ .custom-scrollbar::-webkit-scrollbar { - width: 7px; - /* 统一滚动条宽度 */ + width: 7px; + /* 统一滚动条宽度 */ } .custom-scrollbar::-webkit-scrollbar-track { - background: transparent; + background: transparent; } .custom-scrollbar::-webkit-scrollbar-thumb { - background-color: var(--scrollbar-color); - /* 使用变量 */ - border-radius: 4px; + background-color: var(--scrollbar-color); + /* 使用变量 */ + border-radius: 4px; } .custom-scrollbar::-webkit-scrollbar-thumb:hover { - background-color: var(--scrollbar-hover-color); - /* 使用变量 */ + background-color: var(--scrollbar-hover-color); + /* 使用变量 */ } /* 防止滚动条导致的布局偏移 */ html { - overflow-y: hidden; - /* 改为hidden,移除强制显示的滚动条 */ - scrollbar-width: thin; - /* Firefox */ - /* 明确 rem 基准字号:便于用 rem 统一管理字号(1rem = 16px) */ - font-size: 16px; + overflow-y: hidden; + /* 改为hidden,移除强制显示的滚动条 */ + scrollbar-width: thin; + /* Firefox */ + /* 明确 rem 基准字号:便于用 rem 统一管理字号(1rem = 16px) */ + font-size: 16px; } /* 搜索高亮样式 */ .highlight { - background-color: var(--highlight-bg); - border-radius: var(--radius-sm); - padding: 0 2px; - font-weight: bold; - color: var(--text-color); + background-color: var(--highlight-bg); + border-radius: var(--radius-sm); + padding: 0 2px; + font-weight: bold; + color: var(--text-color); } - body { - font-family: var(--font-body, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Helvetica Neue", Arial, sans-serif); - font-weight: var(--font-weight-body, normal); - line-height: 1.6; - background-color: var(--bg-color); - color: var(--text-color); - min-height: var(--app-height, 100vh); - overflow: hidden; - /* 防止body滚动 */ - padding-right: 0 !important; - /* 防止滚动条导致的布局偏移 */ - transition: background-color 0.3s ease, color 0.3s ease; + font-family: var( + --font-body, + system-ui, + -apple-system, + 'Segoe UI', + Roboto, + 'Noto Sans', + 'Helvetica Neue', + Arial, + sans-serif + ); + font-weight: var(--font-weight-body, normal); + line-height: 1.6; + background-color: var(--bg-color); + color: var(--text-color); + min-height: var(--app-height, 100vh); + overflow: hidden; + /* 防止body滚动 */ + padding-right: 0 !important; + /* 防止滚动条导致的布局偏移 */ + transition: + background-color 0.3s ease, + color 0.3s ease; } /* 布局 */ .layout { - display: flex; - min-height: var(--app-height, 100vh); - position: relative; - z-index: 1; - overflow: hidden; - /* 防止layout滚动 */ - opacity: 0; - transition: opacity 0.3s ease; + display: flex; + min-height: var(--app-height, 100vh); + position: relative; + z-index: 1; + overflow: hidden; + /* 防止layout滚动 */ + opacity: 0; + transition: opacity 0.3s ease; } /* 确保加载后立即显示 */ body.loaded .layout { - opacity: 1; + opacity: 1; } /* 移动端基础样式 */ .mobile-buttons { - display: none; - position: fixed; - top: var(--spacing-md); - top: calc(env(safe-area-inset-top) + var(--spacing-md)); - left: 0; - right: 0; - width: 100%; - padding: 0 var(--spacing-md); - padding-left: calc(env(safe-area-inset-left) + var(--spacing-md)); - padding-right: calc(env(safe-area-inset-right) + var(--spacing-md)); - justify-content: space-between; - z-index: 910; - pointer-events: none; + display: none; + position: fixed; + top: var(--spacing-md); + top: calc(env(safe-area-inset-top) + var(--spacing-md)); + left: 0; + right: 0; + width: 100%; + padding: 0 var(--spacing-md); + padding-left: calc(env(safe-area-inset-left) + var(--spacing-md)); + padding-right: calc(env(safe-area-inset-right) + var(--spacing-md)); + justify-content: space-between; + z-index: 910; + pointer-events: none; } .menu-toggle, .search-toggle { - background: var(--sidebar-bg); - border: none; - color: var(--text-color); - width: 2.5rem; - height: 2.5rem; - border-radius: var(--radius-md); - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.25s var(--transition-bounce); - box-shadow: 0 2px 8px var(--shadow-color); - pointer-events: auto; + background: var(--sidebar-bg); + border: none; + color: var(--text-color); + width: 2.5rem; + height: 2.5rem; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.25s var(--transition-bounce); + box-shadow: 0 2px 8px var(--shadow-color); + pointer-events: auto; } .menu-toggle:hover, .search-toggle:hover { - background: var(--secondary-bg); - transform: translateY(-2px); - box-shadow: 0 4px 12px var(--shadow-color); + background: var(--secondary-bg); + transform: translateY(-2px); + box-shadow: 0 4px 12px var(--shadow-color); } .menu-toggle:active, .search-toggle:active { - transform: translateY(0); + transform: translateY(0); } /* 遮罩层 */ .overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - opacity: 0; - visibility: hidden; - transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); - z-index: 950; - /* 调整遮罩层z-index,处于按钮与弹出面板之间 */ + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + opacity: 0; + visibility: hidden; + transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); + z-index: 950; + /* 调整遮罩层z-index,处于按钮与弹出面板之间 */ } .overlay.active { - opacity: 1; - visibility: visible; + opacity: 1; + visibility: visible; } /* 侧边栏样式 */ .sidebar { - width: var(--sidebar-width); - background-color: var(--sidebar-bg); - position: fixed; - top: 0; - left: 0; - bottom: 0; - box-shadow: 2px 0 10px var(--shadow-color); - z-index: 100; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - transform: translateZ(0); - height: var(--app-height, 100vh); - display: grid; - grid-template-rows: auto 1fr auto auto; - grid-template-areas: - "header" - "content" - "social" - "footer"; - scrollbar-width: thin; - scrollbar-color: var(--scrollbar-color) transparent; - overflow-y: hidden; - transition: background-color var(--transition-normal); + width: var(--sidebar-width); + background-color: var(--sidebar-bg); + position: fixed; + top: 0; + left: 0; + bottom: 0; + box-shadow: 2px 0 10px var(--shadow-color); + z-index: 100; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transform: translateZ(0); + height: var(--app-height, 100vh); + display: grid; + grid-template-rows: auto 1fr auto auto; + grid-template-areas: + 'header' + 'content' + 'social' + 'footer'; + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-color) transparent; + overflow-y: hidden; + transition: background-color var(--transition-normal); } /* 侧边栏折叠状态 */ .sidebar.collapsed { - width: var(--sidebar-collapsed-width); - overflow-x: hidden; + width: var(--sidebar-collapsed-width); + overflow-x: hidden; } /* 优化侧边栏折叠时的Logo部分 */ .sidebar.collapsed .logo { - padding: 1.2rem 0.5rem 0.6rem; - justify-content: center; - display: flex; - align-items: center; - height: 3.75rem; - /* 确保与展开状态高度一致 */ - margin-bottom: 0.8rem; - /* 收起态同样拉开与按钮的间距 */ -} - -/* 折叠状态下的侧边栏内容区域调整 */ -.sidebar.collapsed .sidebar-content { - padding: 0; - scrollbar-width: none; - /* 隐藏滚动条 */ + padding: 1.2rem 0.5rem 0.6rem; + justify-content: center; + display: flex; + align-items: center; + height: 3.75rem; + /* 确保与展开状态高度一致 */ + margin-bottom: 0.8rem; + /* 收起态同样拉开与按钮的间距 */ } /* 调整折叠侧边栏的部分元素间距 */ .sidebar.collapsed .nav-section { - gap: 2px; + gap: 2px; } /* 折叠状态下隐藏底部版权区域(不占位) */ .sidebar.collapsed .sidebar-footer { - padding: 0; - height: 0; - min-height: 0; - margin: 0; - overflow: hidden; - border: none; -} - -.sidebar.collapsed .sidebar-content::-webkit-scrollbar { - display: none; - /* 隐藏WebKit浏览器的滚动条 */ + padding: 0; + height: 0; + min-height: 0; + margin: 0; + overflow: hidden; + border: none; } /* 侧边栏头部区域 */ .sidebar .logo { - grid-area: header; - padding: 1.2rem 1.2rem 0.6rem; - /* 调整上下padding更紧凑 */ - display: flex; - align-items: center; - overflow: hidden; - /* 防止内容溢出 */ - position: relative; - /* 添加相对定位,作为按钮的参考 */ - height: 3.75rem; - /* 固定高度 60px */ - margin-bottom: 0.8rem; - /* 与下方按钮区域拉开间距 */ - transition: padding 0.3s ease; - /* 添加padding过渡,避免突变 */ + grid-area: header; + padding: 1.2rem 1.2rem 0.6rem; + /* 调整上下padding更紧凑 */ + display: flex; + align-items: center; + overflow: hidden; + /* 防止内容溢出 */ + position: relative; + /* 添加相对定位,作为按钮的参考 */ + height: 3.75rem; + /* 固定高度 60px */ + margin-bottom: 0.8rem; + /* 与下方按钮区域拉开间距 */ + transition: padding 0.3s ease; + /* 添加padding过渡,避免突变 */ } .logo-brand { - display: flex; - align-items: center; - gap: 0.6rem; - min-width: 0; - flex: 1; - padding-right: 2.2rem; - /* 预留右侧折叠按钮空间 */ + display: flex; + align-items: center; + gap: 0.6rem; + min-width: 0; + flex: 1; + padding-right: 2.2rem; + /* 预留右侧折叠按钮空间 */ } .logo-brand h1 { - padding-left: 0; + padding-left: 0; } .logo-image { - width: 26px; - height: 26px; - flex-shrink: 0; + width: 26px; + height: 26px; + flex-shrink: 0; } .sidebar.collapsed .logo-image { - display: none; + display: none; } .logo h1 { - font-size: 1.4rem; - color: var(--text-bright); - margin-bottom: 0; - padding-left: 0.5rem; - letter-spacing: 0.5px; - transition: opacity 0.3s ease, transform 0.3s ease; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex: 1; + font-size: 1.4rem; + color: var(--text-bright); + margin-bottom: 0; + padding-left: 0.5rem; + letter-spacing: 0.5px; + transition: + opacity 0.3s ease, + transform 0.3s ease; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; } /* 侧边栏折叠按钮 */ .sidebar-toggle { - background: transparent; - border: none; - color: var(--accent-color); - height: 28px; - width: 28px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: background 0.3s ease; - /* 只过渡背景色,移除all避免位置过渡 */ - padding: 0; - flex-shrink: 0; - /* 防止按钮被压缩 */ - position: absolute; - /* 在两种状态下都使用绝对定位 */ - right: 1.2rem; - /* 展开状态下固定在右侧 */ - top: 60%; - transform: translateY(-50%); - /* 垂直居中 */ + background: transparent; + border: none; + color: var(--accent-color); + height: 28px; + width: 28px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.3s ease; + /* 只过渡背景色,移除all避免位置过渡 */ + padding: 0; + flex-shrink: 0; + /* 防止按钮被压缩 */ + position: absolute; + /* 在两种状态下都使用绝对定位 */ + right: 1.2rem; + /* 展开状态下固定在右侧 */ + top: 60%; + transform: translateY(-50%); + /* 垂直居中 */ } .sidebar-toggle .toggle-icon { - font-size: 0.9rem; - transition: transform 0.3s ease; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; + font-size: 0.9rem; + transition: transform 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; } .sidebar-toggle:hover { - background: var(--secondary-bg); + background: var(--secondary-bg); } .sidebar-toggle:active { - background: var(--secondary-bg); + background: var(--secondary-bg); } /* 收起状态下按钮居中 */ .sidebar.collapsed .sidebar-toggle { - left: 50%; - /* 水平居中 */ - right: auto; - /* 移除右侧定位 */ - transform: translate(-50%, -50%); - /* 同时水平和垂直居中 */ + left: 50%; + /* 水平居中 */ + right: auto; + /* 移除右侧定位 */ + transform: translate(-50%, -50%); + /* 同时水平和垂直居中 */ } .sidebar.collapsed .sidebar-toggle:hover { - background: var(--secondary-bg); + background: var(--secondary-bg); } .sidebar.collapsed .sidebar-toggle:active { - background: var(--secondary-bg); + background: var(--secondary-bg); } /* 侧边栏折叠状态下的按钮图标旋转180度 */ .sidebar.collapsed .toggle-icon { - transform: rotate(180deg); + transform: rotate(180deg); } -/* 侧边栏内容区域 - 可滚动 */ +/* 侧边栏内容区域:导航项常驻显示,分类列表在独立面板内滚动 */ .sidebar-content { - grid-area: content; - min-height: 0; - /* 允许在 CSS Grid 内正确收缩与滚动,避免把 footer 挤出可视区域 */ - overflow-y: auto; - /* 只有内容区域可滚动 */ - padding: 0 1.2rem; - display: flex; - flex-direction: column; - gap: 0.6rem; - /* 从1rem减小到0.6rem */ - /* 隐藏滚动条但保持滚动功能 */ - scrollbar-width: none; - /* Firefox */ + grid-area: content; + min-height: 0; + /* 允许在 CSS Grid 内正确收缩与滚动,避免把 footer 挤出可视区域 */ + overflow: hidden; + /* 导航项常驻显示,分类列表在独立面板内滚动 */ + padding: 0 1.2rem; + display: flex; + flex-direction: column; + gap: 0.6rem; + /* 从1rem减小到0.6rem */ } .sidebar-content::-webkit-scrollbar { - display: none; - /* Webkit browsers */ + display: none; + /* Webkit browsers(默认不滚动,保留兼容) */ +} + +/* 展开态:子菜单不在导航项内部展开,改在独立面板展示(避免把“页面列表”挤出首屏) */ +.sidebar:not(.collapsed) .nav-item-wrapper > .submenu { + display: none; +} + +/* 侧边栏:页面分类面板(容器本身可滚动,隐藏滚动条) */ +.sidebar-submenu-panel { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; + padding: 0 0 0.6rem; + /* 移除顶部 padding,避免标题上方出现缝隙 */ + scrollbar-width: none; + /* Firefox 隐藏滚动条 */ +} + +.sidebar-submenu-panel:empty { + display: none; +} + +.sidebar-submenu-panel::-webkit-scrollbar { + display: none; + /* Webkit 浏览器隐藏滚动条 */ +} + +/* 面板内的 submenu 始终可见(不依赖 wrapper.expanded) */ +.sidebar-submenu-panel .submenu { + max-height: none; + overflow: visible; + opacity: 1; + visibility: visible; + margin-left: 0; + transition: none; } /* 折叠状态下的内容区域调整 */ .sidebar.collapsed .sidebar-content { - padding: 0 0.5rem; - scrollbar-width: none; - /* 隐藏滚动条 */ + padding: 0 0.5rem; + overflow-y: auto; + overflow-x: hidden; + scrollbar-width: none; + /* 隐藏滚动条 */ } .sidebar.collapsed .sidebar-content::-webkit-scrollbar { - display: none; - /* 隐藏WebKit浏览器的滚动条 */ + display: none; + /* 隐藏WebKit浏览器的滚动条 */ +} + +.sidebar.collapsed .sidebar-submenu-panel { + display: none; +} + +/* 子菜单标题:默认隐藏(在导航栏内折叠时) */ +.submenu-header { + display: none; + font-size: 0.85rem; + font-weight: 500; + text-transform: uppercase; + color: var(--text-muted); + letter-spacing: 0.5px; + padding: 0.8rem 1rem 0.6rem; + margin-bottom: 0.2rem; + border-bottom: 1px solid var(--border-color); + opacity: 0.8; +} + +/* 当子菜单在面板中显示时:显示标题并固定在顶部 */ +.sidebar-submenu-panel .submenu-header { + display: block; + position: sticky; + top: 0; + margin-top: 0; + margin-bottom: 0.2rem; + /* 覆盖基础样式的 margin-bottom */ + background-color: var(--sidebar-bg); + opacity: 1; + /* 覆盖基础样式的半透明,确保背景完全不透明 */ + z-index: 1; + /* 确保标题在滚动时覆盖下方内容 */ +} + +/* 子菜单项样式优化 */ +.submenu-item { + display: flex; + align-items: center; + gap: 0.8rem; + padding: 0.6rem 1rem; + color: var(--nav-item-color); + text-decoration: none; + border-radius: var(--radius-md); + transition: all var(--transition-normal); + margin-bottom: 2px; + font-size: 0.95rem; + position: relative; + overflow: hidden; +} + +.submenu-item i { + width: 1.4rem; + text-align: center; + font-size: 1rem; + opacity: 0.8; + transition: transform var(--transition-normal); +} + +.submenu-item span { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* 悬浮状态 */ +.submenu-item:hover { + background-color: var(--secondary-bg); + color: var(--text-bright); + padding-left: 1.2rem; /* 悬浮时轻微右移增加动感 */ +} + +.submenu-item:hover i { + transform: scale(1.1); + color: var(--accent-color); + opacity: 1; +} + +/* 激活状态 */ +.submenu-item.active { + background-color: rgba(var(--accent-rgb), 0.15); + color: var(--accent-color); + font-weight: 500; +} + +.submenu-item.active i { + color: var(--accent-color); + opacity: 1; +} + +/* 在激活状态左侧添加指示条 */ +.submenu-item.active::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + height: 60%; + width: 3px; + background-color: var(--accent-color); + border-radius: 0 2px 2px 0; } /* 折叠状态下的Logo文本 */ .sidebar.collapsed .logo h1 { - opacity: 0; - transform: translateX(-20px); - width: 0; - visibility: hidden; - /* 确保完全隐藏,防止干扰布局 */ - pointer-events: none; - /* 禁用交互,避免影响布局 */ + opacity: 0; + transform: translateX(-20px); + width: 0; + visibility: hidden; + /* 确保完全隐藏,防止干扰布局 */ + pointer-events: none; + /* 禁用交互,避免影响布局 */ } /* 导航区域样式 */ .nav-section { - display: flex; - flex-direction: column; - gap: 0.4rem; - /* 增大按钮间距 */ + display: flex; + flex-direction: column; + gap: 0; + /* wrapper 之间不需要 gap,由 nav-item 的 margin 控制 */ + flex: 0 0 auto; + /* 不伸缩,根据内容大小 */ + overflow: visible; + /* 导航项不滚动,保持常驻显示 */ } .section-title { - font-size: 1rem; - color: var(--accent-color); - padding: 0.4rem 0.5rem; - /* 减小上下padding */ - margin-bottom: 0.2rem; - /* 增大与下方按钮组的间距 */ - display: flex; - align-items: center; - gap: 0.5rem; - transition: color 0.3s ease; + font-size: 1rem; + color: var(--accent-color); + padding: 0.4rem 0.5rem; + /* 减小上下padding */ + margin-bottom: 0.2rem; + /* 增大与下方按钮组的间距 */ + display: flex; + align-items: center; + gap: 0.5rem; + transition: color 0.3s ease; } .section-title i { - font-size: 1.2rem; + font-size: 1.2rem; } /* 调整侧边栏折叠状态下的章节标题 */ .sidebar.collapsed .section-title { - justify-content: center; - /* 统一与展开态的垂直间距 */ - padding: 0.4rem 0; - text-align: center; - margin-bottom: 0.2rem; - /* 与展开态保持一致且更大 */ + justify-content: center; + /* 统一与展开态的垂直间距 */ + padding: 0.4rem 0; + text-align: center; + margin-bottom: 0.2rem; + /* 与展开态保持一致且更大 */ } .sidebar.collapsed .section-title i { - margin: 0 auto; - font-size: 1.2rem; + margin: 0 auto; + font-size: 1.2rem; } /* 折叠状态下的导航项布局优化 */ .sidebar.collapsed .nav-section { - gap: 0.4rem; - align-items: center; + gap: 0.4rem; + align-items: center; } .sidebar.collapsed .nav-item { - padding: 0; - justify-content: center; - width: 2.75rem; - /* 增大按钮方块尺寸 44px */ - height: 2.75rem; - /* 增大按钮方块尺寸 44px */ - text-align: center; - margin-left: auto; - margin-right: auto; - border-radius: var(--radius-md); - /* 略增圆角 */ - display: flex; - align-items: center; - box-sizing: border-box; + padding: 0; + justify-content: center; + width: 2.75rem; + /* 增大按钮方块尺寸 44px */ + height: 2.75rem; + /* 增大按钮方块尺寸 44px */ + text-align: center; + margin-left: auto; + margin-right: auto; + border-radius: var(--radius-md); + /* 略增圆角 */ + display: flex; + align-items: center; + box-sizing: border-box; } .sidebar.collapsed .nav-item i { - font-size: 1.25rem; - width: auto; - margin: 0; - padding: 0; + font-size: 1.25rem; + width: auto; + margin: 0; + padding: 0; } .sidebar.collapsed .nav-item .icon-container { - margin: 0; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; + margin: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; } /* 折叠状态下的导航项文本 */ .sidebar.collapsed .nav-item .nav-text, .sidebar.collapsed .nav-item .external-icon { - opacity: 0; - transform: translateX(-10px); - width: 0; - display: none; - /* 完全移除,防止干扰布局 */ - visibility: hidden; + opacity: 0; + transform: translateX(-10px); + width: 0; + display: none; + /* 完全移除,防止干扰布局 */ + visibility: hidden; } .nav-item { - display: flex; - align-items: center; - height: 44px; - padding: 0 0.9rem; - color: var(--nav-item-color); - text-decoration: none; - border-radius: var(--radius-md); - transition: background-color var(--transition-normal), color var(--transition-normal), box-shadow var(--transition-normal); - position: relative; + display: flex; + align-items: center; + height: 44px; + padding: 0 0.9rem; + margin-bottom: 0.4rem; + /* 导航按钮之间的间距 */ + color: var(--nav-item-color); + text-decoration: none; + border-radius: var(--radius-md); + transition: + background-color var(--transition-normal), + color var(--transition-normal), + box-shadow var(--transition-normal); + position: relative; +} + +.nav-item-wrapper:last-child .nav-item { + margin-bottom: 0; + /* 最后一个导航按钮不需要底部间距 */ } .nav-item .icon-container { - width: 24px; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - margin-right: var(--spacing-md); - transition: margin var(--transition-normal); + width: 24px; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + margin-right: var(--spacing-md); + transition: margin var(--transition-normal); } .nav-item .nav-text { - flex: 1; - transition: opacity var(--transition-normal), transform var(--transition-normal); - white-space: nowrap; - overflow: hidden; + flex: 1; + transition: + opacity var(--transition-normal), + transform var(--transition-normal); + white-space: nowrap; + overflow: hidden; } .nav-item .external-icon { - font-size: 0.9rem; - opacity: 0.6; - margin-left: 0.5rem; - transition: all var(--transition-normal); + font-size: 0.9rem; + opacity: 0.6; + margin-left: 0.5rem; + transition: all var(--transition-normal); } .nav-item:hover { - background-color: var(--secondary-bg); - color: var(--text-bright); + background-color: var(--secondary-bg); + color: var(--text-bright); } .nav-item:hover .external-icon { - opacity: 1; - transform: translateX(2px); + opacity: 1; + transform: translateX(2px); } .nav-item.active { - background-color: var(--secondary-bg); - color: var(--text-bright); + background-color: var(--secondary-bg); + color: var(--text-bright); } .nav-item i { - width: 20px; - text-align: center; + width: 20px; + text-align: center; } /* 折叠状态下:底部区域不可见且不可交互 */ .sidebar.collapsed .sidebar-footer { - visibility: hidden; - pointer-events: none; + visibility: hidden; + pointer-events: none; } /* 主内容区域 - 修复滚动条问题 */ .content { - flex: 1; - margin-left: var(--sidebar-width); - padding: 2rem 1.5rem; - background-color: var(--bg-color); - position: relative; - height: var(--app-height, 100vh); - /* 固定高度(移动端避免 100vh 问题) */ - overflow-y: auto; - /* 使用auto替代scroll,只在需要时显示滚动条 */ - overflow-x: hidden; - width: calc(100vw - var(--sidebar-width)); - display: flex; - flex-direction: column; - align-items: center; - /* 防止“有无滚动条”导致内容横向平移(支持的浏览器会稳定预留滚动条槽位) */ - scrollbar-gutter: stable; - /* 自定义滚动条颜色(Firefox) */ - scrollbar-width: thin; - scrollbar-color: var(--scrollbar-color) transparent; + flex: 1; + margin-left: var(--sidebar-width); + padding: 2rem 1.5rem; + background-color: var(--bg-color); + position: relative; + height: var(--app-height, 100vh); + /* 固定高度(移动端避免 100vh 问题) */ + overflow-y: auto; + /* 使用auto替代scroll,只在需要时显示滚动条 */ + overflow-x: hidden; + width: calc(100vw - var(--sidebar-width)); + display: flex; + flex-direction: column; + align-items: center; + /* 防止“有无滚动条”导致内容横向平移(支持的浏览器会稳定预留滚动条槽位) */ + scrollbar-gutter: stable; + /* 自定义滚动条颜色(Firefox) */ + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-color) transparent; } /* 自定义滚动条(Chromium / Safari) */ .content::-webkit-scrollbar { - width: 8px; + width: 8px; } .content::-webkit-scrollbar-track { - background: transparent; + background: transparent; } .content::-webkit-scrollbar-thumb { - background-color: var(--scrollbar-color); - border-radius: var(--radius-full); - /* 用透明边框制造“内边距”,更贴合卡片阴影风格 */ - border: 2px solid transparent; - background-clip: content-box; + background-color: var(--scrollbar-color); + border-radius: var(--radius-full); + /* 用透明边框制造“内边距”,更贴合卡片阴影风格 */ + border: 2px solid transparent; + background-clip: content-box; } .content::-webkit-scrollbar-thumb:hover { - background-color: var(--scrollbar-hover-color); + background-color: var(--scrollbar-hover-color); } /* 回退:不支持 scrollbar-gutter 的浏览器,强制始终显示滚动条以避免横向抖动 */ @supports not (scrollbar-gutter: stable) { - .content { - overflow-y: scroll; - } + .content { + overflow-y: scroll; + } } /* 优化内容区域在侧边栏折叠状态下的边距 */ body .content.expanded { - margin-left: var(--sidebar-collapsed-width); - width: calc(100vw - var(--sidebar-collapsed-width)); + margin-left: var(--sidebar-collapsed-width); + width: calc(100vw - var(--sidebar-collapsed-width)); } /* 仅在交互时启用布局相关过渡,避免首帧闪烁 */ .with-anim .sidebar { - transition: width 0.3s ease, background-color 0.3s ease; + transition: + width 0.3s ease, + background-color 0.3s ease; } .with-anim .content { - transition: background-color 0.3s ease, margin-left 0.3s ease, width 0.3s ease; + transition: + background-color 0.3s ease, + margin-left 0.3s ease, + width 0.3s ease; } /* 搜索框容器 - 固定在顶部 */ .search-container { - width: 100%; - display: flex; - justify-content: center; - padding: 0 2rem; - margin-bottom: 1rem; - position: sticky; - top: 0; - /* 搜索框必须始终位于页面内容之上,避免搜索结果卡片滚动时遮挡 */ - z-index: 200; + width: 100%; + display: flex; + justify-content: center; + padding: 0 2rem; + margin-bottom: 1rem; + position: sticky; + top: 0; + /* 搜索框必须始终位于页面内容之上,避免搜索结果卡片滚动时遮挡 */ + z-index: 200; } /* 分类切换按钮 */ .category-toggle { - position: fixed; - bottom: 5rem; - right: var(--spacing-xl); - width: 2.5rem; - height: 2.5rem; - border-radius: var(--radius-lg); - background: rgba(var(--card-bg-rgb), 0.65); - border: 1px solid var(--border-color); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - color: var(--text-color); - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all var(--transition-normal); - transition-timing-function: var(--transition-bounce); - z-index: 100; - box-shadow: 0 4px 16px var(--shadow-color); + position: fixed; + bottom: 5rem; + right: var(--spacing-xl); + width: 2.5rem; + height: 2.5rem; + border-radius: var(--radius-lg); + background: rgba(var(--card-bg-rgb), 0.65); + border: 1px solid var(--border-color); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + color: var(--text-color); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all var(--transition-normal); + transition-timing-function: var(--transition-bounce); + z-index: 100; + box-shadow: 0 4px 16px var(--shadow-color); } .category-toggle:hover { - transform: translateY(-2px); - background: rgba(var(--card-bg-rgb), 0.75); - box-shadow: 0 6px 20px var(--shadow-color); - color: var(--accent-color); + transform: translateY(-2px); + background: rgba(var(--card-bg-rgb), 0.75); + box-shadow: 0 6px 20px var(--shadow-color); + color: var(--accent-color); } .category-toggle:active { - transform: translateY(0); - box-shadow: 0 2px 8px var(--shadow-color); + transform: translateY(0); + box-shadow: 0 2px 8px var(--shadow-color); } .category-toggle i { - font-size: 18px; + font-size: 18px; } /* 搜索框 */ .search-box { - position: relative; - width: 100%; - max-width: 600px; - display: flex; - align-items: stretch; - --search-status-right: 0.9rem; - --search-hint-right: 1.6rem; - background: rgba(var(--card-bg-rgb), 0.65); - border: 1px solid var(--border-color); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-radius: var(--radius-lg); - box-shadow: 0 4px 16px var(--shadow-color); - transition: background var(--transition-normal), border-color var(--transition-normal), box-shadow var(--transition-normal); + position: relative; + width: 100%; + max-width: 600px; + display: flex; + align-items: stretch; + --search-status-right: 0.9rem; + --search-hint-right: 1.6rem; + background: rgba(var(--card-bg-rgb), 0.65); + border: 1px solid var(--border-color); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-radius: var(--radius-lg); + box-shadow: 0 4px 16px var(--shadow-color); + transition: + background var(--transition-normal), + border-color var(--transition-normal), + box-shadow var(--transition-normal); } .search-box:focus-within { - border-color: rgba(var(--accent-rgb), 0.55); - box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.28), - 0 0 18px rgba(var(--accent-rgb), 0.18), - 0 6px 24px var(--shadow-color); + border-color: rgba(var(--accent-rgb), 0.55); + box-shadow: + 0 0 0 1px rgba(var(--accent-rgb), 0.28), + 0 0 18px rgba(var(--accent-rgb), 0.18), + 0 6px 24px var(--shadow-color); } .search-box::after { - content: ''; - position: absolute; - right: var(--search-status-right); - top: 50%; - transform: translateY(-50%); - width: 6px; - height: 6px; - border-radius: 50%; - opacity: 0; - transition: all var(--transition-normal); - pointer-events: none; + content: ''; + position: absolute; + right: var(--search-status-right); + top: 50%; + transform: translateY(-50%); + width: 6px; + height: 6px; + border-radius: 50%; + opacity: 0; + transition: all var(--transition-normal); + pointer-events: none; } .search-box.has-results::after { - background-color: var(--success-color); - opacity: 1; + background-color: var(--success-color); + opacity: 1; } .search-box.no-results::after { - background-color: var(--error-color); - opacity: 1; + background-color: var(--error-color); + opacity: 1; } .search-box input { - flex: 1; - min-width: 0; - width: 100%; - padding: var(--spacing-md) calc(var(--spacing-lg) + 4.8rem) var(--spacing-md) var(--spacing-md); - border: none; - border-radius: 0 var(--radius-lg) var(--radius-lg) 0; - background-color: transparent; - color: var(--text-color); - font-family: inherit; - font-weight: inherit; - font-size: 1rem; - transition: background-color var(--transition-normal), color var(--transition-normal); - box-shadow: none; + flex: 1; + min-width: 0; + width: 100%; + padding: var(--spacing-md) calc(var(--spacing-lg) + 4.8rem) var(--spacing-md) var(--spacing-md); + border: none; + border-radius: 0 var(--radius-lg) var(--radius-lg) 0; + background-color: transparent; + color: var(--text-color); + font-family: inherit; + font-weight: inherit; + font-size: 1rem; + transition: + background-color var(--transition-normal), + color var(--transition-normal); + box-shadow: none; } .search-box input:focus { - outline: none; - background-color: rgba(var(--card-bg-rgb), 0.25); - box-shadow: none; + outline: none; + background-color: rgba(var(--card-bg-rgb), 0.25); + box-shadow: none; } .search-box input::placeholder { - color: var(--text-muted); - font-family: inherit; - font-weight: inherit; + color: var(--text-muted); + font-family: inherit; + font-weight: inherit; } .search-shortcut-hint { - position: absolute; - top: 50%; - right: var(--search-hint-right); - transform: translateY(-50%); - padding: 0.1rem 0.4rem; - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - background: rgba(var(--card-bg-rgb), 0.25); - font-size: 0.78rem; - line-height: 1.2; - color: var(--text-muted); - opacity: 0.65; - pointer-events: none; - user-select: none; + position: absolute; + top: 50%; + right: var(--search-hint-right); + transform: translateY(-50%); + padding: 0.1rem 0.4rem; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + background: rgba(var(--card-bg-rgb), 0.25); + font-size: 0.78rem; + line-height: 1.2; + color: var(--text-muted); + opacity: 0.65; + pointer-events: none; + user-select: none; } .search-box:focus-within .search-shortcut-hint { - opacity: 0.85; + opacity: 0.85; } /* 搜索引擎前缀按钮(方案B:输入框前缀一体化) */ .search-engine-button { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0 0.75rem; - width: 120px; - flex: 0 0 120px; - border: none; - border-right: 1px solid var(--border-color); - border-radius: var(--radius-lg) 0 0 var(--radius-lg); - background: transparent; - color: var(--text-muted); - cursor: pointer; - font: inherit; - transition: background var(--transition-normal), color var(--transition-normal), transform var(--transition-normal); + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0 0.75rem; + width: 120px; + flex: 0 0 120px; + border: none; + border-right: 1px solid var(--border-color); + border-radius: var(--radius-lg) 0 0 var(--radius-lg); + background: transparent; + color: var(--text-muted); + cursor: pointer; + font: inherit; + transition: + background var(--transition-normal), + color var(--transition-normal), + transform var(--transition-normal); } .search-engine-button:hover { - background: rgba(var(--card-bg-rgb), 0.25); + background: rgba(var(--card-bg-rgb), 0.25); } .search-engine-button:focus-visible { - outline: 2px solid var(--accent-color); - outline-offset: 2px; + outline: 2px solid var(--accent-color); + outline-offset: 2px; } .search-box:focus-within .search-engine-button { - color: var(--accent-color); + color: var(--accent-color); } .search-engine-icon { - display: grid; - place-items: center; - height: 1.2em; - width: 1.2em; - min-width: 1.2em; - font-size: 1.25rem; - line-height: 1; - text-align: center; - flex: 0 0 1.2em; + display: grid; + place-items: center; + height: 1.2em; + width: 1.2em; + min-width: 1.2em; + font-size: 1.25rem; + line-height: 1; + text-align: center; + flex: 0 0 1.2em; } .search-engine-icon.search-engine-icon-svg { - font-size: 1.25rem; + font-size: 1.25rem; } .search-engine-icon.search-engine-icon-svg svg { - width: 100%; - height: 100%; - display: block; + width: 100%; + height: 100%; + display: block; } .search-engine-label { - flex: 1; - min-width: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-size: 0.95rem; + flex: 1; + min-width: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: 0.95rem; } .search-box.dropdown-open .search-engine-button { - background: rgba(var(--card-bg-rgb), 0.25); + background: rgba(var(--card-bg-rgb), 0.25); } /* 搜索引擎下拉菜单 */ .search-engine-dropdown { - position: absolute; - top: calc(100% + 6px); - left: 0; - background: rgba(var(--card-bg-rgb), 0.9); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-radius: var(--radius-md); - box-shadow: 0 4px 15px var(--shadow-color); - display: none; - z-index: 100; - padding: 0.35rem; - border: 1px solid var(--border-color); - min-width: 190px; - flex-direction: column; - gap: 0.25rem; + position: absolute; + top: calc(100% + 6px); + left: 0; + background: rgba(var(--card-bg-rgb), 0.9); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-radius: var(--radius-md); + box-shadow: 0 4px 15px var(--shadow-color); + display: none; + z-index: 100; + padding: 0.35rem; + border: 1px solid var(--border-color); + min-width: 190px; + flex-direction: column; + gap: 0.25rem; } .search-engine-dropdown.active { - display: flex; - animation: fadeIn 0.2s ease-out forwards; + display: flex; + animation: fadeIn 0.2s ease-out forwards; } .search-engine-option { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 0.6rem; - width: 100%; - height: 40px; - padding: 0 0.75rem; - border: none; - border-radius: var(--radius-md); - cursor: pointer; - transition: all 0.2s ease; - background: transparent; - color: var(--text-color); - font: inherit; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 0.6rem; + width: 100%; + height: 40px; + padding: 0 0.75rem; + border: none; + border-radius: var(--radius-md); + cursor: pointer; + transition: all 0.2s ease; + background: transparent; + color: var(--text-color); + font: inherit; } .search-engine-option:hover { - background: rgba(var(--card-bg-rgb), 0.22); + background: rgba(var(--card-bg-rgb), 0.22); } .search-engine-option:focus-visible { - outline: 2px solid var(--accent-color); - outline-offset: 2px; + outline: 2px solid var(--accent-color); + outline-offset: 2px; } .search-engine-option.active { - background-color: var(--secondary-bg); - color: var(--text-bright); + background-color: var(--secondary-bg); + color: var(--text-bright); } .search-engine-option i { - display: grid; - place-items: center; - position: static; - transform: none; - font-size: 1.25rem; - width: 1.35em; - height: 1.35em; - line-height: 1; - text-align: center; - flex: 0 0 1.35em; + display: grid; + place-items: center; + position: static; + transform: none; + font-size: 1.25rem; + width: 1.35em; + height: 1.35em; + line-height: 1; + text-align: center; + flex: 0 0 1.35em; } .search-engine-option i.search-engine-option-svg svg { - width: 100%; - height: 100%; - display: block; + width: 100%; + height: 100%; + display: block; } .search-engine-option-label { - font-size: 0.95rem; + font-size: 0.95rem; } /* 页面容器 */ .page { - position: relative; - width: 100%; - display: none; - flex-direction: column; - align-items: center; - padding-top: 2rem; - padding-left: 0.5rem; - padding-right: 0.5rem; + position: relative; + width: 100%; + display: none; + flex-direction: column; + align-items: center; + padding-top: 2rem; + padding-left: 0.5rem; + padding-right: 0.5rem; } .page.active { - display: flex; + display: flex; } /* 页面模板容器(friends/articles/projects 等): * .page 是 flex 且 align-items:center,如果子元素未显式设置宽度,会触发 shrink-to-fit, * 导致分类/网格布局变窄(只剩单列)。 */ .page-template { - width: 100%; - max-width: var(--page-max-width); - margin: 0 auto; + width: 100%; + max-width: var(--page-max-width); + margin: 0 auto; } /* 欢迎区域 */ .welcome-section { - width: 100%; - max-width: var(--page-max-width); - margin: 0 auto 2.2rem auto; - padding: 0 var(--spacing-lg); - text-align: left; - position: relative; - z-index: 5; - display: flex; - justify-content: space-between; - align-items: flex-end; - flex-wrap: wrap; - gap: var(--spacing-md); + width: 100%; + max-width: var(--page-max-width); + margin: 0 auto 2.2rem auto; + padding: 0 var(--spacing-lg); + text-align: left; + position: relative; + z-index: 5; + display: flex; + justify-content: space-between; + align-items: flex-end; + flex-wrap: wrap; + gap: var(--spacing-md); } .welcome-section-main { - flex: 1; - min-width: 220px; + flex: 1; + min-width: 220px; } .welcome-section-side { - flex: 0 0 auto; + flex: 0 0 auto; } .welcome-section h2 { - font-size: 2.4rem; - color: var(--text-bright); - margin-bottom: 0.5rem; - letter-spacing: 0.5px; - transition: color 0.3s ease; + font-size: 2.4rem; + color: var(--text-bright); + margin-bottom: 0.5rem; + letter-spacing: 0.5px; + transition: color 0.3s ease; } .welcome-section h3 { - font-family: var(--font-body, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Helvetica Neue", Arial, sans-serif); - font-weight: 500; - font-size: 2rem; - margin-bottom: 1rem; - letter-spacing: 0.3px; - background: var(--gradient-color); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - position: relative; - display: inline-block; - text-shadow: 0 0 20px rgba(118, 148, 185, 0.1); - animation: glow 2s ease-in-out infinite alternate; + font-family: var( + --font-body, + system-ui, + -apple-system, + 'Segoe UI', + Roboto, + 'Noto Sans', + 'Helvetica Neue', + Arial, + sans-serif + ); + font-weight: 500; + font-size: 2rem; + margin-bottom: 1rem; + letter-spacing: 0.3px; + background: var(--gradient-color); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + position: relative; + display: inline-block; + text-shadow: 0 0 20px rgba(118, 148, 185, 0.1); + animation: glow 2s ease-in-out infinite alternate; } .welcome-section h3::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: inherit; - filter: blur(20px); - opacity: 0.3; - z-index: -1; + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: inherit; + filter: blur(20px); + opacity: 0.3; + z-index: -1; } .welcome-section .subtitle { - color: var(--text-muted); - font-size: 1.1rem; - line-height: 1.5; - transition: color 0.3s ease; + color: var(--text-muted); + font-size: 1.1rem; + line-height: 1.5; + transition: color 0.3s ease; } /* bookmarks:标题后追加“更新时间”小字(灰色、只读展示) */ .welcome-title-row { - display: flex; - align-items: baseline; - flex-wrap: wrap; - gap: 0.6rem; - margin-bottom: 0.5rem; + display: flex; + align-items: baseline; + flex-wrap: wrap; + gap: 0.6rem; + margin-bottom: 0.5rem; } .welcome-title-row h2 { - margin: 0; + margin: 0; } .page-updated-inline { - color: var(--text-muted); - font-size: 0.9rem; - opacity: 0.85; - white-space: nowrap; + color: var(--text-muted); + font-size: 0.9rem; + opacity: 0.85; + white-space: nowrap; } @keyframes glow { - from { - filter: drop-shadow(0 0 2px rgba(118, 148, 185, 0.2)) drop-shadow(0 0 4px rgba(168, 85, 247, 0.2)); - } + from { + filter: drop-shadow(0 0 2px rgba(118, 148, 185, 0.2)) + drop-shadow(0 0 4px rgba(168, 85, 247, 0.2)); + } - to { - filter: drop-shadow(0 0 4px rgba(118, 148, 185, 0.4)) drop-shadow(0 0 8px rgba(168, 85, 247, 0.4)); - } + to { + filter: drop-shadow(0 0 4px rgba(118, 148, 185, 0.4)) + drop-shadow(0 0 8px rgba(168, 85, 247, 0.4)); + } } /* 分类样式 */ .category { - background: linear-gradient(145deg, var(--card-bg-gradient-1), var(--card-bg-gradient-2)); - border-radius: var(--radius-xl); - padding: var(--spacing-lg); - margin: 0 auto var(--spacing-lg) auto; - width: 100%; - max-width: var(--page-max-width); - position: relative; - z-index: 1; - opacity: 1; - box-shadow: 0 4px 20px var(--shadow-color); - border: 1px solid var(--border-color); - transition: background var(--transition-normal), box-shadow var(--transition-normal); + background: linear-gradient(145deg, var(--card-bg-gradient-1), var(--card-bg-gradient-2)); + border-radius: var(--radius-xl); + padding: var(--spacing-lg); + margin: 0 auto var(--spacing-lg) auto; + width: 100%; + max-width: var(--page-max-width); + position: relative; + z-index: 1; + opacity: 1; + box-shadow: 0 4px 20px var(--shadow-color); + border: 1px solid var(--border-color); + transition: + background var(--transition-normal), + box-shadow var(--transition-normal); } /* 分类标题容器 */ .category-header { - border-radius: var(--radius-md); - padding: 0.5rem; - margin: -0.5rem -0.5rem 1rem -0.5rem; - transition: all var(--transition-normal); + border-radius: var(--radius-md); + padding: 0.5rem; + margin: -0.5rem -0.5rem 1rem -0.5rem; + transition: all var(--transition-normal); } /* 标题前图标固定宽度:避免不同图标宽度导致标题文本不对齐 */ -.category-header [data-editable="category-name"]>i, -.group-header [data-editable="group-name"]>i { - width: 1.25em; - min-width: 1.25em; - text-align: center; - flex: 0 0 1.25em; +.category-header [data-editable='category-name'] > i, +.group-header [data-editable='group-name'] > i { + width: 1.25em; + min-width: 1.25em; + text-align: center; + flex: 0 0 1.25em; } /* 分组标题容器:与分类保持一致的悬浮动效基础 */ .group-header { - border-radius: var(--radius-md); - transition: all var(--transition-normal); + border-radius: var(--radius-md); + transition: all var(--transition-normal); } /* 仅可折叠的标题显示交互态 */ -.category-header[data-toggle="category"], -.group-header[data-toggle="group"] { - cursor: pointer; - user-select: none; +.category-header[data-toggle='category'], +.group-header[data-toggle='group'] { + cursor: pointer; + user-select: none; } -.category-header[data-toggle="category"]:hover { - transform: translateY(-2px); - background: linear-gradient(145deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0.01)); +.category-header[data-toggle='category']:hover { + transform: translateY(-2px); + background: linear-gradient(145deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0.01)); } -.group-header[data-toggle="group"]:hover { - transform: translateY(-2px); - background: linear-gradient(145deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0.01)); +.group-header[data-toggle='group']:hover { + transform: translateY(-2px); + background: linear-gradient(145deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0.01)); } -.category-header[data-toggle="category"]:active { - transform: translateY(0); +.category-header[data-toggle='category']:active { + transform: translateY(0); } -.group-header[data-toggle="group"]:active { - transform: translateY(0); +.group-header[data-toggle='group']:active { + transform: translateY(0); } .category h2 { - font-size: 1.2rem; - margin-bottom: 0; - color: var(--text-bright); - display: flex; - align-items: center; - gap: 0.8rem; - letter-spacing: 0.3px; - transition: color 0.3s ease; + font-size: 1.2rem; + margin-bottom: 0; + color: var(--text-bright); + display: flex; + align-items: center; + gap: 0.8rem; + letter-spacing: 0.3px; + transition: color 0.3s ease; } -.category h2>i { - color: var(--accent-color); - font-size: 1.3rem; - transition: all 0.3s ease; +.category h2 > i { + color: var(--accent-color); + font-size: 1.3rem; + transition: all 0.3s ease; } -.category-header[data-toggle="category"]:hover h2>i { - transform: scale(1.1); - color: var(--accent-hover); +.category-header[data-toggle='category']:hover h2 > i { + transform: scale(1.1); + color: var(--accent-hover); } /* 多层级嵌套样式 - 扁平化设计 */ @@ -1287,254 +1468,256 @@ body .content.expanded { .category-level-4, .group-level-3, .group-level-4 { - background: none; - border: none; - box-shadow: none; - padding: 0; - width: 100%; - margin: 0; + background: none; + border: none; + box-shadow: none; + padding: 0; + width: 100%; + margin: 0; } /* 层级2: 子分类 */ .category-level-2 { - margin-top: 0; - margin-bottom: 0; - padding-left: 0.5rem; - border-left: none; + margin-top: 0; + margin-bottom: 0; + padding-left: 0.5rem; + border-left: none; } /* 层级2: 标题样式 */ .category-level-2 .category-header { - margin: 0 -0.5rem 1rem -0.5rem; - padding: 0.5rem; - background: none; - border-radius: var(--radius-md); + margin: 0 -0.5rem 1rem -0.5rem; + padding: 0.5rem; + background: none; + border-radius: var(--radius-md); } .category-level-2 .category-header h3 { - font-size: 1.1rem; - font-weight: 600; - color: var(--text-bright); - display: flex; - align-items: center; - gap: 0.8rem; + font-size: 1.1rem; + font-weight: 600; + color: var(--text-bright); + display: flex; + align-items: center; + gap: 0.8rem; } -.category-level-2 .category-header h3>i { - color: var(--accent-color); - font-size: 1.2rem; - opacity: 0.9; +.category-level-2 .category-header h3 > i { + color: var(--accent-color); + font-size: 1.2rem; + opacity: 0.9; } /* 层级3: 分组 */ .group-level-3, .category-level-3 { - margin-top: 0; - margin-bottom: 0; - padding-left: 0.5rem; + margin-top: 0; + margin-bottom: 0; + padding-left: 0.5rem; } /* 层级3: 标题样式 */ .group-level-3 .group-header, .category-level-3 .category-header { - margin: 0 0 0.8rem 0; - padding: 0.3rem 0; - background: none; + margin: 0 0 0.8rem 0; + padding: 0.3rem 0; + background: none; } .group-level-3 .group-header h4, .category-level-3 .category-header h4 { - font-size: 1rem; - font-weight: 500; - color: var(--text-color); - display: flex; - align-items: center; - gap: 0.6rem; + font-size: 1rem; + font-weight: 500; + color: var(--text-color); + display: flex; + align-items: center; + gap: 0.6rem; } .group-level-3 .group-header h4 i, .category-level-3 .category-header h4 i { - color: var(--text-muted); - font-size: 1rem; + color: var(--text-muted); + font-size: 1rem; } /* 层级4: 子分组 */ .group-level-4, .category-level-4 { - margin-top: 0; - margin-bottom: 0; - padding-left: 0.5rem; + margin-top: 0; + margin-bottom: 0; + padding-left: 0.5rem; } /* 嵌套层级间距:仅在同级相邻时增加间距,避免首项被额外下推 */ -.subcategories-container>.category-level-2+.category-level-2 { - margin-top: 1rem; +.subcategories-container > .category-level-2 + .category-level-2 { + margin-top: 1rem; } -.groups-container>.group-level-3+.group-level-3, -.groups-container>.category-level-3+.category-level-3 { - margin-top: 0.8rem; +.groups-container > .group-level-3 + .group-level-3, +.groups-container > .category-level-3 + .category-level-3 { + margin-top: 0.8rem; } -.subgroups-container>.group-level-4+.group-level-4, -.subcategories-container>.category-level-4+.category-level-4 { - margin-top: 0.6rem; +.subgroups-container > .group-level-4 + .group-level-4, +.subcategories-container > .category-level-4 + .category-level-4 { + margin-top: 0.6rem; } /* 层级4: 标题样式 */ .group-level-4 .group-header, .category-level-4 .category-header { - margin: 0 0 0.6rem 0; - padding: 0.2rem 0; - background: none; + margin: 0 0 0.6rem 0; + padding: 0.2rem 0; + background: none; } .group-level-4 .group-header h5, .category-level-4 .category-header h5 { - font-size: 0.9rem; - font-weight: 500; - color: var(--text-muted); - display: flex; - align-items: center; - gap: 0.5rem; + font-size: 0.9rem; + font-weight: 500; + color: var(--text-muted); + display: flex; + align-items: center; + gap: 0.5rem; } .group-level-4 .group-header h5 i, .category-level-4 .category-header h5 i { - font-size: 0.9rem; - opacity: 0.7; + font-size: 0.9rem; + opacity: 0.7; } /* 移除悬停时的缩放效果,保持简洁 */ -.category-level-2 .category-header:hover h3>i, +.category-level-2 .category-header:hover h3 > i, .group-level-3 .group-header:hover h4 i, .category-level-3 .category-header:hover h4 i, .group-level-4 .group-header:hover h5 i, .category-level-4 .category-header:hover h5 i { - transform: none; + transform: none; } /* 切换图标样式 */ .category-header .toggle-icon, .group-header .toggle-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 20px; - height: 20px; - margin-left: auto; - color: var(--text-muted); - font-size: 0.9rem; + display: inline-flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + margin-left: auto; + color: var(--text-muted); + font-size: 0.9rem; } .category-header .toggle-icon i, .group-header .toggle-icon i { - transition: transform 0.3s ease, color 0.3s ease; - transform: rotate(0deg); + transition: + transform 0.3s ease, + color 0.3s ease; + transform: rotate(0deg); } /* 展开态:图标旋转 180°(类似参考样式1) */ -.category:not(.collapsed)>.category-header .toggle-icon i, -.group:not(.collapsed)>.group-header .toggle-icon i { - transform: rotate(180deg); - color: var(--text-bright); +.category:not(.collapsed) > .category-header .toggle-icon i, +.group:not(.collapsed) > .group-header .toggle-icon i { + transform: rotate(180deg); + color: var(--text-bright); } -.category-header[data-toggle="category"]:hover .toggle-icon i, -.group-header[data-toggle="group"]:hover .toggle-icon i { - color: var(--accent-color); +.category-header[data-toggle='category']:hover .toggle-icon i, +.group-header[data-toggle='group']:hover .toggle-icon i { + color: var(--accent-color); } /* 分类/分组折叠图标:桌面端默认隐藏,悬停/收起时显示,避免按钮过多 */ @media (hover: hover) and (pointer: fine) { + .category-header .toggle-icon, + .group-header .toggle-icon { + opacity: 0; + transition: opacity 0.2s ease; + } - .category-header .toggle-icon, - .group-header .toggle-icon { - opacity: 0; - transition: opacity 0.2s ease; - } - - .category-header[data-toggle="category"]:hover .toggle-icon, - .category.collapsed>.category-header .toggle-icon, - .group-header[data-toggle="group"]:hover .toggle-icon, - .group.collapsed>.group-header .toggle-icon { - opacity: 1; - } + .category-header[data-toggle='category']:hover .toggle-icon, + .category.collapsed > .category-header .toggle-icon, + .group-header[data-toggle='group']:hover .toggle-icon, + .group.collapsed > .group-header .toggle-icon { + opacity: 1; + } } /* 展开/折叠动画 */ .category-content, .group-content { - overflow: visible; - transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), - opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); - max-height: 5000px; - opacity: 1; + overflow: visible; + transition: + max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), + opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); + max-height: 5000px; + opacity: 1; } .category.collapsed .category-content, .group.collapsed .group-content { - overflow: hidden; - max-height: 0; - opacity: 0; - margin-top: 0; + overflow: hidden; + max-height: 0; + opacity: 0; + margin-top: 0; } /* 收起状态下调整header的下边距 */ -.category.collapsed>.category-header { - margin-bottom: -0.5rem; +.category.collapsed > .category-header { + margin-bottom: -0.5rem; } -.category-level-2.collapsed>.category-header { - margin-bottom: 0; - border-bottom: none; +.category-level-2.collapsed > .category-header { + margin-bottom: 0; + border-bottom: none; } -.group-level-3.collapsed>.group-header, -.category-level-3.collapsed>.category-header { - margin-bottom: 0; +.group-level-3.collapsed > .group-header, +.category-level-3.collapsed > .category-header { + margin-bottom: 0; } -.group-level-4.collapsed>.group-header, -.category-level-4.collapsed>.category-header { - margin-bottom: 0; +.group-level-4.collapsed > .group-header, +.category-level-4.collapsed > .category-header { + margin-bottom: 0; } /* 收起态默认向下,无需额外旋转(保持 0deg) */ /* 空内容提示 */ .empty-content { - color: var(--text-muted); - font-style: italic; - text-align: center; - padding: 1rem; - font-size: 0.9rem; + color: var(--text-muted); + font-style: italic; + text-align: center; + padding: 1rem; + font-size: 0.9rem; } /* 子容器样式 */ .subcategories-container, .groups-container { - width: 100%; + width: 100%; } /* 当分类同时包含子分类和站点时的样式优化 */ -.category-content .subcategories-container+.sites-grid { - margin-top: 1.2rem; - padding-top: 1rem; - border-top: 1px solid var(--border-color); +.category-content .subcategories-container + .sites-grid { + margin-top: 1.2rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color); } /* 当分类同时包含分组和站点时的样式优化 */ -.category-content .groups-container+.sites-grid { - margin-top: 1.2rem; - padding-top: 1rem; - border-top: 1px solid var(--border-color); +.category-content .groups-container + .sites-grid { + margin-top: 1.2rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color); } /* 子分类容器底部间距调整 */ .category-content .subcategories-container:not(:last-child), .category-content .groups-container:not(:last-child) { - margin-bottom: 0.6rem; + margin-bottom: 0.6rem; } /* 确保嵌套的网站网格正确显示 */ @@ -1543,1545 +1726,1553 @@ body .content.expanded { .category-level-3 .sites-grid, .group-level-4 .sites-grid, .category-level-4 .sites-grid { - margin-top: 0; - gap: var(--spacing-md); - /* 保持与顶层一致的网格布局 */ - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + margin-top: 0; + gap: var(--spacing-md); + /* 保持与顶层一致的网格布局 */ + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } /* 响应式设计 - 嵌套结构 */ @media (max-width: 768px) { - .category-level-2 { - padding-left: 0; - } + .category-level-2 { + padding-left: 0; + } - .group-level-3, - .category-level-3 { - padding-left: 0; - } + .group-level-3, + .category-level-3 { + padding-left: 0; + } - .group-level-4, - .category-level-4 { - padding-left: 0; - } + .group-level-4, + .category-level-4 { + padding-left: 0; + } - .subcategories-container>.category-level-2+.category-level-2 { - margin-top: 0.8rem; - } + .subcategories-container > .category-level-2 + .category-level-2 { + margin-top: 0.8rem; + } - .groups-container>.group-level-3+.group-level-3, - .groups-container>.category-level-3+.category-level-3 { - margin-top: 0.7rem; - } + .groups-container > .group-level-3 + .group-level-3, + .groups-container > .category-level-3 + .category-level-3 { + margin-top: 0.7rem; + } - .subgroups-container>.group-level-4+.group-level-4, - .subcategories-container>.category-level-4+.category-level-4 { - margin-top: 0.55rem; - } + .subgroups-container > .group-level-4 + .group-level-4, + .subcategories-container > .category-level-4 + .category-level-4 { + margin-top: 0.55rem; + } - .category-level-2 .sites-grid, - .group-level-3 .sites-grid, - .category-level-3 .sites-grid, - .group-level-4 .sites-grid, - .category-level-4 .sites-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: var(--spacing-sm); - } + .category-level-2 .sites-grid, + .group-level-3 .sites-grid, + .category-level-3 .sites-grid, + .group-level-4 .sites-grid, + .category-level-4 .sites-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--spacing-sm); + } } @media (max-width: 480px) { - .category { - margin-left: 0.5rem; - margin-right: 0.5rem; - padding: 1rem; - } + .category { + margin-left: 0.5rem; + margin-right: 0.5rem; + padding: 1rem; + } - .category-level-2, - .group-level-3, - .category-level-3 { - margin-left: 0; - padding-left: 0; - width: 100%; - } + .category-level-2, + .group-level-3, + .category-level-3 { + margin-left: 0; + padding-left: 0; + width: 100%; + } - .group-level-4, - .category-level-4 { - margin-left: 0; - padding-left: 0; - width: 100%; - } + .group-level-4, + .category-level-4 { + margin-left: 0; + padding-left: 0; + width: 100%; + } - .category-level-2 .sites-grid, - .group-level-3 .sites-grid, - .category-level-3 .sites-grid, - .group-level-4 .sites-grid, - .category-level-4 .sites-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 0.5rem; - } + .category-level-2 .sites-grid, + .group-level-3 .sites-grid, + .category-level-3 .sites-grid, + .group-level-4 .sites-grid, + .category-level-4 .sites-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.5rem; + } } /* 网站卡片网格 */ .sites-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - gap: var(--spacing-md); - position: relative; - z-index: 1; - width: 100%; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: var(--spacing-md); + position: relative; + z-index: 1; + width: 100%; } /* projects:GitHub 热力图(标题区右侧,可选) */ .page-template-projects .heatmap-container { - flex-shrink: 0; - opacity: 0.85; - transition: opacity 0.3s ease; + flex-shrink: 0; + opacity: 0.85; + transition: opacity 0.3s ease; } .page-template-projects .heatmap-container:hover { - opacity: 1; + opacity: 1; } .page-template-projects .heatmap-img { - display: block; - max-width: 100%; - height: auto; + display: block; + max-width: 100%; + height: auto; } .page-template-projects .sites-grid { - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 24px; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 24px; } /* projects:代码仓库风卡片 */ .site-card.site-card-repo { - position: relative; - display: flex; - flex-direction: column; - align-items: stretch; - padding: 1.1rem 1.1rem 1rem; - gap: 0; + position: relative; + display: flex; + flex-direction: column; + align-items: stretch; + padding: 1.1rem 1.1rem 1rem; + gap: 0; } .site-card.site-card-repo:hover { - transform: translateY(-4px); + transform: translateY(-4px); } .site-card.site-card-repo .repo-header { - display: flex; - align-items: center; - gap: 0.75rem; - margin-bottom: 12px; - min-width: 0; + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 12px; + min-width: 0; } .site-card.site-card-repo .repo-icon { - font-size: 1.15rem; - color: var(--nav-item-color); - opacity: 0.85; - transition: color 0.3s ease, opacity 0.3s ease; - flex: 0 0 auto; + font-size: 1.15rem; + color: var(--nav-item-color); + opacity: 0.85; + transition: + color 0.3s ease, + opacity 0.3s ease; + flex: 0 0 auto; } .site-card.site-card-repo:hover .repo-icon { - color: var(--accent-color); - opacity: 1; + color: var(--accent-color); + opacity: 1; } .site-card.site-card-repo .repo-title { - font-size: 1rem; - font-weight: 600; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + font-size: 1rem; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .site-card.site-card-repo .repo-desc { - font-size: 0.9rem; - color: var(--nav-item-color); - opacity: 0.85; - line-height: 1.5; - flex-grow: 1; - margin: 0 0 16px 0; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; - position: relative; - /* Ensure tooltip positioning context */ + font-size: 0.9rem; + color: var(--nav-item-color); + opacity: 0.85; + line-height: 1.5; + flex-grow: 1; + margin: 0 0 16px 0; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + position: relative; + /* Ensure tooltip positioning context */ } .site-card.site-card-repo .repo-stats { - display: flex; - align-items: center; - gap: 16px; - padding-top: 12px; - border-top: 1px solid rgba(255, 255, 255, 0.06); - font-size: 0.8rem; - color: var(--nav-item-color); - opacity: 0.85; + display: flex; + align-items: center; + gap: 16px; + padding-top: 12px; + border-top: 1px solid rgba(255, 255, 255, 0.06); + font-size: 0.8rem; + color: var(--nav-item-color); + opacity: 0.85; } .site-card.site-card-repo .stat-item { - display: flex; - align-items: center; - gap: 6px; - min-width: 0; + display: flex; + align-items: center; + gap: 6px; + min-width: 0; } .site-card.site-card-repo .lang-dot { - width: 10px; - height: 10px; - border-radius: 50%; - display: inline-block; + width: 10px; + height: 10px; + border-radius: 50%; + display: inline-block; } @media (max-width: 600px) { - .welcome-section-with-side { - align-items: flex-start; - } + .welcome-section-with-side { + align-items: flex-start; + } - .welcome-section-with-side .welcome-section-side { - width: 100%; - } + .welcome-section-with-side .welcome-section-side { + width: 100%; + } - .page-template-projects .heatmap-container { - width: 100%; - overflow: hidden; - } + .page-template-projects .heatmap-container { + width: 100%; + overflow: hidden; + } - .page-template-projects .heatmap-img { - /* 移动端优先保证“缩小后完整显示” */ - width: 100%; - max-width: 100%; - } + .page-template-projects .heatmap-img { + /* 移动端优先保证“缩小后完整显示” */ + width: 100%; + max-width: 100%; + } } /* 网站卡片样式 */ .site-card { - background: linear-gradient(145deg, var(--site-card-bg-gradient-1), var(--site-card-bg-gradient-2)); - border-radius: var(--radius-lg); - padding: 0.85rem 1rem; - text-decoration: none; - color: inherit; - transition: background var(--transition-normal), transform var(--transition-normal), box-shadow var(--transition-normal), border-color var(--transition-normal); - display: flex; - align-items: center; - gap: 0.75rem; - text-align: left; - backface-visibility: hidden; - transform: translateZ(0); - will-change: transform; - max-width: 100%; - position: relative; - box-shadow: 0 4px 16px var(--shadow-color); - border: 1px solid var(--border-color); - z-index: 2; - overflow: hidden; + background: linear-gradient( + 145deg, + var(--site-card-bg-gradient-1), + var(--site-card-bg-gradient-2) + ); + border-radius: var(--radius-lg); + padding: 0.85rem 1rem; + text-decoration: none; + color: inherit; + transition: + background var(--transition-normal), + transform var(--transition-normal), + box-shadow var(--transition-normal), + border-color var(--transition-normal); + display: flex; + align-items: center; + gap: 0.75rem; + text-align: left; + backface-visibility: hidden; + transform: translateZ(0); + will-change: transform; + max-width: 100%; + position: relative; + box-shadow: 0 4px 16px var(--shadow-color); + border: 1px solid var(--border-color); + z-index: 2; + overflow: hidden; } /* 网站卡片变体:projects 大卡片 */ .site-card.site-card-large { - padding: 1.1rem 1.2rem; - gap: 0.9rem; + padding: 1.1rem 1.2rem; + gap: 0.9rem; } .site-card.site-card-large .site-card-icon { - width: 3.1rem; - height: 3.1rem; + width: 3.1rem; + height: 3.1rem; } .site-card.site-card-large h3 { - font-size: 1rem; - font-weight: 600; + font-size: 1rem; + font-weight: 600; } .site-card.site-card-large p { - font-size: 0.9rem; + font-size: 0.9rem; } /* Phase 2:articles 页面隐藏“扩展写回结构”,避免与文章条目渲染混淆 */ .menav-extension-shadow { - display: none; + display: none; } /* articles:文章元信息(日期 + 来源) */ -.site-card[data-type="article"] .site-card-meta { - margin: 0 0 8px 0; - font-size: 0.75rem; - color: var(--nav-item-color); - opacity: 0.9; - display: flex; - align-items: center; - gap: 0.4rem; +.site-card[data-type='article'] .site-card-meta { + margin: 0 0 8px 0; + font-size: 0.75rem; + color: var(--nav-item-color); + opacity: 0.9; + display: flex; + align-items: center; + gap: 0.4rem; } -.site-card[data-type="article"] .site-card-meta-sep { - opacity: 0.8; +.site-card[data-type='article'] .site-card-meta-sep { + opacity: 0.8; } /* articles:文章卡片布局(首行:图标+标题;下方:时间/来源 + 简介 全宽对齐) */ -.site-card[data-type="article"] { - display: block; - padding: 1rem 1.1rem; +.site-card[data-type='article'] { + display: block; + padding: 1rem 1.1rem; } -.site-card[data-type="article"] .article-card-header { - display: flex; - align-items: flex-start; - gap: 0.75rem; +.site-card[data-type='article'] .article-card-header { + display: flex; + align-items: flex-start; + gap: 0.75rem; } -.site-card[data-type="article"] .article-card-title { - min-width: 0; +.site-card[data-type='article'] .article-card-title { + min-width: 0; } -.site-card[data-type="article"] .article-card-body { - margin-top: 0.55rem; +.site-card[data-type='article'] .article-card-body { + margin-top: 0.55rem; } -.site-card[data-type="article"] h3 { - margin: 0; +.site-card[data-type='article'] h3 { + margin: 0; } -.site-card[data-type="article"] p { - margin: 0; +.site-card[data-type='article'] p { + margin: 0; } /* articles:桌面端网格固定 3 列(避免 auto-fill 在大屏上过多列导致阅读密度过高) */ .page-template-articles .sites-grid { - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(3, minmax(0, 1fr)); } @media (max-width: 1024px) { - .page-template-articles .sites-grid { - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - } + .page-template-articles .sites-grid { + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + } } @media (max-width: 480px) { - .page-template-articles .sites-grid { - grid-template-columns: 1fr; - gap: 0.5rem; - } + .page-template-articles .sites-grid { + grid-template-columns: 1fr; + gap: 0.5rem; + } } /* articles:标题/描述允许两行显示(更适合多列宽卡片,也适用于搜索结果页) */ -.site-card[data-type="article"] h3 { - white-space: normal; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; +.site-card[data-type='article'] h3 { + white-space: normal; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } -.site-card[data-type="article"] p { - white-space: normal; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; +.site-card[data-type='article'] p { + white-space: normal; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } .site-card:hover { - transform: translateY(-3px); - background: var(--site-card-hover-bg); - border-color: var(--border-color); + transform: translateY(-3px); + background: var(--site-card-hover-bg); + border-color: var(--border-color); } .site-card-icon { - flex-shrink: 0; - width: 2.5rem; - height: 2.5rem; - border-radius: var(--radius-md); - background: rgba(var(--card-bg-rgb), 0.35); - border: 1px solid var(--border-color); - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.3s ease, background-color 0.3s ease; + flex-shrink: 0; + width: 2.5rem; + height: 2.5rem; + border-radius: var(--radius-md); + background: rgba(var(--card-bg-rgb), 0.35); + border: 1px solid var(--border-color); + display: flex; + align-items: center; + justify-content: center; + transition: + transform 0.3s ease, + background-color 0.3s ease; } .site-card .site-icon { - font-size: 1.4rem; - color: var(--accent-color); - transition: color 0.3s ease; + font-size: 1.4rem; + color: var(--accent-color); + transition: color 0.3s ease; } .site-card:hover .site-card-icon { - transform: scale(1.06); + transform: scale(1.06); } .site-card:hover .site-icon { - color: var(--accent-hover); + color: var(--accent-hover); } /* 网站卡片 favicon 图片样式,与图标尺寸保持一致 */ .site-card .favicon-icon { - display: inline-block; - width: 1.8rem; - height: 1.8rem; - border-radius: var(--radius-sm); - object-fit: cover; - transition: transform 0.3s ease, box-shadow 0.3s ease; + display: inline-block; + width: 1.8rem; + height: 1.8rem; + border-radius: var(--radius-sm); + object-fit: cover; + transition: + transform 0.3s ease, + box-shadow 0.3s ease; } .site-card .icon-placeholder, .site-card .icon-fallback { - display: inline-block; - width: 1.8rem; - height: 1.8rem; - border-radius: var(--radius-sm); - flex-shrink: 0; - vertical-align: middle; - text-align: center; - line-height: 1.8rem; - font-size: 1.5rem; - transition: transform 0.3s ease, box-shadow 0.3s ease; - color: var(--accent-color); + display: inline-block; + width: 1.8rem; + height: 1.8rem; + border-radius: var(--radius-sm); + flex-shrink: 0; + vertical-align: middle; + text-align: center; + line-height: 1.8rem; + font-size: 1.5rem; + transition: + transform 0.3s ease, + box-shadow 0.3s ease; + color: var(--accent-color); } /* 确保图标容器在加载过程中保持固定尺寸 */ .site-card .icon-container { - display: inline-block; - width: 1.8rem; - height: 1.8rem; - position: relative; - vertical-align: middle; + display: inline-block; + width: 1.8rem; + height: 1.8rem; + position: relative; + vertical-align: middle; } .site-card .icon-container .favicon-icon, .site-card .icon-container .icon-placeholder, .site-card .icon-container .icon-fallback { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - margin-bottom: 0; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + margin-bottom: 0; } /* 优化图标切换动画 */ .site-card .icon-container .favicon-icon { - opacity: 0; - transition: opacity 0.3s ease; + opacity: 0; + transition: opacity 0.3s ease; } .site-card .icon-container .favicon-icon.loaded { - opacity: 1; + opacity: 1; } .site-card .icon-container .favicon-icon.error { - display: none; + display: none; } .site-card .icon-container .icon-placeholder { - opacity: 1; - transition: opacity 0.3s ease; + opacity: 1; + transition: opacity 0.3s ease; } .site-card .icon-container .icon-placeholder.hidden { - opacity: 0; - pointer-events: none; + opacity: 0; + pointer-events: none; } .site-card .icon-container .icon-fallback { - opacity: 0; - transition: opacity 0.3s ease; + opacity: 0; + transition: opacity 0.3s ease; } .site-card .icon-container .icon-fallback.visible { - opacity: 1; + opacity: 1; } .site-card:hover .icon-placeholder, .site-card:hover .icon-fallback { - color: var(--accent-hover); + color: var(--accent-hover); } .site-card-content { - flex: 1; - min-width: 0; - overflow: hidden; + flex: 1; + min-width: 0; + overflow: hidden; } .site-card h3 { - font-size: 1rem; - margin-bottom: 0.25rem; - color: var(--text-bright); - font-weight: 500; - letter-spacing: 0.3px; - transition: color 0.3s ease; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; + font-size: 1rem; + margin-bottom: 0.25rem; + color: var(--text-bright); + font-weight: 500; + letter-spacing: 0.3px; + transition: color 0.3s ease; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; } .site-card p { - font-size: 0.9rem; - color: var(--nav-item-color); - margin: 0; - line-height: 1.4; - transition: color 0.3s ease; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; - position: relative; - /* Ensure tooltip positioning context */ + font-size: 0.9rem; + color: var(--nav-item-color); + margin: 0; + line-height: 1.4; + transition: color 0.3s ease; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + position: relative; + /* Ensure tooltip positioning context */ } /* Tooltip styles */ /* Tooltip styles */ .site-card p[data-tooltip], .site-card .repo-desc[data-tooltip] { - cursor: default; - /* Indicate interactivity */ + cursor: default; + /* Indicate interactivity */ } .custom-tooltip { - position: fixed; - background: rgba(47, 48, 53, 0.95); - /* Fallback dark */ - background: rgba(var(--card-bg-rgb), 0.95); - color: var(--text-bright); - padding: 0.5rem 0.8rem; - border-radius: var(--radius-md); - box-shadow: 0 4px 12px var(--shadow-color); - border: 1px solid var(--border-color); - font-size: 0.85rem; - white-space: normal; - line-height: 1.4; - z-index: 9999; - pointer-events: none; - opacity: 0; - transition: opacity 0.2s ease-out; - backdrop-filter: blur(4px); - -webkit-backdrop-filter: blur(4px); - max-width: 300px; - word-break: break-word; + position: fixed; + background: rgba(47, 48, 53, 0.95); + /* Fallback dark */ + background: rgba(var(--card-bg-rgb), 0.95); + color: var(--text-bright); + padding: 0.5rem 0.8rem; + border-radius: var(--radius-md); + box-shadow: 0 4px 12px var(--shadow-color); + border: 1px solid var(--border-color); + font-size: 0.85rem; + white-space: normal; + line-height: 1.4; + z-index: 9999; + pointer-events: none; + opacity: 0; + transition: opacity 0.2s ease-out; + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); + max-width: 300px; + word-break: break-word; } .custom-tooltip.visible { - opacity: 1; + opacity: 1; } /* 添加编辑按钮 */ .edit-buttons { - position: absolute; - top: 0.5rem; - right: 0.5rem; - display: flex; - gap: 0.5rem; - opacity: 0; - transition: opacity 0.3s ease; + position: absolute; + top: 0.5rem; + right: 0.5rem; + display: flex; + gap: 0.5rem; + opacity: 0; + transition: opacity 0.3s ease; } .site-card:hover .edit-buttons { - opacity: 1; + opacity: 1; } .edit-btn, .delete-btn { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 0.3rem; - border-radius: 4px; - transition: all 0.3s ease; + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.3rem; + border-radius: 4px; + transition: all 0.3s ease; } .edit-btn:hover, .delete-btn:hover { - color: var(--text-bright); - background-color: var(--secondary-bg); + color: var(--text-bright); + background-color: var(--secondary-bg); } /* 添加网站按钮 */ .add-site-btn { - background: linear-gradient(145deg, var(--site-card-bg-gradient-1), var(--site-card-bg-gradient-2)); - border: 2px dashed var(--border-color); - border-radius: var(--radius-lg); - padding: 1.5rem; - color: var(--text-muted); - cursor: pointer; - transition: all var(--transition-normal); - transition-timing-function: var(--transition-bounce); - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 180px; - box-shadow: 0 4px 16px var(--shadow-color); + background: linear-gradient( + 145deg, + var(--site-card-bg-gradient-1), + var(--site-card-bg-gradient-2) + ); + border: 2px dashed var(--border-color); + border-radius: var(--radius-lg); + padding: 1.5rem; + color: var(--text-muted); + cursor: pointer; + transition: all var(--transition-normal); + transition-timing-function: var(--transition-bounce); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 180px; + box-shadow: 0 4px 16px var(--shadow-color); } .add-site-btn:hover { - background: linear-gradient(145deg, var(--secondary-bg), var(--site-card-bg-gradient-1)); - border-color: var(--accent-color); - color: var(--text-bright); - transform: translateY(-2px); - box-shadow: 0 6px 20px var(--shadow-color); + background: linear-gradient(145deg, var(--secondary-bg), var(--site-card-bg-gradient-1)); + border-color: var(--accent-color); + color: var(--text-bright); + transform: translateY(-2px); + box-shadow: 0 6px 20px var(--shadow-color); } .add-site-btn i { - font-size: 2.2rem; - margin-bottom: 0.8rem; - transition: transform 0.3s ease; + font-size: 2.2rem; + margin-bottom: 0.8rem; + transition: transform 0.3s ease; } .add-site-btn:hover i { - transform: scale(1.1); + transform: scale(1.1); } /* 模态框样式 */ .modal { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.6); - display: none; - justify-content: center; - align-items: center; - z-index: 1000; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + display: none; + justify-content: center; + align-items: center; + z-index: 1000; } .modal.active { - display: flex; - animation: modalFadeIn 0.3s ease-out forwards; + display: flex; + animation: modalFadeIn 0.3s ease-out forwards; } .modal-content { - background-color: var(--sidebar-bg); - border-radius: var(--radius-xl); - padding: var(--spacing-xl); - width: 90%; - max-width: 520px; - position: relative; - box-shadow: 0 8px 32px var(--shadow-color); - transform: scale(0.95); - opacity: 0; - animation: modalContentShow 0.3s ease-out forwards; - transition: background-color 0.3s ease; + background-color: var(--sidebar-bg); + border-radius: var(--radius-xl); + padding: var(--spacing-xl); + width: 90%; + max-width: 520px; + position: relative; + box-shadow: 0 8px 32px var(--shadow-color); + transform: scale(0.95); + opacity: 0; + animation: modalContentShow 0.3s ease-out forwards; + transition: background-color 0.3s ease; } .modal-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 2rem; + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; } .modal-header h3 { - color: var(--text-bright); - font-size: 1.3rem; - letter-spacing: 0.3px; - font-weight: 500; - transition: color 0.3s ease; + color: var(--text-bright); + font-size: 1.3rem; + letter-spacing: 0.3px; + font-weight: 500; + transition: color 0.3s ease; } .close-modal { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - font-size: 1.5rem; - padding: var(--spacing-sm); - transition: all var(--transition-normal); - border-radius: var(--radius-md); + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + font-size: 1.5rem; + padding: var(--spacing-sm); + transition: all var(--transition-normal); + border-radius: var(--radius-md); } .close-modal:hover { - color: var(--text-bright); - background-color: var(--secondary-bg); + color: var(--text-bright); + background-color: var(--secondary-bg); } /* 表单样式 */ .site-form { - display: flex; - flex-direction: column; - gap: 1.2rem; + display: flex; + flex-direction: column; + gap: 1.2rem; } .form-group { - display: flex; - flex-direction: column; - gap: 0.6rem; + display: flex; + flex-direction: column; + gap: 0.6rem; } .form-group label { - color: var(--text-muted); - font-size: 0.95rem; - letter-spacing: 0.2px; - transition: color 0.3s ease; + color: var(--text-muted); + font-size: 0.95rem; + letter-spacing: 0.2px; + transition: color 0.3s ease; } .form-group input, .form-group select { - background-color: var(--secondary-bg); - border: 1px solid transparent; - border-radius: var(--radius-md); - padding: var(--spacing-md) var(--spacing-lg); - color: var(--text-color); - font-size: 1rem; - transition: all var(--transition-normal); - box-shadow: 0 2px 6px var(--shadow-color); + background-color: var(--secondary-bg); + border: 1px solid transparent; + border-radius: var(--radius-md); + padding: var(--spacing-md) var(--spacing-lg); + color: var(--text-color); + font-size: 1rem; + transition: all var(--transition-normal); + box-shadow: 0 2px 6px var(--shadow-color); } .form-group input:focus, .form-group select:focus { - outline: none; - background-color: var(--secondary-bg); - border-color: var(--accent-color); - box-shadow: 0 2px 8px rgba(118, 148, 185, 0.15); + outline: none; + background-color: var(--secondary-bg); + border-color: var(--accent-color); + box-shadow: 0 2px 8px rgba(118, 148, 185, 0.15); } .form-group input::placeholder { - color: var(--text-muted); + color: var(--text-muted); } .form-actions { - display: flex; - justify-content: flex-end; - gap: 1rem; - margin-top: 2rem; + display: flex; + justify-content: flex-end; + gap: 1rem; + margin-top: 2rem; } .btn { - padding: var(--spacing-md) var(--spacing-xl); - border: none; - border-radius: var(--radius-md); - cursor: pointer; - font-size: 1rem; - font-weight: 500; - letter-spacing: 0.3px; - transition: all var(--transition-normal); - transition-timing-function: var(--transition-bounce); - box-shadow: 0 2px 6px var(--shadow-color); + padding: var(--spacing-md) var(--spacing-xl); + border: none; + border-radius: var(--radius-md); + cursor: pointer; + font-size: 1rem; + font-weight: 500; + letter-spacing: 0.3px; + transition: all var(--transition-normal); + transition-timing-function: var(--transition-bounce); + box-shadow: 0 2px 6px var(--shadow-color); } .btn-primary { - background-color: var(--accent-color); - color: var(--white-color); + background-color: var(--accent-color); + color: var(--white-color); } .btn-primary:hover { - background-color: var(--accent-hover); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(118, 148, 185, 0.2); + background-color: var(--accent-hover); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(118, 148, 185, 0.2); } .btn-secondary { - background-color: var(--secondary-bg); - color: var(--text-muted); + background-color: var(--secondary-bg); + color: var(--text-muted); } .btn-secondary:hover { - background-color: var(--secondary-bg); - color: var(--text-bright); - transform: translateY(-2px); - box-shadow: 0 4px 12px var(--shadow-color); + background-color: var(--secondary-bg); + color: var(--text-bright); + transform: translateY(-2px); + box-shadow: 0 4px 12px var(--shadow-color); } /* 响应式设计 */ @media (max-width: 1200px) { - .welcome-section { - padding: 0 var(--spacing-lg); - margin-bottom: 2rem; - } + .welcome-section { + padding: 0 var(--spacing-lg); + margin-bottom: 2rem; + } - .category { - max-width: 1100px; - margin: 0 auto 2.5rem auto; - } + .category { + max-width: 1100px; + margin: 0 auto 2.5rem auto; + } } @media (max-width: 768px) { - .mobile-buttons { - display: flex; - } + .mobile-buttons { + display: flex; + } - :root { - /* 与移动端搜索框高度更贴合(搜索框更高一些,菜单按钮同步放大) */ - --mobile-top-button-size: 2.9rem; - } + :root { + /* 与移动端搜索框高度更贴合(搜索框更高一些,菜单按钮同步放大) */ + --mobile-top-button-size: 2.9rem; + } - .menu-toggle { - width: var(--mobile-top-button-size); - height: var(--mobile-top-button-size); - background: rgba(var(--card-bg-rgb), 0.65); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - box-shadow: 0 4px 16px var(--shadow-color); - } + .menu-toggle { + width: var(--mobile-top-button-size); + height: var(--mobile-top-button-size); + background: rgba(var(--card-bg-rgb), 0.65); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + box-shadow: 0 4px 16px var(--shadow-color); + } - /* 移动端:右下角磁贴与侧边栏按钮磁贴统一风格 */ - .theme-toggle, - .category-toggle { - width: var(--mobile-top-button-size); - height: var(--mobile-top-button-size); - background: rgba(var(--card-bg-rgb), 0.65); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - box-shadow: 0 4px 16px var(--shadow-color); - transition: all var(--transition-normal); - transition-timing-function: var(--transition-bounce); - } + /* 移动端:右下角磁贴与侧边栏按钮磁贴统一风格 */ + .theme-toggle, + .category-toggle { + width: var(--mobile-top-button-size); + height: var(--mobile-top-button-size); + background: rgba(var(--card-bg-rgb), 0.65); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + box-shadow: 0 4px 16px var(--shadow-color); + transition: all var(--transition-normal); + transition-timing-function: var(--transition-bounce); + } - .theme-toggle:hover, - .category-toggle:hover { - transform: translateY(-2px); - background: rgba(var(--card-bg-rgb), 0.75); - box-shadow: 0 6px 20px var(--shadow-color); - color: var(--accent-color); - } + .theme-toggle:hover, + .category-toggle:hover { + transform: translateY(-2px); + background: rgba(var(--card-bg-rgb), 0.75); + box-shadow: 0 6px 20px var(--shadow-color); + color: var(--accent-color); + } - .theme-toggle:active, - .category-toggle:active { - transform: translateY(0); - box-shadow: 0 2px 8px var(--shadow-color); - } + .theme-toggle:active, + .category-toggle:active { + transform: translateY(0); + box-shadow: 0 2px 8px var(--shadow-color); + } - .content { - margin-left: 0; - width: 100vw; - max-width: 100vw; - padding-top: calc(var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); - padding-top: calc(env(safe-area-inset-top) + var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); - /* 缩短分类卡片与页面边缘的左右留白,扩大分类卡片可用宽度 */ - padding-left: calc(var(--spacing-sm) + var(--spacing-xs)); - padding-right: calc(var(--spacing-sm) + var(--spacing-xs)); - } + .content { + margin-left: 0; + width: 100vw; + max-width: 100vw; + padding-top: calc(var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); + padding-top: calc( + env(safe-area-inset-top) + var(--spacing-md) + var(--mobile-top-button-size) + + var(--spacing-sm) + ); + /* 缩短分类卡片与页面边缘的左右留白,扩大分类卡片可用宽度 */ + padding-left: calc(var(--spacing-sm) + var(--spacing-xs)); + padding-right: calc(var(--spacing-sm) + var(--spacing-xs)); + } - .sidebar { - transform: translateX(-100%); - box-shadow: none; - transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); - max-width: 100vw; - overflow-x: hidden; - } + .sidebar { + transform: translateX(-100%); + box-shadow: none; + transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); + max-width: 100vw; + overflow-x: hidden; + } - .sidebar .logo { - padding-top: 1.5rem; - display: flex; - align-items: center; - height: 60px; - } + .sidebar .logo { + padding-top: 1.5rem; + display: flex; + align-items: center; + height: 60px; + } - /* 移动端下隐藏侧边栏折叠按钮 */ - .sidebar-toggle { - display: none; - } + /* 移动端下隐藏侧边栏折叠按钮 */ + .sidebar-toggle { + display: none; + } - .sidebar.active { - transform: translateX(0); - box-shadow: 2px 0 10px var(--shadow-color); - z-index: 1000; - /* 增加侧边栏激活时的z-index,确保显示在按钮之上 */ - } + .sidebar.active { + transform: translateX(0); + box-shadow: 2px 0 10px var(--shadow-color); + z-index: 1000; + /* 增加侧边栏激活时的z-index,确保显示在按钮之上 */ + } - /* 重置移动端下的侧边栏展开状态 */ - .sidebar.collapsed { - width: var(--sidebar-width); - } + /* 重置移动端下的侧边栏展开状态 */ + .sidebar.collapsed { + width: var(--sidebar-width); + } - .sidebar.collapsed .logo h1, - .sidebar.collapsed .nav-item .nav-text, - .sidebar.collapsed .nav-item .external-icon { - opacity: 1; - transform: none; - width: auto; - } + .sidebar.collapsed .logo h1, + .sidebar.collapsed .nav-item .nav-text, + .sidebar.collapsed .nav-item .external-icon { + opacity: 1; + transform: none; + width: auto; + } - .sidebar.collapsed .sidebar-footer { - height: auto; - padding: 1rem 1.2rem; - visibility: visible; - pointer-events: auto; - border-top: 1px solid var(--border-color); - } + .sidebar.collapsed .sidebar-footer { + height: auto; + padding: 1rem 1.2rem; + visibility: visible; + pointer-events: auto; + border-top: 1px solid var(--border-color); + } - .sidebar.collapsed .sidebar-social { - padding: 0.2rem 1.2rem 0.8rem; - flex-direction: row; - } + .sidebar.collapsed .sidebar-social { + padding: 0.2rem 1.2rem 0.8rem; + flex-direction: row; + } - .sidebar.collapsed .nav-item { - padding: 0.6rem 0.8rem; - justify-content: flex-start; - } + .sidebar.collapsed .nav-item { + padding: 0.6rem 0.8rem; + justify-content: flex-start; + } - .sidebar.collapsed .nav-item .icon-container { - margin-right: 1rem; - } + .sidebar.collapsed .nav-item .icon-container { + margin-right: 1rem; + } - /* 移动端:搜索框常驻显示(与侧边栏按钮同一行,无需“悬浮磁贴”) */ - .search-container { - position: fixed; - top: var(--spacing-md); - top: calc(env(safe-area-inset-top) + var(--spacing-md)); - /* 给左侧菜单按钮留出空间 */ - left: calc(var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); - right: var(--spacing-md); - left: calc(env(safe-area-inset-left) + var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); - right: calc(env(safe-area-inset-right) + var(--spacing-md)); - width: auto; - padding: 0; - margin-bottom: 0; - box-shadow: none; - z-index: 900; - } + /* 移动端:搜索框常驻显示(与侧边栏按钮同一行,无需“悬浮磁贴”) */ + .search-container { + position: fixed; + top: var(--spacing-md); + top: calc(env(safe-area-inset-top) + var(--spacing-md)); + /* 给左侧菜单按钮留出空间 */ + left: calc(var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); + right: var(--spacing-md); + left: calc( + env(safe-area-inset-left) + var(--spacing-md) + var(--mobile-top-button-size) + + var(--spacing-sm) + ); + right: calc(env(safe-area-inset-right) + var(--spacing-md)); + width: auto; + padding: 0; + margin-bottom: 0; + box-shadow: none; + z-index: 900; + } - .search-box { - max-width: 100%; - } + .search-box { + max-width: 100%; + } - .search-box input { - padding: 0.8rem 3rem 0.8rem 1rem; - font-size: 0.95rem; - } + .search-box input { + padding: 0.8rem 3rem 0.8rem 1rem; + font-size: 0.95rem; + } - .search-box::after { - right: 0.8rem; - } + .search-box::after { + right: 0.8rem; + } - .search-shortcut-hint { - right: 1.2rem; - font-size: 0.72rem; - padding: 0.1rem 0.35rem; - } + .search-shortcut-hint { + right: 1.2rem; + font-size: 0.72rem; + padding: 0.1rem 0.35rem; + } - .search-engine-button { - width: 104px; - flex: 0 0 104px; - padding: 0 0.6rem; - } + .search-engine-button { + width: 104px; + flex: 0 0 104px; + padding: 0 0.6rem; + } - .sidebar .logo h1, - .sidebar .nav-item span { - opacity: 1; - display: block; - } + .sidebar .logo h1, + .sidebar .nav-item span { + opacity: 1; + display: block; + } - /* 欢迎区域样式 */ - .welcome-section { - padding: 0 1rem; - margin-top: 1rem; - /* 增加顶部间距 */ - } + /* 欢迎区域样式 */ + .welcome-section { + padding: 0 1rem; + margin-top: 1rem; + /* 增加顶部间距 */ + } - .page { - padding-left: 0.15rem; - padding-right: 0.15rem; - } + .page { + padding-left: 0.15rem; + padding-right: 0.15rem; + } - .welcome-section h2 { - font-size: 2rem; - } + .welcome-section h2 { + font-size: 2rem; + } - .welcome-section h3 { - font-size: 1.6rem; - background: var(--gradient-color-simple); - -webkit-background-clip: text; - background-clip: text; - animation: glow 3s ease-in-out infinite alternate; - } + .welcome-section h3 { + font-size: 1.6rem; + background: var(--gradient-color-simple); + -webkit-background-clip: text; + background-clip: text; + animation: glow 3s ease-in-out infinite alternate; + } - /* 移动端分类切换按钮 */ - .category-toggle { - bottom: 4rem; - bottom: calc(env(safe-area-inset-bottom) + 4rem); - right: 1rem; - right: calc(env(safe-area-inset-right) + 1rem); - } + /* 移动端分类切换按钮 */ + .category-toggle { + bottom: 4rem; + bottom: calc(env(safe-area-inset-bottom) + 4rem); + right: 1rem; + right: calc(env(safe-area-inset-right) + 1rem); + } - /* 移动端:隐藏搜索按钮(未删除,仅隐藏;搜索框常驻) */ - .search-toggle { - display: none; - } + /* 移动端:隐藏搜索按钮(未删除,仅隐藏;搜索框常驻) */ + .search-toggle { + display: none; + } - /* 分类样式优化 */ - .category { - margin: 0 auto var(--spacing-lg) auto; - padding: var(--spacing-md); - width: 100%; - } + /* 分类样式优化 */ + .category { + margin: 0 auto var(--spacing-lg) auto; + padding: var(--spacing-md); + width: 100%; + } - .sites-grid { - gap: var(--spacing-sm); - grid-template-columns: repeat(2, minmax(0, 1fr)); - } + .sites-grid { + gap: var(--spacing-sm); + grid-template-columns: repeat(2, minmax(0, 1fr)); + } - .site-card { - /* 移动端保持与客户端一致:横排卡片(图标在左,文本左对齐) */ - flex-direction: row; - align-items: center; - text-align: left; - padding: 0.75rem 0.65rem; - gap: 0.6rem; - } + .site-card { + /* 移动端保持与客户端一致:横排卡片(图标在左,文本左对齐) */ + flex-direction: row; + align-items: center; + text-align: left; + padding: 0.75rem 0.65rem; + gap: 0.6rem; + } - .site-card-icon { - width: 2.2rem; - height: 2.2rem; - } + .site-card-icon { + width: 2.2rem; + height: 2.2rem; + } - .site-card .site-icon { - font-size: 1.5rem; - } + .site-card .site-icon { + font-size: 1.5rem; + } - .site-card .favicon-icon, - .site-card .icon-placeholder, - .site-card .icon-fallback, - .site-card .icon-container { - width: 1.5rem; - height: 1.5rem; - } + .site-card .favicon-icon, + .site-card .icon-placeholder, + .site-card .icon-fallback, + .site-card .icon-container { + width: 1.5rem; + height: 1.5rem; + } - .site-card .icon-placeholder, - .site-card .icon-fallback { - line-height: 1.5rem; - font-size: 1.3rem; - } + .site-card .icon-placeholder, + .site-card .icon-fallback { + line-height: 1.5rem; + font-size: 1.3rem; + } - .site-card-content { - text-align: left; - } + .site-card-content { + text-align: left; + } - .site-card h3 { - font-size: 1rem; - margin-bottom: 0.25rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - } + .site-card h3 { + font-size: 1rem; + margin-bottom: 0.25rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + } - .site-card p { - font-size: 0.9rem; - line-height: 1.4; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } + .site-card p { + font-size: 0.9rem; + line-height: 1.4; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } - /* 在移动端的主题切换按钮 */ - .theme-toggle { - bottom: 1rem; - bottom: calc(env(safe-area-inset-bottom) + 1rem); - right: 1rem; - right: calc(env(safe-area-inset-right) + 1rem); - } + /* 在移动端的主题切换按钮 */ + .theme-toggle { + bottom: 1rem; + bottom: calc(env(safe-area-inset-bottom) + 1rem); + right: 1rem; + right: calc(env(safe-area-inset-right) + 1rem); + } - .sidebar .submenu { - margin-left: 1rem; - } + .sidebar .submenu { + margin-left: 1rem; + } - .sidebar.active .submenu-item { - padding: 0.5rem 0.6rem; - } + .sidebar.active .submenu-item { + padding: 0.5rem 0.6rem; + } - /* 确保移动设备上子菜单不会出现漏出问题 */ - .sidebar.collapsed .submenu { - display: none; - } + /* 确保移动设备上子菜单不会出现漏出问题 */ + .sidebar.collapsed .submenu { + display: none; + } } @media (max-width: 480px) { + .welcome-section { + padding: 0 1rem; + margin-bottom: 1.5rem; + } - .welcome-section { - padding: 0 1rem; - margin-bottom: 1.5rem; - } + .category { + margin: 0 auto 1.3rem auto; + padding: 0.95rem; + width: 100%; + } - .category { - margin: 0 auto 1.3rem auto; - padding: 0.95rem; - width: 100%; - } + .search-container { + left: calc(var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); + right: var(--spacing-md); + left: calc( + env(safe-area-inset-left) + var(--spacing-md) + var(--mobile-top-button-size) + + var(--spacing-sm) + ); + right: calc(env(safe-area-inset-right) + var(--spacing-md)); + } - .search-container { - left: calc(var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); - right: var(--spacing-md); - left: calc(env(safe-area-inset-left) + var(--spacing-md) + var(--mobile-top-button-size) + var(--spacing-sm)); - right: calc(env(safe-area-inset-right) + var(--spacing-md)); - } + .page { + padding-top: 1rem; + padding-left: 0.1rem; + padding-right: 0.1rem; + } - .page { - padding-top: 1rem; - padding-left: 0.1rem; - padding-right: 0.1rem; - } + .sites-grid { + gap: 0.5rem; + grid-template-columns: repeat(2, minmax(0, 1fr)); + } - .sites-grid { - gap: 0.5rem; - grid-template-columns: repeat(2, minmax(0, 1fr)); - } + .site-card { + padding: 0.75rem 0.5rem; + gap: 0.5rem; + } - .site-card { - padding: 0.75rem 0.5rem; - gap: 0.5rem; - } + .site-card-icon { + width: 2rem; + height: 2rem; + } - .site-card-icon { - width: 2rem; - height: 2rem; - } + .site-card .site-icon { + font-size: 1.3rem; + } - .site-card .site-icon { - font-size: 1.3rem; - } + .site-card .favicon-icon, + .site-card .icon-placeholder, + .site-card .icon-fallback, + .site-card .icon-container { + width: 1.35rem; + height: 1.35rem; + } - .site-card .favicon-icon, - .site-card .icon-placeholder, - .site-card .icon-fallback, - .site-card .icon-container { - width: 1.35rem; - height: 1.35rem; - } + .site-card .icon-placeholder, + .site-card .icon-fallback { + line-height: 1.35rem; + font-size: 1.2rem; + } - .site-card .icon-placeholder, - .site-card .icon-fallback { - line-height: 1.35rem; - font-size: 1.2rem; - } + .site-card h3 { + font-size: 1rem; + margin-bottom: 0.3rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + } - .site-card h3 { - font-size: 1rem; - margin-bottom: 0.3rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - } - - .site-card p { - font-size: 0.9rem; - line-height: 1.2; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } + .site-card p { + font-size: 0.9rem; + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } } @media (max-width: 400px) { - .category { - padding: 0.85rem; - margin: 0 0.05rem 1.2rem 0.05rem; - width: calc(100% - 0.1rem); - } + .category { + padding: 0.85rem; + margin: 0 0.05rem 1.2rem 0.05rem; + width: calc(100% - 0.1rem); + } - .sites-grid { - gap: 0.4rem; - grid-template-columns: repeat(2, minmax(0, 1fr)); - } + .sites-grid { + gap: 0.4rem; + grid-template-columns: repeat(2, minmax(0, 1fr)); + } - .site-card { - padding: 0.6rem 0.4rem; - gap: 0.45rem; - } + .site-card { + padding: 0.6rem 0.4rem; + gap: 0.45rem; + } - .site-card-icon { - width: 1.9rem; - height: 1.9rem; - } + .site-card-icon { + width: 1.9rem; + height: 1.9rem; + } - .site-card .site-icon { - font-size: 1.2rem; - } + .site-card .site-icon { + font-size: 1.2rem; + } - .site-card .favicon-icon, - .site-card .icon-placeholder, - .site-card .icon-fallback, - .site-card .icon-container { - width: 1.25rem; - height: 1.25rem; - } + .site-card .favicon-icon, + .site-card .icon-placeholder, + .site-card .icon-fallback, + .site-card .icon-container { + width: 1.25rem; + height: 1.25rem; + } - .site-card .icon-placeholder, - .site-card .icon-fallback { - line-height: 1.25rem; - font-size: 1.1rem; - } + .site-card .icon-placeholder, + .site-card .icon-fallback { + line-height: 1.25rem; + font-size: 1.1rem; + } - .site-card h3 { - font-size: 1rem; - margin-bottom: 0.25rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - } + .site-card h3 { + font-size: 1rem; + margin-bottom: 0.25rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + } - .site-card p { - font-size: 0.9rem; - line-height: 1.15; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } + .site-card p { + font-size: 0.9rem; + line-height: 1.15; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } } /* 动画效果 */ @keyframes fadeIn { - from { - opacity: 0; - transform: translateY(10px); - } + from { + opacity: 0; + transform: translateY(10px); + } - to { - opacity: 1; - transform: translateY(0); - } + to { + opacity: 1; + transform: translateY(0); + } } /* 搜索结果页面 */ #search-results { - position: relative; - width: 100%; - display: none; - flex-direction: column; - align-items: center; - /* 保持在搜索框之下,避免滚动时覆盖 sticky 的搜索容器 */ - z-index: 1; - transform: none !important; - /* 确保没有变换 */ - min-height: 400px; - /* 确保最小高度,防止内容过少时的布局跳动 */ + position: relative; + width: 100%; + display: none; + flex-direction: column; + align-items: center; + /* 保持在搜索框之下,避免滚动时覆盖 sticky 的搜索容器 */ + z-index: 1; + transform: none !important; + /* 确保没有变换 */ + min-height: 400px; + /* 确保最小高度,防止内容过少时的布局跳动 */ } #search-results.active { - display: flex; - animation: fadeIn 0.3s ease-out forwards; + display: flex; + animation: fadeIn 0.3s ease-out forwards; } /* 搜索结果区域 */ .search-section { - width: 100%; - max-width: var(--page-max-width); - margin: 0 auto 2.5rem auto; - position: relative; - z-index: 1; - transform: none !important; - opacity: 1 !important; + width: 100%; + max-width: var(--page-max-width); + margin: 0 auto 2.5rem auto; + position: relative; + z-index: 1; + transform: none !important; + opacity: 1 !important; } /* 确保搜索结果中的网格有正确的间距 */ .search-section .sites-grid { - margin-top: 1rem; + margin-top: 1rem; } /* 搜索结果页:按来源页面复用对应网格规则(方案 2:复用原卡片 DOM) */ -#search-results [data-section="projects"] .sites-grid { - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 24px; +#search-results [data-section='projects'] .sites-grid { + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 24px; } -#search-results [data-section="articles"] .sites-grid { - grid-template-columns: repeat(4, minmax(0, 1fr)); +#search-results [data-section='articles'] .sites-grid { + grid-template-columns: repeat(4, minmax(0, 1fr)); } @media (max-width: 1024px) { - #search-results [data-section="articles"] .sites-grid { - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - } + #search-results [data-section='articles'] .sites-grid { + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + } } @media (max-width: 480px) { - #search-results [data-section="articles"] .sites-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 0.5rem; - } + #search-results [data-section='articles'] .sites-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.5rem; + } } /* 确保搜索结果中的卡片样式一致 */ .search-section .site-card { - max-width: 100%; + max-width: 100%; } /* 加载中动画 */ .page { - opacity: 0; - transition: opacity 0.3s ease; + opacity: 0; + transition: opacity 0.3s ease; } .page.active { - opacity: 1; + opacity: 1; } /* 模态框动画 */ @keyframes modalFadeIn { - from { - opacity: 0; - } + from { + opacity: 0; + } - to { - opacity: 1; - } + to { + opacity: 1; + } } @keyframes modalContentShow { - from { - opacity: 0; - transform: scale(0.9); - } + from { + opacity: 0; + transform: scale(0.9); + } - to { - opacity: 1; - transform: scale(1); - } + to { + opacity: 1; + transform: scale(1); + } } .sites-grid { - transition: gap 0.3s ease; + transition: gap 0.3s ease; } /* 侧边栏底部:社交图标(位于 sidebar-footer 上方) */ .sidebar-social { - grid-area: social; - padding: 0.2rem 1.2rem 0.8rem; - display: flex; - justify-content: center; - flex-wrap: wrap; - gap: 0.9rem; + grid-area: social; + padding: 0.2rem 1.2rem 0.8rem; + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 0.9rem; } .social-icon { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0.35rem; - border-radius: var(--radius-full); - color: var(--nav-item-color); - text-decoration: none; - transition: color var(--transition-fast), transform var(--transition-fast); + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.35rem; + border-radius: var(--radius-full); + color: var(--nav-item-color); + text-decoration: none; + transition: + color var(--transition-fast), + transform var(--transition-fast); } .social-icon:hover { - color: var(--accent-color); - transform: translateY(-1px); + color: var(--accent-color); + transform: translateY(-1px); } .social-icon:active { - transform: translateY(0); + transform: translateY(0); } .social-icon:focus-visible { - outline: 2px solid rgba(118, 148, 185, 0.35); - outline-offset: 2px; + outline: 2px solid rgba(118, 148, 185, 0.35); + outline-offset: 2px; } .social-icon i { - width: auto; - font-size: 1.2rem; + width: auto; + font-size: 1.2rem; } /* 侧边栏底部:版权信息 */ .sidebar-footer { - grid-area: footer; - padding: 1rem 1.2rem; - padding-bottom: calc(1rem + env(safe-area-inset-bottom)); - text-align: center; - color: var(--text-muted); - font-size: 0.85rem; - border-top: 1px solid var(--border-color); - background-color: var(--sidebar-bg); - /* 使用变量 */ - transition: background-color 0.3s ease, color 0.3s ease, opacity 0.3s ease; + grid-area: footer; + padding: 1rem 1.2rem; + padding-bottom: calc(1rem + env(safe-area-inset-bottom)); + text-align: center; + color: var(--text-muted); + font-size: 0.85rem; + border-top: 1px solid var(--border-color); + background-color: var(--sidebar-bg); + /* 使用变量 */ + transition: + background-color 0.3s ease, + color 0.3s ease, + opacity 0.3s ease; } .sidebar-footer .copyright { - margin: 0; + margin: 0; } .sidebar.collapsed .sidebar-social { - padding: 0.2rem 0.5rem 0.8rem; - flex-direction: column; - align-items: center; - gap: 0.6rem; + padding: 0.2rem 0.5rem 0.8rem; + flex-direction: column; + align-items: center; + gap: 0.6rem; } .copyright a { - color: var(--accent-color); - text-decoration: none; - transition: all 0.3s ease; + color: var(--accent-color); + text-decoration: none; + transition: all 0.3s ease; } .copyright a:hover { - color: var(--accent-hover); - text-decoration: underline; + color: var(--accent-hover); + text-decoration: underline; } /* 导航项包装器 - 包含导航项和子菜单 */ .nav-item-wrapper { - position: relative; - display: flex; - flex-direction: column; - width: 100%; -} - -/* 子菜单切换图标 */ -.submenu-toggle { - font-size: 0.8rem; - margin-left: 0.5rem; - transition: transform 0.3s ease; -} - -/* 子菜单展开状态图标旋转 */ -.nav-item-wrapper.expanded .submenu-toggle { - transform: rotate(180deg); + position: relative; + display: flex; + flex-direction: column; + width: 100%; } /* 子菜单容器 */ .submenu { - max-height: 0; - overflow: hidden; - transition: max-height 0.3s ease; - margin-left: 1.5rem; - opacity: 0; - visibility: hidden; + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease; + margin-left: 1.5rem; + opacity: 0; + visibility: hidden; } /* 子菜单展开状态 */ .nav-item-wrapper.expanded .submenu { - max-height: 300px; - /* 设置合理的最大高度 */ - overflow-y: scroll; - /* 改为scroll确保始终能滚动 */ - opacity: 1; - visibility: visible; - scrollbar-width: none; - /* Firefox隐藏滚动条 */ -} - -/* 为WebKit浏览器隐藏滚动条 */ -.nav-item-wrapper.expanded .submenu::-webkit-scrollbar { - display: none; + max-height: none; + overflow: visible; + opacity: 1; + visibility: visible; } /* 子菜单项样式 */ .submenu-item { - display: flex; - align-items: center; - padding: 0.5rem 0.8rem; - color: var(--nav-item-color); - text-decoration: none; - border-radius: 8px; - transition: all 0.3s ease; - font-size: 0.9rem; - margin: 0.1rem 0; + display: flex; + align-items: center; + padding: 0.5rem 0.8rem; + color: var(--nav-item-color); + text-decoration: none; + border-radius: 8px; + transition: all 0.3s ease; + font-size: 0.9rem; + margin: 0.1rem 0; } .submenu-item i { - margin-right: 0.8rem; - font-size: 0.85rem; - width: 16px; - text-align: center; + margin-right: 0.8rem; + font-size: 0.85rem; + width: 16px; + text-align: center; } .submenu-item span { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .submenu-item:hover { - background-color: var(--secondary-bg); - color: var(--text-bright); + background-color: var(--secondary-bg); + color: var(--text-bright); } .submenu-item.active { - background-color: var(--secondary-bg); - color: var(--text-bright); + background-color: var(--secondary-bg); + color: var(--text-bright); } /* 侧边栏折叠状态下子菜单样式 通过精确控制子菜单的位置和显示方式,确保在侧边栏折叠状态下子菜单不会漏出 使用display: none确保完全隐藏,避免任何可能的视觉问题 */ .sidebar.collapsed .submenu { - position: absolute; - left: var(--sidebar-collapsed-width); - /* 使用变量确保与侧边栏宽度一致 */ - top: 0; - background-color: var(--sidebar-bg); - border-radius: 0 8px 8px 0; - box-shadow: 4px 0 10px var(--shadow-color); - margin-left: 0; - width: 180px; - opacity: 0; - visibility: hidden; - max-height: 0; - overflow: hidden; - z-index: 200; - pointer-events: none; - transition: all 0.3s ease; - display: none; - /* 添加 display: none 确保完全隐藏 */ + position: absolute; + left: var(--sidebar-collapsed-width); + /* 使用变量确保与侧边栏宽度一致 */ + top: 0; + background-color: var(--sidebar-bg); + border-radius: 0 8px 8px 0; + box-shadow: 4px 0 10px var(--shadow-color); + margin-left: 0; + width: 180px; + opacity: 0; + visibility: hidden; + max-height: 0; + overflow: hidden; + z-index: 200; + pointer-events: none; + transition: all 0.3s ease; + display: none; + /* 添加 display: none 确保完全隐藏 */ } /* 确保子菜单项在悬停时不会漏出 控制子菜单项的文本溢出行为,确保内容不会超出容器范围 */ .sidebar.collapsed .submenu-item { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; - box-sizing: border-box; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + box-sizing: border-box; } /* 确保子菜单容器在悬停时不会漏出 使用static定位是为了让子菜单相对于侧边栏定位,而不是相对于nav-item-wrapper, 这样可以避免子菜单在折叠状态下漏出的问题 */ .sidebar.collapsed .nav-item-wrapper { - position: static; - /* 改为static,防止子菜单定位问题 */ + position: static; + /* 改为static,防止子菜单定位问题 */ } /* 修改子菜单在悬停时的显示位置 当用户悬停在导航项上时,显示子菜单,并确保其位置正确 使用绝对定位确保子菜单相对于侧边栏定位,避免在不同滚动位置出现问题 */ .sidebar.collapsed .nav-item-wrapper:hover .submenu { - max-height: 300px; - overflow-y: scroll; - opacity: 1; - visibility: visible; - scrollbar-width: none; - pointer-events: auto; - display: block; - left: var(--sidebar-collapsed-width); - /* 确保与侧边栏宽度一致 */ - top: 0; - /* 确保从顶部开始 */ - position: absolute; - /* 使用绝对定位,更符合文档流 */ + max-height: 300px; + overflow-y: scroll; + opacity: 1; + visibility: visible; + scrollbar-width: none; + pointer-events: auto; + display: block; + left: var(--sidebar-collapsed-width); + /* 确保与侧边栏宽度一致 */ + top: 0; + /* 确保从顶部开始 */ + position: absolute; + /* 使用绝对定位,更符合文档流 */ } /* 为WebKit浏览器隐藏滚动条 */ .sidebar.collapsed .nav-item-wrapper:hover .submenu::-webkit-scrollbar { - display: none; -} - -.sidebar.collapsed .submenu-toggle { - display: none; + display: none; } /* 移动端样式调整 */ @media (max-width: 768px) { - .sidebar .submenu { - margin-left: 1rem; - } + .sidebar .submenu { + margin-left: 1rem; + } - .sidebar.active .submenu-item { - padding: 0.5rem 0.6rem; - } + .sidebar.active .submenu-item { + padding: 0.5rem 0.6rem; + } - /* 确保移动设备上子菜单不会出现漏出问题 */ - .sidebar.collapsed .submenu { - display: none; - } + /* 确保移动设备上子菜单不会出现漏出问题 */ + .sidebar.collapsed .submenu { + display: none; + } } diff --git a/src/runtime/app/routing.js b/src/runtime/app/routing.js index e07045f..55cb41b 100644 --- a/src/runtime/app/routing.js +++ b/src/runtime/app/routing.js @@ -2,7 +2,7 @@ const nested = require('../nested'); module.exports = function initRouting(state, dom, api) { const { ui, search } = api; - const { searchInput, content } = dom; + const { searchInput, content, sidebar } = dom; function showPage(pageId, skipSearchReset = false) { if (state.currentPageId === pageId && !skipSearchReset && !state.isInitialLoad) return; @@ -52,6 +52,83 @@ module.exports = function initRouting(state, dom, api) { const normalizeText = (value) => String(value === null || value === undefined ? '' : value).trim(); + // 侧边栏子菜单面板:将“当前页面的分类列表”放到独立区域滚动,避免挤压“页面列表” + const submenuPanel = document.querySelector('.sidebar-submenu-panel'); + const submenuByPageId = new Map(); + let submenuPanelPageId = ''; + + navItemWrappers.forEach((wrapper) => { + const nav = wrapper.querySelector('.nav-item'); + const pageId = nav ? normalizeText(nav.getAttribute('data-page')) : ''; + const submenu = wrapper.querySelector('.submenu'); + if (!pageId || !submenu) return; + submenuByPageId.set(pageId, { wrapper, submenu }); + }); + + const isSidebarCollapsed = () => Boolean(sidebar && sidebar.classList.contains('collapsed')); + + const clearSubmenuPanel = () => { + if (!submenuPanel) return; + + const pageId = normalizeText(submenuPanelPageId); + if (pageId) { + const entry = submenuByPageId.get(pageId); + if (entry && entry.wrapper && entry.submenu) { + entry.wrapper.appendChild(entry.submenu); + } + } + + submenuPanel.textContent = ''; + submenuPanelPageId = ''; + }; + + const renderSubmenuPanelForPage = (pageId) => { + if (!submenuPanel) return; + + const id = normalizeText(pageId); + if (!id) { + clearSubmenuPanel(); + return; + } + + // 折叠态:子菜单使用 hover 弹出,不使用面板 + if (isSidebarCollapsed()) { + clearSubmenuPanel(); + return; + } + + const entry = submenuByPageId.get(id); + if (!entry || !entry.wrapper || !entry.submenu) { + clearSubmenuPanel(); + return; + } + + // 仅当 wrapper 处于 expanded 时展示(与 UI 行为保持一致) + if (!entry.wrapper.classList.contains('expanded')) { + clearSubmenuPanel(); + return; + } + + if (normalizeText(submenuPanelPageId) === id && submenuPanel.contains(entry.submenu)) { + return; + } + + clearSubmenuPanel(); + submenuPanel.appendChild(entry.submenu); + submenuPanelPageId = id; + }; + + // 监听侧边栏折叠状态变化:折叠时归还子菜单;展开时渲染当前页子菜单 + if (sidebar && typeof MutationObserver === 'function') { + const observer = new MutationObserver(() => { + const activeNav = document.querySelector('.nav-item.active'); + const activePageId = activeNav ? normalizeText(activeNav.getAttribute('data-page')) : ''; + renderSubmenuPanelForPage(activePageId); + }); + + observer.observe(sidebar, { attributes: true, attributeFilter: ['class'] }); + } + const isValidPageId = (pageId) => { const id = normalizeText(pageId); if (!id) return false; @@ -119,10 +196,13 @@ module.exports = function initRouting(state, dom, api) { navItemWrappers.forEach((wrapper) => { const nav = wrapper.querySelector('.nav-item'); if (!nav) return; - const hasSubmenu = Boolean(wrapper.querySelector('.submenu')); + const pageId = normalizeText(nav.getAttribute('data-page')); + const hasSubmenu = pageId ? submenuByPageId.has(pageId) : false; const shouldExpand = hasSubmenu && nav === activeItem; wrapper.classList.toggle('expanded', shouldExpand); }); + + renderSubmenuPanelForPage(id); }; const escapeSelector = (value) => { @@ -270,17 +350,6 @@ module.exports = function initRouting(state, dom, api) { }, index * 100); }); - // 初始展开当前页面的子菜单:高亮项如果有子菜单,需要同步展开 - document.querySelectorAll('.nav-item.active').forEach((activeItem) => { - const activeWrapper = activeItem.closest('.nav-item-wrapper'); - if (!activeWrapper) return; - - const hasSubmenu = activeWrapper.querySelector('.submenu'); - if (hasSubmenu) { - activeWrapper.classList.add('expanded'); - } - }); - // 导航项点击效果 navItems.forEach((item) => { item.addEventListener('click', (e) => { @@ -290,45 +359,31 @@ module.exports = function initRouting(state, dom, api) { // 获取当前项的父级 wrapper const wrapper = item.closest('.nav-item-wrapper'); - const hasSubmenu = wrapper && wrapper.querySelector('.submenu'); + const pageId = normalizeText(item.getAttribute('data-page')); + const hasSubmenu = Boolean(wrapper && pageId && submenuByPageId.has(pageId)); + + if (!pageId) return; // 处理子菜单展开/折叠 - if (hasSubmenu) { - // 如果点击的导航项已经激活且有子菜单,则切换子菜单展开状态 - if (item.classList.contains('active')) { - wrapper.classList.toggle('expanded'); - } else { - // 关闭所有已展开的子菜单 - navItemWrappers.forEach((navWrapper) => { - if (navWrapper !== wrapper) { - navWrapper.classList.remove('expanded'); - } - }); - - // 展开当前子菜单 - wrapper.classList.add('expanded'); - } + if (hasSubmenu && item.classList.contains('active')) { + // 当前页:保持子菜单展开状态,不做任何操作 + return; + } else { + // 切换页面:统一由 setActiveNavByPageId 管理 active/expanded + setActiveNavByPageId(pageId); } - // 激活导航项 - navItems.forEach((nav) => { - nav.classList.toggle('active', nav === item); - }); + const prevPageId = state.currentPageId; + showPage(pageId); - const pageId = item.getAttribute('data-page'); - if (pageId) { - const prevPageId = state.currentPageId; - showPage(pageId); + // 切换页面时同步 URL(清空旧 hash,避免跨页残留) + if (normalizeText(prevPageId) !== normalizeText(pageId)) { + setUrlState({ pageId, hash: '' }, { replace: true }); + } - // 切换页面时同步 URL(清空旧 hash,避免跨页残留) - if (normalizeText(prevPageId) !== normalizeText(pageId)) { - setUrlState({ pageId, hash: '' }, { replace: true }); - } - - // 在移动端视图下点击导航项后自动收起侧边栏 - if (ui.isMobile() && state.isSidebarOpen && !hasSubmenu) { - ui.closeAllPanels(); - } + // 在移动端视图下点击导航项后自动收起侧边栏 + if (ui.isMobile() && state.isSidebarOpen && !hasSubmenu) { + ui.closeAllPanels(); } }); }); @@ -352,10 +407,8 @@ module.exports = function initRouting(state, dom, api) { // 激活当前子菜单项 item.classList.add('active'); - // 激活相应的导航项 - navItems.forEach((nav) => { - nav.classList.toggle('active', nav.getAttribute('data-page') === pageId); - }); + // 激活导航项并同步子菜单展开状态 + setActiveNavByPageId(pageId); // 显示对应页面 showPage(pageId); diff --git a/templates/components/navigation.hbs b/templates/components/navigation.hbs index 199f5d4..f1a253a 100644 --- a/templates/components/navigation.hbs +++ b/templates/components/navigation.hbs @@ -6,10 +6,10 @@ {{name}} - {{#if submenu}}{{/if}} {{#if submenu}}