Files
HomeDash/web/navi.css
HomeDash Bot 26a0b15014 perf(web)+fix(admin): 撤掉卡片层模糊、补隐藏动画、后台窄屏适配、收边两段式
1) 卡顿:撤掉"重复且参与动画"的卡片层 backdrop-filter
   实测首页 37 个元素带模糊(24 张卡片 + 6 个分组容器 + 顶栏 + 悬浮件)。
   模糊要对背景逐帧重采样,而卡片又参与逐张淡入与悬停位移,叠加就是卡顿。
   现在只保留分组容器的玻璃感与悬浮件(搜索栏因宽/圆角/内边距一直在变也去掉)。
   实测:/ 从 37 → 12,/minimal 从 15 → 4。
   注意:选择器必须写成 html[data-theme] body a.item —— 主题的 customCss 由
   Dashy 运行时注入,同权重 + 同为 !important 时靠文档顺序决胜,写在 navi.css
   里的规则会输,必须提高特异性。

2) 隐藏/出现补动画
   ≤380px 让位隐藏按钮组:加上 opacity+位移过渡,并把 visibility 延迟到淡出
   结束再切(否则瞬间消失、看不到过渡)。弹层关闭先加 .closing 淡出再摘节点。
   降动效模式下不再用 transform:none 抹掉"收边"的位移,避免隐藏失效。

3) 工作空间收边改为"第一次交互只滑出"
   收起态点一下只滑出、不触发(否则贴边的按钮会被直接点中,比如想看搜索框
   结果把管理后台打开了);第二次点击才生效。判据是"元素是否真的露在视口内",
   所以鼠标悬停已展开时一次点击即生效。6 秒无操作或 Esc 自动收回。

4) 后台窄屏:分组行原本是内联 flex + 固定 max-width,窄屏既不能换行也不能
   收缩,输入框顶破卡片。改用类 + ≤560px 适配(竖排、整行占满、按钮右对齐、
   字号 16px 防 iOS 聚焦缩放)。实测 390px:scrollWidth == innerWidth、
   零横向溢出。
2026-09-11 20:13:44 +08:00

1352 lines
43 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* HomeDash responsive presentation layer.
Loaded after Dashy's bundled styles; persistent wallpaper rules stay in conf.yml. */
html {
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
/* 禁用移动端/Chromium 对可点击元素注入的蓝色点击闪烁。 */
html[data-theme] *,
html[data-theme] *::before,
html[data-theme] *::after {
-webkit-tap-highlight-color: transparent !important;
}
html[data-theme] body {
/* border-box 让 padding 计入 min-height:否则 min-height:100vh 与
padding-bottom 相加,短页面(极简/工作空间)必然多出一屏滚动。 */
box-sizing: border-box !important;
min-width: 0;
overflow-x: hidden;
/* 列向 flex + 页脚 margin-top:auto,把备案号顶到页面底部而非浮在中间。 */
display: flex !important;
flex-direction: column !important;
min-height: 100vh !important;
/* 备案号占据真正的页面最底部;悬浮控件在它上方,不再用底部 padding
把页脚整体抬高。 */
padding-bottom: 0 !important;
}
html[data-theme] #app {
width: 100% !important;
}
/* Dashy 的 #dashy 默认 min-height:100vh,短页面叠加页脚后必出滚动;
交回内容自然撑高,视口高度由 body 兜住。 */
html[data-theme] #dashy {
min-height: auto !important;
}
/* Dashy's native filter/settings strip duplicates the portal search and breaks on phones.
原生设置入口(齿轮/铅笔/调色板)与我们的 /admin/ 重复,统一隐藏。 */
html[data-theme] .home > .settings-outer,
html[data-theme] .config-launcher,
html[data-theme] .options-trigger,
html[data-theme] .settings-outer,
html[data-theme] .minimal-home .title-and-search > form {
display: none !important;
}
html[data-theme] body:has(.modal-overlay) > .navi-search-bar,
html[data-theme] body:has(.modal-overlay) > .navi-footer-host {
visibility: hidden !important;
pointer-events: none !important;
}
/* Keep configuration dialogs above section tabs and cards without changing dialog layout. */
html[data-theme] .modal-overlay {
z-index: 10000 !important;
}
html[data-theme] dialog.dashy-modal {
z-index: 10001 !important;
}
/* Stable icon geometry: raster/SVG and font icons occupy the same visual box. */
html[data-theme] a.item .item-icon {
flex: 0 0 56px !important;
width: 56px !important;
min-width: 56px !important;
height: 56px !important;
min-height: 56px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
overflow: hidden !important;
transform: none !important;
}
html[data-theme] a.item .item-icon .tile-icon,
html[data-theme] a.item .item-icon img,
html[data-theme] a.item .item-icon object {
box-sizing: border-box !important;
width: 48px !important;
min-width: 48px !important;
max-width: 48px !important;
height: 48px !important;
min-height: 48px !important;
max-height: 48px !important;
padding: 2px !important;
object-fit: contain !important;
object-position: center !important;
transform: none !important;
}
html[data-theme] a.item .item-icon i,
html[data-theme] a.item .item-icon svg:not(.tile-icon) {
width: 32px !important;
height: 32px !important;
font-size: 30px !important;
line-height: 32px !important;
}
html[data-theme] a.item .tile-title {
min-width: 0 !important;
overflow: hidden;
}
html[data-theme] a.item .tile-title .text,
html[data-theme] a.item .description,
html[data-theme] a.item .item-url {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ── 渲染开销:把 backdrop-filter 从「重复的卡片层」撤掉 ──
实测首页 37 个元素带模糊(24 张卡片 + 6 个分组容器 + 顶栏 + 悬浮件)。
模糊要对背景逐帧重新采样,而卡片又参与逐张淡入/悬停位移,
两者叠加就是肉眼可见的卡顿。这里保留分组容器的玻璃感与悬浮件,
卡片只留半透明底 + 边框 + 投影(视觉差异很小,开销差很多)。 */
html[data-theme] body a.item,
html[data-theme] body .minimal-section-inner,
html[data-theme] body div.item-wrapper {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
/* 搜索栏是最常动的元素(宽/圆角/内边距都在变),它的模糊每帧都要重算 */
html[data-theme] body .navi-search-bar {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
/* ── 底部搜索:左下角放大镜悬浮球 ──
收起态只显示一个放大镜图标;点它展开成输入框;
展开后输入框内左侧仍是同一个放大镜按钮,点它收起。 */
html[data-theme] .navi-search-bar {
box-sizing: border-box !important;
position: fixed !important;
left: calc(16px + env(safe-area-inset-left, 0px)) !important;
bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important;
margin: 0 !important;
display: flex !important;
align-items: center !important;
gap: 8px !important;
z-index: 900 !important;
color: #475569 !important;
background: rgba(255, 255, 255, .72) !important;
border: 1px solid rgba(255, 255, 255, .9) !important;
box-shadow: 0 14px 38px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .95) !important;
backdrop-filter: blur(22px) saturate(180%) !important;
-webkit-backdrop-filter: blur(22px) saturate(180%) !important;
overflow: hidden !important;
}
html[data-theme] .navi-search-bar[data-state="collapsed"] {
width: 56px !important;
height: 56px !important;
padding: 0 !important;
border-radius: 50% !important;
}
html[data-theme] .navi-search-bar[data-state="open"] {
/* 必须给右下按钮组留位:按钮组 right:16px、宽 52+10+52=114px,
其左边缘在 innerW-130;搜索栏 left:16 → 上限 innerW-130-12-16 = 100%-158px。
否则展开后发送按钮会压在视图切换/管理入口上(窄屏尤其明显)。 */
width: min(560px, calc(100% - 158px)) !important;
min-height: 58px !important;
padding: 7px 8px !important;
border-radius: 20px !important;
}
html[data-theme] .navi-search-bar[data-state="collapsed"] input,
html[data-theme] .navi-search-bar[data-state="collapsed"] .navi-search-submit {
display: none !important;
}
html[data-theme] .navi-search-toggle {
flex: 0 0 42px !important;
width: 42px !important;
height: 42px !important;
display: grid !important;
place-items: center !important;
padding: 0 !important;
color: #0f172a !important;
background: transparent !important;
border: 0 !important;
border-radius: 50% !important;
cursor: pointer;
appearance: none !important;
-webkit-appearance: none !important;
-webkit-tap-highlight-color: transparent;
transition: transform .28s cubic-bezier(.22, 1, .36, 1) !important;
}
/* 点击与聚焦都不变蓝,只保留轻微缩放反馈。 */
html[data-theme] .navi-search-toggle:hover,
html[data-theme] .navi-search-toggle:focus,
html[data-theme] .navi-search-toggle:active {
color: #0f172a !important;
background: transparent !important;
outline: none !important;
}
@media (hover: hover) {
html[data-theme] .navi-search-toggle:hover {
transform: scale(1.05);
}
}
html[data-theme] .navi-search-toggle:active {
transform: scale(.96);
}
/* ── 右下角按钮组(视图切换 + 管理入口)────
两者放进同一个 fixed 容器,便于在工作空间作为一组收边,
避免各自位移后互相重叠。 */
html[data-theme] .navi-dock {
transition: opacity .2s ease, transform .2s cubic-bezier(.22, 1, .36, 1),
visibility 0s linear 0s !important;
position: fixed !important;
right: calc(16px + env(safe-area-inset-right, 0px)) !important;
bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important;
display: flex !important;
align-items: center !important;
gap: 10px !important;
z-index: 900 !important;
}
html[data-theme] .navi-dock > .navi-admin-entry {
position: static !important;
left: auto !important;
right: auto !important;
top: auto !important;
bottom: auto !important;
}
html[data-theme] .navi-dock > .navi-view-switch {
position: relative !important;
left: auto !important;
right: auto !important;
top: auto !important;
bottom: auto !important;
}
/* 右侧管理入口:Dashy 页面本身没有去 /admin/ 的链接 */
html[data-theme] .navi-admin-entry {
box-sizing: border-box !important;
width: 52px !important;
height: 52px !important;
display: grid !important;
place-items: center !important;
z-index: 900 !important;
color: #334155 !important;
background: rgba(255, 255, 255, .72) !important;
border: 1px solid rgba(255, 255, 255, .9) !important;
border-radius: 50% !important;
box-shadow: 0 14px 38px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .95) !important;
backdrop-filter: blur(22px) saturate(180%) !important;
-webkit-backdrop-filter: blur(22px) saturate(180%) !important;
-webkit-tap-highlight-color: transparent !important;
transition: transform .22s cubic-bezier(.22, 1, .36, 1), background .2s ease !important;
}
html[data-theme] .navi-admin-entry:hover,
html[data-theme] .navi-admin-entry:focus,
html[data-theme] .navi-admin-entry:active {
color: #334155 !important;
background: rgba(255, 255, 255, .94) !important;
outline: none !important;
}
@media (hover: hover) {
html[data-theme] .navi-admin-entry:hover {
transform: translateY(-1px) scale(1.05);
}
}
html[data-theme] .navi-admin-entry:active {
transform: scale(.96);
}
html[data-theme] .navi-admin-entry svg {
width: 22px !important;
height: 22px !important;
}
html[data-theme] body:has(.modal-overlay) > .navi-dock,
html[data-theme] body:has(.modal-overlay) .navi-admin-entry {
visibility: hidden !important;
pointer-events: none !important;
}
/* ── 视图切换:圆形悬浮按钮,紧贴管理入口左侧 ──
原生 .switch-view-buttons 是侧栏底部的方形图标,这里一并隐藏。 */
html[data-theme] nav.side-bar .switch-view-buttons {
display: none !important;
}
html[data-theme] .navi-view-switch {
display: block !important;
}
html[data-theme] .navi-view-toggle {
box-sizing: border-box !important;
width: 52px !important;
height: 52px !important;
display: grid !important;
place-items: center !important;
padding: 0 !important;
color: #334155 !important;
background: rgba(255, 255, 255, .72) !important;
border: 1px solid rgba(255, 255, 255, .9) !important;
border-radius: 50% !important;
box-shadow: 0 14px 38px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .95) !important;
backdrop-filter: blur(22px) saturate(180%) !important;
-webkit-backdrop-filter: blur(22px) saturate(180%) !important;
-webkit-tap-highlight-color: transparent !important;
appearance: none !important;
-webkit-appearance: none !important;
outline: none !important;
cursor: pointer;
transition: transform .22s cubic-bezier(.22, 1, .36, 1), background .2s ease !important;
}
html[data-theme] .navi-view-toggle:hover,
html[data-theme] .navi-view-toggle:focus,
html[data-theme] .navi-view-toggle:active {
color: #334155 !important;
background: rgba(255, 255, 255, .94) !important;
}
@media (hover: hover) {
html[data-theme] .navi-view-toggle:hover {
transform: translateY(-1px) scale(1.05);
}
}
html[data-theme] .navi-view-toggle:active {
transform: scale(.96);
}
html[data-theme] .navi-view-toggle svg {
width: 22px !important;
height: 22px !important;
}
html[data-theme] .navi-view-menu {
position: absolute !important;
right: 0 !important;
bottom: 62px !important;
min-width: 134px !important;
display: flex !important;
flex-direction: column !important;
gap: 2px !important;
padding: 7px !important;
background: rgba(255, 255, 255, .92) !important;
border: 1px solid rgba(255, 255, 255, .95) !important;
border-radius: 16px !important;
box-shadow: 0 18px 40px rgba(15, 23, 42, .18), inset 0 1px 0 rgba(255, 255, 255, .95) !important;
backdrop-filter: blur(20px) saturate(180%) !important;
-webkit-backdrop-filter: blur(20px) saturate(180%) !important;
animation: navi-fade-up .22s cubic-bezier(.22, 1, .36, 1) both;
}
html[data-theme] .navi-view-menu[hidden] {
display: none !important;
}
html[data-theme] .navi-view-option {
padding: 9px 12px !important;
color: #334155 !important;
font-size: 13.5px !important;
text-decoration: none !important;
border-radius: 10px !important;
white-space: nowrap !important;
-webkit-tap-highlight-color: transparent !important;
}
html[data-theme] .navi-view-option:hover,
html[data-theme] .navi-view-option:focus,
html[data-theme] .navi-view-option:active {
color: #0f172a !important;
background: rgba(226, 232, 240, .7) !important;
outline: none !important;
}
html[data-theme] .navi-view-option.is-active {
color: #0f172a !important;
background: rgba(186, 230, 253, .55) !important;
font-weight: 600 !important;
}
html[data-theme] body:has(.modal-overlay) .navi-view-switch {
visibility: hidden !important;
pointer-events: none !important;
}
html[data-theme] .navi-search-bar input {
min-width: 0 !important;
height: 42px !important;
flex: 1 1 auto !important;
padding: 0 4px !important;
color: #0f172a !important;
background: transparent !important;
border: 0 !important;
outline: 0 !important;
box-shadow: none !important;
font: inherit !important;
font-size: 16px !important;
}
html[data-theme] .navi-search-bar input::placeholder {
color: #64748b !important;
opacity: 1;
}
html[data-theme] .navi-search-submit {
flex: 0 0 44px !important;
width: 44px !important;
height: 44px !important;
display: grid !important;
place-items: center !important;
padding: 0 !important;
color: #fff !important;
background: linear-gradient(135deg, #0ea5e9, #2563eb) !important;
border: 0 !important;
border-radius: 14px !important;
box-shadow: 0 8px 20px rgba(37, 99, 235, .28) !important;
cursor: pointer;
-webkit-tap-highlight-color: transparent !important;
outline: none !important;
}
html[data-theme] .navi-search-toggle svg,
html[data-theme] .navi-search-submit svg {
width: 20px;
height: 20px;
}
/* 放大镜与搜索框同步形变:圆环、手柄退场,向左收起箭头进入。 */
html[data-theme] .navi-search-toggle svg {
overflow: visible;
}
html[data-theme] .navi-magnifier-ring,
html[data-theme] .navi-magnifier-handle,
html[data-theme] .navi-collapse-arrow {
transform-box: fill-box;
transform-origin: center;
transition: opacity .22s ease, transform .28s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] .navi-collapse-arrow {
opacity: 0;
transform: translateX(5px) scale(.62);
}
html[data-theme] .navi-search-bar[data-state="open"] .navi-magnifier-ring {
opacity: 0;
transform: translateX(-4px) scale(.28);
}
html[data-theme] .navi-search-bar[data-state="open"] .navi-magnifier-handle {
opacity: 0;
transform: translate(-4px, -4px) rotate(-35deg) scale(.45);
}
html[data-theme] .navi-search-bar[data-state="open"] .navi-collapse-arrow {
opacity: 1;
transform: translateX(0) scale(1);
}
/* Minimal view is the phone/tablet layout used by Dashy. */
html[data-theme] .minimal-home {
box-sizing: border-box !important;
width: min(100% - 24px, 920px) !important;
max-width: 920px !important;
min-height: auto !important;
margin: 0 auto !important;
padding: 28px 0 16px !important;
background: transparent !important;
}
html[data-theme] .minimal-home .title-and-search {
padding: 0 8px !important;
}
/* ── 顶部标题:三个视图统一(同字号/字重/字距/居中)──
此前 /minimal 是 48px 居中,而 / 与 /workspace 是顶栏里 40px 左对齐,
同一个站点的三个视图两套标题样式,很割裂。 */
html[data-theme] #dashy > header {
display: flex !important;
align-items: center !important;
justify-content: center !important;
padding: 10px 12px !important;
}
html[data-theme] #dashy > header .page-titles {
display: block !important;
width: auto !important;
max-width: 100% !important;
margin: 0 auto !important;
text-align: center !important;
}
html[data-theme] #dashy > header .page-titles .text {
display: block !important;
text-align: center !important;
}
html[data-theme] #dashy > header .page-titles .subtitle {
display: block !important;
margin: 6px 0 0 !important;
color: #64748b !important;
font-size: 13.5px !important;
font-weight: 400 !important;
letter-spacing: 0 !important;
text-align: center !important;
}
html[data-theme] #dashy > header .page-titles h1,
html[data-theme] .minimal-home .title-and-search h1 {
max-width: 100%;
margin: 0 !important;
color: #0f172a !important;
font-size: clamp(1.75rem, 4vw, 2.75rem) !important;
font-weight: 700 !important;
line-height: 1.08 !important;
letter-spacing: -.035em !important;
text-align: center !important;
overflow-wrap: anywhere;
}
html[data-theme] .minimal-home > .item-group-container {
box-sizing: border-box !important;
width: 100% !important;
margin: 32px auto 0 !important;
padding: 0 6px !important;
}
html[data-theme] .minimal-headings-wrap {
position: relative;
z-index: 2;
gap: 6px !important;
margin-bottom: 8px !important;
}
html[data-theme] .minimal-headings-row {
gap: 6px !important;
scroll-snap-type: x proximity;
}
/* 滚动行两端用 mask 渐变淡出:此前卡片在滚动行边缘(紧贴两侧 ‹ › 按钮)
被硬切,看起来像"被按钮截断"。用 :has() 关联翻页按钮的 disabled 状态,
已经在尽头的一侧就不淡出,避免"尽头还在渐隐"的错觉。 */
html[data-theme] .minimal-headings-row {
-webkit-mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
}
/* 已到最左:左侧不淡出 */
html[data-theme] .minimal-headings-wrap:has(> .tab-scroll-btn:first-child[disabled]) .minimal-headings-row {
-webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
}
/* 已到最右:右侧不淡出 */
html[data-theme] .minimal-headings-wrap:has(> .tab-scroll-btn:last-child[disabled]) .minimal-headings-row {
-webkit-mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 100%);
mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 100%);
}
/* 两端都到尽头:完全不淡出 */
html[data-theme] .minimal-headings-wrap:has(> .tab-scroll-btn:first-child[disabled]):has(> .tab-scroll-btn:last-child[disabled]) .minimal-headings-row {
-webkit-mask-image: none;
mask-image: none;
}
html[data-theme] .minimal-headings-row .headings {
flex-basis: 132px !important;
min-height: 44px !important;
padding: 8px 12px !important;
border-radius: 14px !important;
scroll-snap-align: start;
}
html[data-theme] .minimal-headings-row .headings .section-title {
font-size: 15px !important;
line-height: 1.2 !important;
}
html[data-theme] .minimal-headings-wrap .tab-scroll-btn {
min-width: 34px !important;
padding: 0 8px !important;
border-radius: 12px !important;
}
html[data-theme] .minimal-section-inner {
padding: 8px !important;
background: rgba(255, 255, 255, .34) !important;
border: 1px solid rgba(255, 255, 255, .72) !important;
border-radius: 20px !important;
box-shadow: 0 16px 38px rgba(15, 23, 42, .10), inset 0 1px 0 rgba(255, 255, 255, .88) !important;
backdrop-filter: blur(20px) saturate(170%) !important;
-webkit-backdrop-filter: blur(20px) saturate(170%) !important;
}
/* 空分组(非选中分组 / 无条目)不能被渲染成空玻璃条。
Dashy 会把其余分组渲染成 16px 的空 .minimal-section-inner,
一旦给它加了边框和底色就会变成一排“莫名其妙的框”。 */
html[data-theme] .minimal-section-inner:not(:has(a.item)),
html[data-theme] .minimal-section-inner:empty {
display: none !important;
}
html[data-theme] .minimal-widget-wrap:empty {
display: none !important;
}
html[data-theme] .minimal-section-inner .section-items {
gap: 10px !important;
}
html[data-theme] .minimal-section-inner a.item {
box-sizing: border-box !important;
min-height: 82px !important;
margin: 0 !important;
padding: 12px 16px !important;
}
@media (max-width: 599px) {
html[data-theme] .minimal-home {
width: min(100% - 16px, 430px) !important;
padding-top: 22px !important;
}
html[data-theme] #dashy > header .page-titles h1,
html[data-theme] .minimal-home .title-and-search h1 {
font-size: clamp(1.6rem, 8vw, 2.2rem) !important;
}
html[data-theme] .minimal-home > .item-group-container {
margin-top: 26px !important;
padding: 0 !important;
}
html[data-theme] .minimal-headings-row .headings {
flex-basis: 116px !important;
padding: 8px 10px !important;
}
html[data-theme] .minimal-section-inner {
padding: 7px !important;
}
html[data-theme] .minimal-section-inner a.item {
min-height: 78px !important;
padding: 10px 12px !important;
border-radius: 16px !important;
}
html[data-theme] a.item .item-icon {
flex-basis: 52px !important;
width: 52px !important;
min-width: 52px !important;
height: 52px !important;
min-height: 52px !important;
}
html[data-theme] a.item .item-icon .tile-icon,
html[data-theme] a.item .item-icon img,
html[data-theme] a.item .item-icon object {
width: 44px !important;
min-width: 44px !important;
max-width: 44px !important;
height: 44px !important;
min-height: 44px !important;
max-height: 44px !important;
}
/* Keep the screen-level warning inside the phone viewport. */
html[data-theme] .modal-overlay .modal-body {
min-width: 0 !important;
max-width: 100vw !important;
overflow-x: hidden !important;
}
html[data-theme] .modal-overlay .config-tabs {
overflow-x: auto !important;
overscroll-behavior-x: contain;
scrollbar-width: none;
}
html[data-theme] .modal-overlay .config-tabs::-webkit-scrollbar {
display: none;
}
html[data-theme] .modal-overlay .config-tabs > * {
flex: 0 0 auto !important;
}
html[data-theme] .modal-overlay .config-buttons,
html[data-theme] .modal-overlay .config-buttons > * {
min-width: 0 !important;
max-width: 100% !important;
}
html[data-theme] .modal-overlay .config-buttons > p,
html[data-theme] .modal-overlay .config-buttons .warning,
html[data-theme] .modal-overlay .config-buttons .info {
white-space: normal !important;
overflow-wrap: anywhere !important;
}
html[data-theme] .navi-search-bar {
left: calc(10px + env(safe-area-inset-left, 0px)) !important;
bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important;
}
html[data-theme] .navi-search-bar[data-state="collapsed"] {
width: 52px !important;
height: 52px !important;
}
html[data-theme] .navi-search-bar[data-state="open"] {
/* 移动端按钮组 right:10px、宽 48+8+48=104px → 左边缘 innerW-114,
搜索栏 left:10 → 上限 100%-132px */
width: calc(100% - 132px) !important;
min-height: 56px !important;
border-radius: 18px !important;
}
html[data-theme] .navi-admin-entry {
width: 48px !important;
height: 48px !important;
}
html[data-theme] .navi-dock {
right: calc(10px + env(safe-area-inset-right, 0px)) !important;
bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important;
gap: 8px !important;
}
/* 移动端基准 right:10px,露出 14px → 位移 = 自身宽度 - 4px */
html[data-theme][data-navi-view="workspace"] .navi-dock {
transform: translateX(calc(100% - 4px)) !important;
}
html[data-theme] .navi-view-toggle {
width: 48px !important;
height: 48px !important;
}
html[data-theme] .navi-view-toggle svg {
width: 20px !important;
height: 20px !important;
}
html[data-theme] body {
padding-bottom: 0 !important;
}
}
/* 极窄屏(≤380px):输入框展开时右下按钮组整组让位。
预留式收窄在 320px 下只剩 68px 可输入,不可用;搜索是聚焦动作,
此时把两个按钮藏起来(visibility 不受 prefers-reduced-motion 影响,
比 transform 更可靠),搜索栏即可用满宽度。 */
@media (max-width: 380px) {
/* 备案号在这里会换行成两行(实测 390px 高 39px、320px 高 66px),
而按钮固定在 bottom:76px → 实测两者只剩 1px。把按钮上移并收紧凑页脚,
保证仍有 ~20px 间隙。 */
html[data-theme] .navi-search-bar {
bottom: calc(88px + env(safe-area-inset-bottom, 0px)) !important;
}
html[data-theme] .navi-dock {
bottom: calc(88px + env(safe-area-inset-bottom, 0px)) !important;
}
html[data-theme] .navi-footer {
gap: 6px !important;
padding: 8px 16px !important;
}
html[data-theme] .navi-search-bar[data-state="open"] {
width: calc(100% - 40px) !important;
}
html[data-theme] .navi-search-bar[data-state="open"] ~ .navi-dock {
/* visibility 延迟到淡出结束再切,否则瞬间消失、看不到过渡 */
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
transform: translateY(10px) !important;
transition: opacity .2s ease, transform .2s cubic-bezier(.22, 1, .36, 1),
visibility 0s linear .2s !important;
}
}
/* ── 页脚:备案号胶囊 ──
备案号在 /admin/ 里编辑,这里只负责呈现;同时清掉历史上塞在
内联样式里的 margin-bottom:80px(那是给旧的流式搜索栏让位的)。 */
html[data-theme] footer {
margin: 0 !important;
padding: 0 0 8px !important;
background: transparent !important;
}
html[data-theme] footer > div {
margin-bottom: 0 !important;
padding: 0 !important;
}
/* 极简/工作空间视图补的备案号页脚:留在文档流里,靠 body 的 flex
把它顶到页面底部(贴着悬浮搜索栏上方),而不是 fixed 浮在内容中间。 */
html[data-theme] .navi-footer-host {
margin-top: auto !important;
display: flex !important;
justify-content: center !important;
padding: 8px !important;
}
html[data-theme] .navi-footer {
display: flex !important;
flex-wrap: wrap !important;
align-items: center !important;
justify-content: center !important;
gap: 9px !important;
width: fit-content !important;
max-width: min(680px, calc(100% - 24px)) !important;
margin: 14px auto 0 !important;
padding: 9px 18px !important;
color: #64748b !important;
font-size: 12.5px !important;
line-height: 1.4 !important;
background: rgba(255, 255, 255, .55) !important;
border: 1px solid rgba(255, 255, 255, .78) !important;
border-radius: 999px !important;
box-shadow: 0 6px 18px rgba(15, 23, 42, .06), inset 0 1px 0 rgba(255, 255, 255, .92) !important;
backdrop-filter: blur(14px) saturate(170%) !important;
-webkit-backdrop-filter: blur(14px) saturate(170%) !important;
}
html[data-theme] .navi-footer a {
color: #64748b !important;
text-decoration: none !important;
border-bottom: 1px dashed rgba(100, 116, 139, .45) !important;
-webkit-tap-highlight-color: transparent !important;
}
html[data-theme] .navi-footer a:hover,
html[data-theme] .navi-footer a:focus,
html[data-theme] .navi-footer a:active {
color: #64748b !important;
border-bottom-color: rgba(100, 116, 139, .45) !important;
outline: none !important;
}
html[data-theme] .navi-footer-sep {
color: rgba(100, 116, 139, .45) !important;
}
/* ── 工作空间:悬浮控件与备案号收起到屏幕边缘 ──
工作空间中间嵌的是别人的应用,这些常驻控件会遮挡内容。
搜索球收左边缘、右下角按钮组整组收右边缘、备案号收下边缘,
各留 14px 露出;鼠标移入或点击、聚焦时滑出展开。 */
html[data-theme][data-navi-view="workspace"] .navi-search-bar,
html[data-theme][data-navi-view="workspace"] .navi-dock,
html[data-theme][data-navi-view="workspace"] .navi-footer-host {
opacity: .55 !important;
transition: transform .26s cubic-bezier(.22, 1, .36, 1), opacity .26s ease !important;
animation: none !important;
}
/* 基础 left 为 16px、宽 56px → 位移 58px 后恰好露出 14px */
html[data-theme][data-navi-view="workspace"] .navi-search-bar {
transform: translateX(-58px) !important;
}
/* 按钮组整组右移自身宽度减 14px,恰好露出 14px */
html[data-theme][data-navi-view="workspace"] .navi-dock {
/* 基准 right:16px,露出 14px → 位移 = 自身宽度 + 16px - 14px */
transform: translateX(calc(100% + 2px)) !important;
}
html[data-theme][data-navi-view="workspace"] .navi-footer-host {
position: fixed !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
z-index: 880 !important;
padding: 0 !important;
transform: translateY(calc(100% - 13px)) !important;
}
/* 展开:悬停 / 聚焦 / 按下 / 搜索已展开 */
html[data-theme][data-navi-view="workspace"] .navi-search-bar:hover,
html[data-theme][data-navi-view="workspace"] .navi-search-bar:focus-within,
html[data-theme][data-navi-view="workspace"] .navi-search-bar[data-state="open"],
html[data-theme][data-navi-view="workspace"] .navi-dock:hover,
html[data-theme][data-navi-view="workspace"] .navi-dock:focus-within,
html[data-theme][data-navi-view="workspace"] .navi-footer-host:hover,
html[data-theme][data-navi-view="workspace"] .navi-footer-host:focus-within,
/* 触摸/点击展开:第一次交互只滑出,第二次才触发(见 navi.js 的 peek guard) */
html[data-navi-view="workspace"].navi-peek-open .navi-search-bar,
html[data-navi-view="workspace"].navi-peek-open .navi-dock,
html[data-navi-view="workspace"].navi-peek-open .navi-footer-host {
opacity: 1 !important;
transform: translateX(0) translateY(0) !important;
}
/* ── 工作空间:点侧栏应用 → 在中间内嵌打开网页 ──
Dashy 的面板就是 iframe,我们只是让它在文档流里正常显示、并且只在
「可内嵌」时显示;被拒绝时改为明确提示,而不是一片空白。
用正常文档流(而不是 fixed 钉在视口中间),否则会把页面切成
「顶栏 / 大方块 / 底部」三段,看起来上下都被截断。 */
html[data-theme] .work-space {
height: auto !important;
min-height: 0 !important;
}
html[data-theme] .work-space .multi-taking-view,
html[data-theme] .work-space .workspace-widget-view {
display: none !important;
}
/* iframe 面板与提示卡共用同一块位置,切换状态时布局不跳动 */
html[data-theme] .work-space .web-content,
html[data-theme] .work-space .navi-ws-notice {
box-sizing: border-box !important;
position: static !important;
display: none !important;
width: auto !important;
height: min(72vh, 720px) !important;
min-height: 300px !important;
margin: 18px 18px 14px 72px !important;
border: 1px solid rgba(255, 255, 255, .85) !important;
border-radius: 20px !important;
box-shadow: 0 18px 44px rgba(15, 23, 42, .14), inset 0 1px 0 rgba(255, 255, 255, .92) !important;
overflow: hidden !important;
z-index: 1 !important;
}
html[data-theme] .work-space .web-content {
padding: 0 !important;
background: #fff !important;
}
html[data-theme] .work-space[data-navi-ws="frame"] .web-content {
display: block !important;
margin-top: 8px !important;
}
/* 面板工具条:常驻退路(刷新 / 在新标签页打开),只在内嵌态出现 */
html[data-theme] .navi-ws-bar {
display: none !important;
}
html[data-theme] .work-space[data-navi-ws="frame"] .navi-ws-bar {
box-sizing: border-box !important;
position: static !important;
display: flex !important;
align-items: center !important;
gap: 10px !important;
min-height: 40px !important;
margin: 18px 18px 0 72px !important;
padding: 5px 6px 5px 16px !important;
background: rgba(255, 255, 255, .55) !important;
border: 1px solid rgba(255, 255, 255, .82) !important;
border-radius: 999px !important;
box-shadow: 0 10px 26px rgba(15, 23, 42, .1), inset 0 1px 0 rgba(255, 255, 255, .92) !important;
backdrop-filter: blur(16px) saturate(180%) !important;
-webkit-backdrop-filter: blur(16px) saturate(180%) !important;
}
html[data-theme] .navi-ws-bar-host {
color: #0f172a !important;
font-size: 13.5px !important;
font-weight: 600 !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
html[data-theme] .navi-ws-bar-note {
color: #94a3b8 !important;
font-size: 12.5px !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
html[data-theme] .navi-ws-bar-spacer {
flex: 1 1 auto !important;
}
html[data-theme] .navi-ws-bar-btn {
flex: 0 0 auto !important;
padding: 6px 13px !important;
color: #334155 !important;
font-family: inherit !important;
font-size: 12.5px !important;
background: rgba(255, 255, 255, .72) !important;
border: 1px solid rgba(255, 255, 255, .9) !important;
border-radius: 999px !important;
cursor: pointer;
-webkit-tap-highlight-color: transparent !important;
outline: none !important;
}
html[data-theme] .navi-ws-bar-btn:hover,
html[data-theme] .navi-ws-bar-btn:focus,
html[data-theme] .navi-ws-bar-btn:active {
color: #0f172a !important;
background: rgba(255, 255, 255, .95) !important;
}
html[data-theme] .work-space .web-content iframe {
/* 必须是 static:Dashy 默认 absolute,包含块是 #dashy 而不是 .web-content,
于是 .web-content 的 overflow:hidden 拦不住它,iframe 会按 #dashy 的高度
撑高整页(实测多出 77px 纵向滚动)。 */
position: static !important;
display: block !important;
width: 100% !important;
height: 100% !important;
border: 0 !important;
background: #fff !important;
}
html[data-theme] .work-space[data-navi-ws="hint"] .navi-ws-notice,
html[data-theme] .work-space[data-navi-ws="loading"] .navi-ws-notice,
html[data-theme] .work-space[data-navi-ws="blocked"] .navi-ws-notice {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
gap: 10px !important;
padding: 24px !important;
text-align: center !important;
background: rgba(255, 255, 255, .55) !important;
backdrop-filter: blur(18px) saturate(180%) !important;
-webkit-backdrop-filter: blur(18px) saturate(180%) !important;
}
html[data-theme] .navi-ws-notice-title {
color: #0f172a !important;
font-size: 16px !important;
font-weight: 650 !important;
}
html[data-theme] .navi-ws-notice-text {
color: #64748b !important;
font-size: 13.5px !important;
}
html[data-theme] .navi-ws-notice-url {
max-width: 80% !important;
color: #94a3b8 !important;
font-size: 12.5px !important;
word-break: break-all !important;
}
/* ── 「不支持在工作区显示」弹层 ──
被拒内嵌时不能只是面板里一行字:用户点了必须有明确反馈。
z-index 低于 Dashy 自己的配置弹层(10000),避免挡住它。 */
html[data-theme] .navi-ws-modal {
position: fixed !important;
inset: 0 !important;
z-index: 9990 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
padding: 18px !important;
background: rgba(15, 23, 42, .28) !important;
backdrop-filter: blur(4px) !important;
-webkit-backdrop-filter: blur(4px) !important;
animation: navi-fade-in .18s ease both;
}
html[data-theme] .navi-ws-modal.closing {
opacity: 0 !important;
transition: opacity .16s ease !important;
}
html[data-theme] .navi-ws-modal.closing .navi-ws-modal-card {
transform: translateY(8px) scale(.98) !important;
transition: transform .16s ease !important;
}
html[data-theme] .navi-ws-modal-card {
box-sizing: border-box !important;
width: min(420px, 100%) !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 8px !important;
padding: 24px 22px 20px !important;
text-align: center !important;
background: rgba(255, 255, 255, .96) !important;
border: 1px solid rgba(255, 255, 255, .9) !important;
border-radius: 20px !important;
box-shadow: 0 26px 60px rgba(15, 23, 42, .28), inset 0 1px 0 rgba(255, 255, 255, .95) !important;
animation: navi-fade-up .22s cubic-bezier(.22, 1, .36, 1) both;
}
html[data-theme] .navi-ws-modal-title {
color: #0f172a !important;
font-size: 17px !important;
font-weight: 650 !important;
}
html[data-theme] .navi-ws-modal-host {
color: #0284c7 !important;
font-size: 13px !important;
word-break: break-all !important;
}
html[data-theme] .navi-ws-modal-text {
color: #64748b !important;
font-size: 13.5px !important;
line-height: 1.5 !important;
}
html[data-theme] .navi-ws-modal-actions {
display: flex !important;
flex-wrap: wrap !important;
gap: 10px !important;
justify-content: center !important;
margin-top: 10px !important;
}
html[data-theme] .navi-ws-modal-ok {
padding: 9px 18px !important;
color: #334155 !important;
font-family: inherit !important;
font-size: 13.5px !important;
background: rgba(241, 245, 249, .95) !important;
border: 1px solid rgba(203, 213, 225, .9) !important;
border-radius: 999px !important;
cursor: pointer;
-webkit-tap-highlight-color: transparent !important;
outline: none !important;
}
html[data-theme] .navi-ws-modal-ok:hover,
html[data-theme] .navi-ws-modal-ok:focus {
color: #0f172a !important;
background: rgba(255, 255, 255, .98) !important;
}
html[data-theme] .navi-ws-open {
margin-top: 6px !important;
padding: 9px 18px !important;
color: #fff !important;
font-family: inherit !important;
font-size: 13.5px !important;
background: linear-gradient(135deg, #0ea5e9, #2563eb) !important;
border: 0 !important;
border-radius: 999px !important;
box-shadow: 0 10px 24px rgba(37, 99, 235, .28) !important;
-webkit-tap-highlight-color: transparent !important;
outline: none !important;
cursor: pointer;
}
/* ── 工作空间:侧栏与内容区同样走玻璃圆角 ── */
html[data-theme] nav.side-bar {
background: rgba(255, 255, 255, .62) !important;
border-right: 1px solid rgba(255, 255, 255, .6) !important;
backdrop-filter: blur(18px) saturate(180%) !important;
-webkit-backdrop-filter: blur(18px) saturate(180%) !important;
}
html[data-theme] nav.side-bar .side-bar-section {
padding: 2px !important;
}
html[data-theme] nav.side-bar .side-bar-item {
border-radius: 12px !important;
transition: background .2s ease !important;
}
html[data-theme] nav.side-bar .side-bar-item:hover {
background: rgba(255, 255, 255, .92) !important;
}
/* ── 动效 ──
只动 transform / opacity,不触发布局;时长 180–380ms,
缓动统一 cubic-bezier(.22,1,.36,1)(快速起步、平稳收尾)。 */
@keyframes navi-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes navi-fade-up {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes navi-bar-in {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
html[data-theme] html,
html[data-theme] body {
scroll-behavior: smooth;
}
/* 视图切换:主内容与选中分组淡入 */
html[data-theme] #dashy > *,
html[data-theme] .minimal-section-inner.selected,
html[data-theme] .work-space {
animation: navi-fade-in .3s cubic-bezier(.22, 1, .36, 1) both;
}
/* 悬浮搜索栏:从下侧滑入 */
html[data-theme] .navi-search-bar {
animation: navi-bar-in .36s cubic-bezier(.22, 1, .36, 1) both;
transition: box-shadow .24s ease, border-color .24s ease, background .24s ease,
width .28s cubic-bezier(.22, 1, .36, 1), border-radius .28s ease !important;
}
html[data-theme] .navi-admin-entry {
animation: navi-fade-in .42s ease both;
}
html[data-theme] .navi-search-submit {
transition: transform .2s cubic-bezier(.22, 1, .36, 1), box-shadow .2s ease, filter .2s ease !important;
}
html[data-theme] .navi-search-submit:hover {
filter: brightness(1.06);
transform: translateY(-1px) scale(1.04);
box-shadow: 0 12px 26px rgba(37, 99, 235, .34) !important;
}
html[data-theme] .navi-search-submit:focus,
html[data-theme] .navi-search-submit:active {
outline: none !important;
}
html[data-theme] .navi-search-submit:active {
transform: translateY(0) scale(.96);
}
html[data-theme] .navi-footer-host {
animation: navi-fade-in .42s ease both;
}
/* 卡片逐个淡入:只作用在内容层,避免和 masonry 布局的位移冲突 */
html[data-theme] div.collapsible-content .item-wrapper,
html[data-theme] .minimal-section-inner .item-wrapper {
animation: navi-fade-up .34s cubic-bezier(.22, 1, .36, 1) both;
}
html[data-theme] .item-wrapper:nth-child(1) { animation-delay: 0ms; }
html[data-theme] .item-wrapper:nth-child(2) { animation-delay: 30ms; }
html[data-theme] .item-wrapper:nth-child(3) { animation-delay: 60ms; }
html[data-theme] .item-wrapper:nth-child(4) { animation-delay: 90ms; }
html[data-theme] .item-wrapper:nth-child(5) { animation-delay: 120ms; }
html[data-theme] .item-wrapper:nth-child(6) { animation-delay: 150ms; }
html[data-theme] .item-wrapper:nth-child(n+7) { animation-delay: 180ms; }
/* 分组容器:悬停轻微上浮 */
html[data-theme] div.collapsable {
transition: box-shadow .26s ease, border-color .26s ease, transform .26s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] div.collapsable:hover {
transform: translateY(-2px);
border-color: rgba(147, 197, 253, .6) !important;
box-shadow: 0 18px 40px rgba(15, 23, 42, .12), inset 0 1px 0 rgba(255, 255, 255, .9) !important;
}
html[data-theme] div.collapsable h2,
html[data-theme] .minimal-headings-row .headings {
transition: background .22s ease, color .22s ease, transform .22s cubic-bezier(.22, 1, .36, 1), border-color .22s ease !important;
}
html[data-theme] .minimal-headings-row .headings:hover {
transform: translateY(-1px);
border-color: rgba(147, 197, 253, .75) !important;
}
html[data-theme] .minimal-headings-row .headings:active {
transform: scale(.975);
}
html[data-theme] .minimal-headings-wrap .tab-scroll-btn {
transition: background .2s ease, color .2s ease, transform .2s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] .minimal-headings-wrap .tab-scroll-btn:hover:not([disabled]) {
transform: scale(1.06);
}
html[data-theme] a.item:active {
transform: translateY(-1px) scale(.99) !important;
}
html[data-theme] a.item .item-icon img,
html[data-theme] a.item .item-icon svg {
transition: transform .26s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] nav.side-bar .side-bar-item {
transition: background .2s ease, transform .2s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] nav.side-bar .side-bar-item:hover {
transform: scale(1.06);
}
html[data-theme] .navi-footer a {
transition: color .2s ease, border-color .2s ease !important;
}
@media (prefers-reduced-motion: reduce) {
html[data-theme] html,
html[data-theme] body {
scroll-behavior: auto !important;
}
html[data-theme] #dashy > *,
html[data-theme] .minimal-section-inner.selected,
html[data-theme] .work-space,
html[data-theme] .navi-search-bar,
html[data-theme] .navi-admin-entry,
html[data-theme] .navi-footer-host,
html[data-theme] div.collapsible-content .item-wrapper,
html[data-theme] .minimal-section-inner .item-wrapper {
animation: none !important;
opacity: 1 !important;
transform: none !important;
}
html[data-theme] a.item,
html[data-theme] a.item .tile-icon {
transition: none !important;
}
html[data-theme] a.item:hover,
html[data-theme] div.collapsable:hover,
html[data-theme] nav.side-bar .side-bar-item:hover,
html[data-theme] .minimal-headings-row .headings:hover {
transform: none !important;
}
}