:root { --bg: #14161a; --bg-soft: #181b20; --bg-card: #1c2027; --line: #2a2f38; --accent: #6ea8fe; --accent-bright: #9cc2ff; --text: #dfe4ec; --text-dim: #8b94a3; --green: #3fb96f; --danger: #d9534f; --amber: #d69e2e; --titlebar-start: #171b26; --titlebar-end: #12141c; --active-text: #0d1420; --hover-bg: rgba(255,255,255,0.06); --hover-strong: rgba(255,255,255,0.09); --input-bg: rgba(255,255,255,0.06); --disabled-bg: #2a2f38; --card-hover-line: #3a4350; --quote-bg: rgba(255,255,255,0.035); --quote-line: #4d5868; --modal-overlay: rgba(0,0,0,0.6); --scrollbar: #2a2f38; --scrollbar-hover: #3a4150; } :root[data-ui-theme="light"] { --bg: #f4f7fb; --bg-soft: #ffffff; --bg-card: #ffffff; --line: #d7dee9; --accent: #2563eb; --accent-bright: #1d4ed8; --text: #1f2937; --text-dim: #64748b; --green: #35ad69; --danger: #c93f3a; --amber: #a96c0c; --titlebar-start: #ffffff; --titlebar-end: #f2f5fa; --active-text: #ffffff; --hover-bg: rgba(15,23,42,0.055); --hover-strong: rgba(15,23,42,0.09); --input-bg: #f7f9fc; --disabled-bg: #e7ebf1; --card-hover-line: #9fb0c7; --quote-bg: #f7f9fc; --quote-line: #b2bfd0; --modal-overlay: rgba(15,23,42,0.36); --scrollbar: #c7d0dd; --scrollbar-hover: #aab6c7; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: "Microsoft YaHei", "PingFang SC", -apple-system, "Segoe UI", sans-serif; background: var(--bg); color: var(--text); height: 100vh; overflow: hidden; display: flex; flex-direction: column; } .hidden { display: none !important; } /* 标题栏 */ .titlebar { height: 44px; background: linear-gradient(135deg, var(--titlebar-start), var(--titlebar-end)); display: flex; align-items: center; padding: 0 8px 0 16px; -webkit-app-region: drag; border-bottom: 1px solid var(--line); flex-shrink: 0; } .titlebar-left { flex-shrink: 0; margin-right: 24px; } .brand { display: flex; align-items: center; gap: 7px; font-size: 15px; font-weight: 700; color: var(--accent-bright); letter-spacing: 0.5px; } .brand-logo { width: 25px; height: 25px; border-radius: 6px; object-fit: contain; } .brand-logo-light { display: none; } :root[data-ui-theme="light"] .brand-logo-dark { display: none; } :root[data-ui-theme="light"] .brand-logo-light { display: block; } .brand-sub { color: var(--text-dim); font-weight: 400; font-size: 12px; } .tabs { display: flex; gap: 4px; -webkit-app-region: no-drag; } .tab { height: 30px; padding: 0 18px; background: transparent; border: none; color: var(--text-dim); font-size: 14px; cursor: pointer; border-radius: 8px; } .tab:hover { color: var(--text); background: var(--hover-bg); } .tab.active { color: var(--active-text); background: var(--accent); font-weight: 600; } .titlebar-spacer { flex: 1; } .titlebar-controls { display: flex; gap: 2px; -webkit-app-region: no-drag; flex-shrink: 0; } .win-btn { display: flex; align-items: center; justify-content: center; width: 40px; height: 30px; background: transparent; border: none; border-radius: 6px; color: var(--text-dim); font-size: 14px; cursor: pointer; } .win-btn:hover { background: var(--hover-strong); color: var(--text); } .win-close:hover { background: var(--danger); color: #fff; } .task-center-wrap { position: relative; } .task-center-btn { position: relative; } .task-center-badge { position: absolute; top: 1px; right: 1px; min-width: 15px; height: 15px; padding: 0 4px; border: 1px solid var(--titlebar-start); border-radius: 8px; background: var(--accent); color: var(--active-text); font-size: 9px; font-weight: 700; line-height: 13px; text-align: center; } .task-center-badge.has-result { background: var(--green); color: #07130b; } .task-center-panel { position: absolute; top: 37px; right: -210px; z-index: 50; width: min(390px, calc(100vw - 20px)); max-height: min(560px, calc(100vh - 58px)); display: flex; flex-direction: column; overflow: hidden; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 18px 46px rgba(0,0,0,0.32); -webkit-app-region: no-drag; } .task-center-head { display: flex; align-items: center; gap: 12px; padding: 14px 15px 12px; border-bottom: 1px solid var(--line); } .task-center-head > div { min-width: 0; flex: 1; } .task-center-title { color: var(--text); font-size: 14px; font-weight: 700; } .task-center-summary { margin-top: 3px; overflow: hidden; color: var(--text-dim); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; } .task-center-clear { flex: none; padding: 4px; background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 11px; } .task-center-clear:hover { color: var(--text); } .task-center-list { min-height: 76px; overflow-y: auto; padding: 7px; } .task-center-empty { padding: 26px 12px; color: var(--text-dim); font-size: 12px; text-align: center; } .task-center-item { padding: 10px; border-radius: 8px; border-left: 3px solid transparent; } .task-center-item:hover { background: var(--hover-bg); } .task-center-item.complete { border-left-color: var(--green); } .task-center-item.paused { border-left-color: var(--amber); } .task-center-item.failed { border-left-color: var(--danger); } .task-center-item-head, .task-center-item-foot { display: flex; align-items: center; gap: 10px; min-width: 0; } .task-center-name { min-width: 0; flex: 1; overflow: hidden; color: var(--text); font-size: 12px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; } .task-center-state { flex: none; color: var(--text-dim); font-size: 10px; } .task-center-item.complete .task-center-state { color: var(--green); } .task-center-item.paused .task-center-state { color: var(--amber); } .task-center-item.failed .task-center-state { color: var(--danger); } .task-center-book { margin-top: 2px; overflow: hidden; color: var(--text-dim); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; } .task-center-progress { position: relative; height: 4px; margin: 8px 0 6px; overflow: hidden; border-radius: 3px; background: var(--hover-strong); } .task-center-progress-fill { height: 100%; background: var(--accent); border-radius: inherit; transition: width 0.12s linear; } .task-center-item.complete .task-center-progress-fill { background: var(--green); } .task-center-item.paused .task-center-progress-fill { background: var(--amber); } .task-center-item.failed .task-center-progress-fill { background: var(--danger); } .task-center-progress.indeterminate .task-center-progress-fill { width: 32% !important; animation: dl-progress-slide 1s ease-in-out infinite; } .task-center-status { min-width: 0; flex: 1; overflow: hidden; color: var(--text-dim); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; } .task-center-item.failed .task-center-status { color: var(--danger); } .task-center-actions { display: flex; flex: none; gap: 7px; } .task-center-actions button { padding: 0; background: none; border: none; color: var(--accent-bright); cursor: pointer; font-size: 10px; } .task-center-actions button:hover { text-decoration: underline; } .task-center-actions button[data-task-action="delete"] { color: var(--danger); } .titlebar-icon { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; } .ui-theme-moon { display: none; } :root[data-ui-theme="light"] .ui-theme-sun { display: none; } :root[data-ui-theme="light"] .ui-theme-moon { display: block; } /* 主区 */ #main { flex: 1; overflow-y: auto; padding: 20px; } .tab-panel { min-height: 100%; } /* 工具栏 */ .toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; } .toolbar .status-bar { margin: 0; flex: 1; } .spacer { flex: 1; } .tb-btn { height: 30px; padding: 0 16px; background: var(--accent); color: var(--active-text); border: none; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; } .tb-btn:hover { background: var(--accent-bright); } .tb-btn.ghost { background: transparent; color: var(--text-dim); border: 1px solid var(--line); } .tb-btn.ghost:hover { color: var(--text); border-color: var(--accent); } .tb-btn:disabled { opacity: 0.4; cursor: not-allowed; } .tb-btn.in-lib { background: var(--disabled-bg); color: var(--text-dim); } .tb-btn.sm { height: 24px; padding: 0 10px; font-size: 12px; } .tb-btn.danger { background: transparent; color: var(--danger); border: 1px solid var(--danger); } .tb-btn.danger:hover { background: var(--danger); color: #fff; } .status-bar { color: var(--text-dim); font-size: 13px; min-height: 18px; } /* 浏览页头部常驻 */ .browse-head { position: sticky; top: -20px; z-index: 6; margin: -20px -20px 0; padding: 20px 20px 14px; background: linear-gradient(to bottom, var(--bg) 62%, transparent); } .browse-head .toolbar { margin-bottom: 0; } .browse-head .status-bar { margin: 0; min-height: 0; } .browse-head .status-bar:not(:empty) { margin-top: 8px; } #browseGridView { min-height: calc(100vh - 84px); display: flex; flex-direction: column; } .source-select { height: 30px; padding: 0 12px; background: var(--bg-soft); color: var(--text); border: 1px solid var(--line); border-radius: 8px; font-size: 13px; cursor: pointer; outline: none; } .search-inline { display: flex; align-items: center; gap: 8px; } #searchInput { width: 300px; height: 30px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 8px; padding: 0 14px; color: var(--text); font-size: 13px; outline: none; } #searchInput:focus { border-color: var(--accent); } /* 卡片网格 */ .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 16px; } .card { cursor: pointer; } /* 封面比例五花八门(生成的是 4:5,书源的常见 0.65~0.75,还有方图和横图)。 用 cover 铺满会按各自比例裁掉不同的边,同一套封面看上去缩放程度不一。 改成 contain 让整张封面完整显示:模糊放大的同一张图由 ::before 垫在**底层** 填掉留白。注意 ::before 会盖在父元素自己的背景之上,所以清晰的那层必须画在 ::after 里,只靠 z-index 调不动父元素背景的层级。 */ .card-cover { position: relative; width: 100%; aspect-ratio: 3/4; background: var(--bg-card) center/contain no-repeat; border: 1px solid var(--line); border-radius: 10px; display: flex; align-items: center; justify-content: center; padding: 10px; text-align: center; overflow: hidden; transition: transform 0.15s, border-color 0.15s; } .card-cover[data-cover-state="ready"]::before, .card-cover[data-cover-state="ready"]::after { content: ""; position: absolute; inset: 0; background-image: inherit; background-repeat: no-repeat; background-position: center; pointer-events: none; } .card-cover[data-cover-state="ready"]::before { z-index: 0; background-size: cover; filter: blur(12px) brightness(0.5); transform: scale(1.15); } .card-cover[data-cover-state="ready"]::after { z-index: 1; background-size: contain; } /* 占位文字与角标必须浮在两层背景之上 */ .card-cover > * { position: relative; z-index: 2; } .card-cover.readable { cursor: pointer; } .card-cover.readable:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } .card:hover .card-cover:not([data-cover-state="pending"]) { transform: translateY(-3px); border-color: var(--accent); } .card:hover .card-cover[data-cover-state="pending"] { border-color: var(--accent); } .card-cover .ph { color: var(--text-dim); font-size: 12px; line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; } .card-title { margin-top: 8px; font-size: 13px; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .card-sub { margin-top: 2px; font-size: 11px; color: var(--text-dim); display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; } .card-date { margin-top: 2px; font-size: 11px; color: var(--text-dim); } /* 状态与笔记标识叠在封面右下角,不再占用封面下方的一行。 封面图案深浅不可控,故用不透明衬底而非半透明色块保证可读性 */ .card-cover-badges { position: absolute; bottom: 6px; display: flex; gap: 4px; max-width: calc(50% - 8px); pointer-events: none; } .card-cover-badges.start { left: 6px; } .card-cover-badges.end { right: 6px; justify-content: flex-end; } .card-badge { padding: 1px 7px; font-size: 10px; line-height: 1.6; border-radius: 10px; white-space: nowrap; background: var(--bg-card); color: var(--green); border: 1px solid rgba(63,185,111,0.45); box-shadow: 0 1px 3px rgba(0,0,0,0.35); } .card-badge.miss { color: var(--danger); border-color: rgba(217,83,79,0.5); } .empty { grid-column: 1 / -1; text-align: center; color: var(--text-dim); padding: 60px 0; } /* 聚合搜索:按源分组 */ .agg-list { display: flex; flex-direction: column; gap: 22px; } .agg-list .empty { grid-column: auto; } .agg-group { border-top: 1px solid var(--line); padding-top: 12px; } .agg-group:first-child { border-top: none; padding-top: 0; } .agg-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; } .agg-name { font-size: 14px; font-weight: 600; color: var(--text); } .agg-count { font-size: 12px; color: var(--text-dim); } .agg-count.err { color: var(--danger); } .agg-more { margin-left: auto; } .agg-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } .agg-loading, .agg-msg { font-size: 12px; color: var(--text-dim); padding: 6px 0; } .agg-err { color: var(--danger); } .agg-group.agg-empty, .agg-group.agg-failed { opacity: 0.55; } /* 分页 */ .pager { display: flex; justify-content: center; align-items: center; gap: 20px; position: sticky; bottom: -20px; margin: auto -20px -20px; padding: 14px 20px 20px; background: linear-gradient(to top, var(--bg) 62%, transparent); z-index: 5; } .page-btn { padding: 8px 20px; background: var(--bg-soft); border: 1px solid var(--line); color: var(--text); border-radius: 8px; cursor: pointer; font-size: 13px; } .page-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-bright); } .page-btn:disabled { opacity: 0.4; cursor: not-allowed; } .page-info { color: var(--text-dim); font-size: 13px; } .page-jump { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 13px; } .jump-input { width: 64px; padding: 7px 8px; background: var(--bg-soft); border: 1px solid var(--line); color: var(--text); border-radius: 8px; font-size: 13px; text-align: center; } .jump-input:focus { outline: none; border-color: var(--accent); } .jump-input::-webkit-outer-spin-button, .jump-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } /* 详情 */ .back-btn { margin-bottom: 14px; height: 30px; padding: 0 14px; background: transparent; color: var(--text-dim); border: 1px solid var(--line); border-radius: 8px; font-size: 13px; cursor: pointer; } .back-btn:hover { color: var(--text); border-color: var(--accent); } .detail-head { display: flex; gap: 20px; margin-bottom: 20px; } .detail-cover { width: 150px; height: 200px; flex-shrink: 0; background: var(--bg-card) center/cover no-repeat; border: 1px solid var(--line); border-radius: 10px; display: flex; align-items: center; justify-content: center; padding: 12px; text-align: center; } .detail-cover .ph { color: var(--text-dim); font-size: 12px; line-height: 1.5; } .detail-meta { flex: 1; min-width: 0; } .detail-title { font-size: 20px; font-weight: 700; line-height: 1.4; margin-bottom: 8px; } .detail-authors { color: var(--accent-bright); font-size: 13px; margin-bottom: 10px; } .meta-row { font-size: 13px; color: var(--text-dim); margin-bottom: 6px; } .meta-row b { color: var(--text); font-weight: 600; margin-right: 8px; } .meta-row a { color: var(--accent); text-decoration: none; word-break: break-all; } .meta-row a:hover { text-decoration: underline; } .add-lib-btn { margin-top: 10px; } .add-lib-hint { margin-top: 6px; font-size: 12px; color: var(--text-dim); } .section-title { font-size: 14px; font-weight: 700; color: var(--accent-bright); margin: 18px 0 10px; } .brief-panel { background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px; padding: 14px; font-size: 13px; line-height: 1.7; color: var(--text-dim); max-height: 220px; overflow-y: auto; } /* 下载区 */ .download-box { display: flex; flex-direction: column; gap: 10px; } .dl-loading, .dl-error { color: var(--text-dim); font-size: 13px; padding: 10px 0; } .dl-error { color: var(--danger); } .retry-btn { margin-left: 10px; background: none; border: none; color: var(--accent); cursor: pointer; font-size: 13px; } .dl-files { display: flex; flex-direction: column; gap: 6px; } .dl-panel-name { font-size: 13px; color: var(--text-dim); margin-bottom: 4px; } .dl-file-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; } .dl-file-name { flex: 1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .dl-fmt { font-size: 11px; color: var(--accent); border: 1px solid var(--accent); border-radius: 6px; padding: 0 6px; flex-shrink: 0; } .copy-btn, .dl-btn { height: 24px; padding: 0 10px; flex-shrink: 0; background: transparent; color: var(--text-dim); border: 1px solid var(--line); border-radius: 6px; font-size: 12px; cursor: pointer; } .copy-btn:hover, .dl-btn:hover { color: var(--text); border-color: var(--accent); } .dl-btn { background: var(--accent); color: var(--active-text); border: none; } .dl-btn:hover { background: var(--accent-bright); color: var(--active-text); } .dl-btn.downloaded { background: var(--green); color: #07130b; border: none; font-weight: 600; } .dl-btn.downloaded:hover { background: #61cc88; color: #07130b; } .dl-btn.copied, .copy-btn.copied { color: var(--green); border-color: var(--green); } .dl-progress { order: 10; flex: 1 0 100%; display: flex; align-items: center; gap: 9px; min-width: 0; } .dl-progress-track { position: relative; flex: 1; height: 5px; overflow: hidden; background: var(--hover-strong); border-radius: 4px; } .dl-progress-fill { width: 0; height: 100%; background: var(--accent); border-radius: inherit; transition: width 0.12s linear; } .dl-progress-label { min-width: 130px; color: var(--text-dim); font-size: 10px; text-align: right; white-space: nowrap; } .dl-progress.indeterminate .dl-progress-fill { width: 32%; animation: dl-progress-slide 1s ease-in-out infinite; } .dl-progress.failed .dl-progress-fill { background: var(--danger); } .dl-progress.failed .dl-progress-label { color: var(--danger); } @keyframes dl-progress-slide { from { transform: translateX(-110%); } to { transform: translateX(340%); } } .dl-link-row { display: flex; align-items: center; gap: 10px; font-size: 13px; padding: 4px 0; } .dl-link-row a { color: var(--accent); text-decoration: none; } .dl-link-row a:hover { text-decoration: underline; } /* 书库 */ .lib-card-actions { display: flex; align-items: center; gap: 5px; margin-top: 8px; flex-wrap: wrap; } .lib-card-actions button { flex: 1; height: 26px; font-size: 12px; border-radius: 6px; cursor: pointer; border: 1px solid var(--line); background: transparent; color: var(--text-dim); } .lib-card-actions .icon-action { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 28px; width: 28px; padding: 0; } .lib-card-actions .icon-action svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; } .lib-card-actions button:hover { color: var(--text); border-color: var(--accent); } .lib-card-actions .open-btn { background: var(--accent); color: var(--active-text); border: none; font-weight: 600; } .lib-card-actions .open-btn:hover { background: var(--accent-bright); } .lib-card-actions .open-btn:disabled { background: var(--disabled-bg); color: var(--text-dim); cursor: not-allowed; } .card-badge.note-count { color: var(--accent-bright); border-color: rgba(110,168,254,0.5); } .card-badge.annotation-count { color: var(--amber); border-color: rgba(214,158,46,0.55); } /* 书库多选 */ .library-selection-bar { display: flex; align-items: center; gap: 12px; margin: -6px 0 16px; padding: 8px 12px; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px; } .library-select-all { display: flex; align-items: center; gap: 6px; color: var(--text-dim); font-size: 13px; cursor: pointer; } .tb-btn.ghost.active { color: var(--accent-bright); border-color: var(--accent); } /* 定位上下文不能只在 select-mode 下建立:退出多选是同步移除类名, 而重绘要等 IPC 返回,其间残留的复选框会失去定位祖先, 直接按视口坐标飞到左上角标题上闪一下 */ .card { position: relative; } .card-select { position: absolute; top: 6px; left: 6px; z-index: 2; display: flex; cursor: pointer; } /* 用投影而不是衬底色块保证在浅色封面上也看得见: 加 padding + 背景板会让复选框看起来套了一圈很粗的边框 */ .card-select input { margin: 0; cursor: pointer; filter: drop-shadow(0 0 1px rgba(0,0,0,0.9)) drop-shadow(0 1px 2px rgba(0,0,0,0.55)); } /* 退出多选后重绘要等 IPC 返回,这期间立刻藏掉残留的复选框 */ #libraryTab:not(.select-mode) .card-select { display: none; } #libraryTab.select-mode .card-cover { transition: none; } #libraryTab.select-mode .card:hover .card-cover { transform: none; } #libraryTab.select-mode .card.selected .card-cover { border-color: var(--accent); } #libraryTab.select-mode .card.selected .card-title { color: var(--accent-bright); } .library-bulk-preview { margin: 8px 0 0; padding-left: 20px; color: var(--text-dim); font-size: 13px; line-height: 1.7; } /* 书库组织 */ .library-page { min-height: calc(100vh - 84px); display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 22px; } .library-sidebar { align-self: start; position: sticky; top: 0; max-height: calc(100vh - 84px); min-width: 0; padding: 12px; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 12px; } .library-sidebar-head { display: flex; align-items: center; gap: 8px; padding: 0 4px 8px; } .library-sidebar-head h2 { flex: 1; font-size: 14px; } .library-filter { display: block; width: 100%; min-width: 0; padding: 7px 9px; background: transparent; border: 1px solid transparent; border-radius: 7px; color: var(--text-dim); font: inherit; font-size: 12px; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; } .library-filter:hover { color: var(--text); background: var(--hover-bg); } .library-filter.active { color: var(--accent-bright); background: rgba(110,168,254,0.11); } .library-filter-list { display: flex; flex-direction: column; gap: 1px; } .library-sidebar-section { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); } .library-sidebar-section-head { display: flex; align-items: center; gap: 8px; padding: 0 4px 7px; } .library-sidebar-section-head h3 { flex: 1; } .library-sidebar-section h3 { color: var(--text-dim); font-size: 11px; font-weight: 600; } /* 行内操作按钮绝对定位:留在文档流里会占掉 47px, 使书架和标签的选中高亮比「全部书籍」等静态项窄一截 */ .library-shelf-row, .library-tag-row { position: relative; display: flex; align-items: center; } .library-shelf-row .library-filter, .library-tag-row .library-filter { flex: 1; padding-right: 48px; } .library-shelf-actions, .library-tag-actions { position: absolute; right: 3px; display: flex; opacity: 0; pointer-events: none; } .library-shelf-row:hover .library-shelf-actions, .library-shelf-row:focus-within .library-shelf-actions, .library-tag-row:hover .library-tag-actions, .library-tag-row:focus-within .library-tag-actions { opacity: 1; pointer-events: auto; } .library-shelf-actions .notes-icon-btn, .library-tag-actions .notes-icon-btn { width: 22px; height: 22px; font-size: 12px; } .library-filter-count { float: right; color: var(--text-dim); } .library-content { min-width: 0; } .library-search { display: flex; min-width: min(320px, 100%); align-items: center; gap: 7px; } .library-search input { width: 230px; height: 30px; padding: 0 11px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 8px; color: var(--text); font: inherit; font-size: 12px; outline: none; } .library-search input:focus { border-color: var(--accent); } /* 标签叠在封面顶部右侧:左上角要留给多选复选框 */ .library-card-tags { position: absolute; top: 6px; right: 6px; display: flex; justify-content: flex-end; gap: 4px; max-width: calc(100% - 42px); overflow: hidden; pointer-events: none; } .library-card-tag { min-width: 0; padding: 1px 6px; border-radius: 8px; background: var(--bg-card); border: 1px solid rgba(110,168,254,0.45); color: var(--accent-bright); font-size: 10px; line-height: 1.6; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; box-shadow: 0 1px 3px rgba(0,0,0,0.35); } .library-organize-form { display: flex; flex-direction: column; gap: 12px; } .library-organize-form label { color: var(--text-dim); font-size: 12px; } .library-organize-form select, .library-organize-form input[type="text"] { width: 100%; height: 34px; margin-top: 5px; padding: 0 10px; background: var(--input-bg); color: var(--text); border: 1px solid var(--line); border-radius: 8px; font: inherit; font-size: 13px; outline: none; } .library-organize-form select:focus, .library-organize-form input[type="text"]:focus { border-color: var(--accent); } .library-tag-picker { position: relative; width: 100%; margin-top: 5px; color: var(--text); font-size: 13px; } .library-tag-picker summary { height: 34px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--input-bg); cursor: pointer; list-style-position: inside; } .library-tag-picker[open] summary { border-color: var(--accent); } .library-tag-options { max-height: 190px; margin-top: 4px; overflow-y: auto; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); box-shadow: 0 8px 24px rgba(0,0,0,0.22); } .library-tag-option { display: flex !important; align-items: center; gap: 8px; padding: 8px 10px; color: var(--text) !important; cursor: pointer; } .library-tag-option:hover { background: var(--hover-bg); } .library-tag-option span:nth-child(2) { flex: 1; } .library-tag-empty { padding: 12px; color: var(--text-dim); text-align: center; } .local-import-section { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); } .local-import-label { color: var(--text-dim); font-size: 12px; font-weight: 600; } .local-import-choice { display: flex; align-items: center; gap: 8px; padding: 6px 4px; color: var(--text); cursor: pointer; } .local-import-section input[type="text"] { width: 100%; height: 34px; padding: 0 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--input-bg); color: var(--text); outline: none; } .local-import-section input[type="text"]:focus { border-color: var(--accent); } .about-formats { display: grid; gap: 10px; width: 100%; margin-top: 10px; color: var(--text); line-height: 1.55; } .about-format-label { display: inline-block; min-width: 120px; margin-right: 12px; color: var(--text-dim); font-weight: 600; } /* 我的笔记 */ .notes-page { min-height: calc(100vh - 84px); display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 22px; } .notes-sidebar { align-self: start; position: sticky; top: 0; min-width: 0; padding: 12px; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 12px; } .notes-sidebar-head { display: flex; align-items: center; gap: 8px; padding: 0 4px 8px; } .notes-sidebar-head h2 { flex: 1; font-size: 14px; } .notes-icon-btn { width: 25px; height: 25px; flex: none; background: transparent; border: 1px solid transparent; border-radius: 6px; color: var(--text-dim); cursor: pointer; font-size: 15px; } .notes-icon-btn:hover { color: var(--accent-bright); border-color: var(--line); } .notes-icon-btn.danger:hover { color: var(--danger); } .notes-collection-row { display: flex; align-items: center; gap: 2px; min-width: 0; } .notes-collection { display: block; width: 100%; min-width: 0; padding: 8px 10px; background: transparent; border: none; border-radius: 7px; color: var(--text-dim); cursor: pointer; font-size: 13px; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .notes-collection:hover { background: var(--hover-bg); color: var(--text); } .notes-collection.active { background: rgba(110,168,254,0.14); color: var(--accent-bright); } .notes-collection-actions { display: none; align-items: center; } .notes-collection-row:hover .notes-collection-actions, .notes-collection-row:focus-within .notes-collection-actions { display: flex; } .notes-collection-row .notes-collection { flex: 1; } .notes-content { min-width: 0; } .notes-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } .notes-search { display: flex; align-items: center; gap: 8px; flex: 1; } #notesSearchInput { width: min(480px, 100%); height: 32px; padding: 0 13px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 8px; color: var(--text); font-size: 13px; outline: none; } #notesSearchInput:focus { border-color: var(--accent); } .notes-type-tabs { display: inline-flex; gap: 3px; margin-bottom: 12px; padding: 3px; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 9px; } .notes-type-tab { min-width: 84px; height: 30px; padding: 0 14px; background: transparent; border: 0; border-radius: 7px; color: var(--text-dim); cursor: pointer; font: inherit; font-size: 12px; } .notes-type-tab:hover { color: var(--text); } .notes-type-tab.active { background: var(--accent); color: var(--on-accent, #fff); } .notes-tag-filters { display: flex; align-items: center; gap: 6px; margin: 3px 0 10px; flex-wrap: wrap; } .notes-tags-label { margin-right: 2px; color: var(--text-dim); font-size: 12px; } .notes-content > .status-bar { margin-bottom: 10px; } .notes-list { width: 100%; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 310px), 1fr)); gap: 12px; } .notes-empty { grid-column: 1 / -1; padding: 70px 20px; border: 1px dashed var(--line); border-radius: 12px; color: var(--text-dim); text-align: center; font-size: 13px; } .note-card { display: flex; min-width: 0; min-height: 300px; padding: 16px 18px 12px; flex-direction: column; background: var(--bg-card); border: 1px solid var(--line); border-radius: 12px; } .note-card:hover { border-color: var(--card-hover-line); } .note-card.pinned { border-left: 3px solid var(--accent); } .note-card-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 10px; } .note-title-box { flex: 1; min-width: 0; } .note-book-title { overflow: hidden; color: var(--accent-bright); font-size: 14px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; } .note-book-authors { margin-top: 2px; overflow: hidden; color: var(--text-dim); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; } .note-title { margin-top: 3px; color: var(--text-dim); font-size: 12px; } .note-badges { display: flex; align-items: flex-end; flex-direction: column; gap: 5px; flex: none; } .note-badge { padding: 2px 7px; border-radius: 10px; font-size: 10px; white-space: nowrap; } .note-badge.source { background: var(--input-bg); color: var(--text-dim); } .note-badge.pinned { background: rgba(110,168,254,0.15); color: var(--accent-bright); } .note-badge.type.reading { background: rgba(99, 179, 237, 0.14); color: #63b3ed; } .note-badge.type.canvas { background: rgba(183, 148, 244, 0.16); color: #b794f4; } .note-quote { margin: 8px 0 10px; padding: 8px 11px; background: var(--quote-bg); border-left: 2px solid var(--quote-line); color: var(--text-dim); font-size: 12px; font-style: normal; line-height: 1.65; overflow-wrap: anywhere; white-space: pre-wrap; } .note-text { max-height: 176px; overflow: hidden; color: var(--text); font-size: 13px; line-height: 1.75; overflow-wrap: anywhere; white-space: pre-wrap; } .note-text .rich-note-image img { max-height: 120px; } .rich-note-content { white-space: normal; } .rich-note-content > :first-child { margin-top: 0; } .rich-note-content > :last-child { margin-bottom: 0; } .rich-note-content p, .rich-note-content h2, .rich-note-content h3, .rich-note-content blockquote, .rich-note-content pre, .rich-note-content ul, .rich-note-content ol { margin: 0.45em 0; } .rich-note-content h2 { font-size: 1.35em; } .rich-note-content h3 { font-size: 1.15em; } .rich-note-content blockquote { padding: 7px 10px; background: var(--quote-bg); border-left: 3px solid var(--accent); color: var(--text-dim); } .rich-note-content pre, .rich-note-content code { font-family: Consolas, "Cascadia Mono", monospace; } .rich-note-content pre { overflow-x: auto; padding: 8px 10px; background: var(--input-bg); border-radius: 7px; white-space: pre-wrap; } .rich-note-content ul, .rich-note-content ol { padding-left: 1.6em; } .rich-note-image { position: relative; width: fit-content; max-width: 100%; margin: 10px 0; } .rich-note-image img { display: block; max-width: 100%; max-height: 520px; border: 1px solid var(--line); border-radius: 8px; object-fit: contain; } .note-context { max-height: 86px; margin-top: 9px; padding-top: 8px; overflow: hidden; border-top: 1px dashed var(--line); color: var(--text-dim); font-size: 11px; line-height: 1.55; overflow-wrap: anywhere; white-space: pre-wrap; } .note-tags { display: flex; gap: 5px; margin-top: 10px; flex-wrap: wrap; } .note-tag { padding: 2px 8px; background: rgba(110,168,254,0.08); border: 1px solid rgba(110,168,254,0.2); border-radius: 10px; color: var(--text-dim); cursor: pointer; font-size: 11px; } .note-tag:hover, .note-tag.active { background: rgba(110,168,254,0.2); border-color: rgba(110,168,254,0.45); color: var(--accent-bright); } .note-card-footer { display: flex; align-items: center; gap: 10px; margin-top: 11px; padding-top: 9px; border-top: 1px solid var(--line); margin-top: auto; } .note-meta { flex: 1; min-width: 0; overflow: hidden; color: var(--text-dim); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; } .note-actions { display: flex; gap: 5px; } .note-action { padding: 3px 8px; background: transparent; border: 1px solid transparent; border-radius: 6px; color: var(--text-dim); cursor: pointer; font-size: 11px; } .note-action:hover { border-color: var(--line); color: var(--text); } .note-action.open { color: var(--accent-bright); } .note-action.window { color: var(--accent-bright); } .note-action.delete:hover { color: var(--danger); } .note-edit-form { display: flex; flex-direction: column; gap: 10px; } .note-type-choice-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } .note-type-choice { position: relative; display: flex; min-height: 116px; padding: 16px; flex-direction: column; gap: 6px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 11px; cursor: pointer; } .note-type-choice:has(input:checked) { background: rgba(110,168,254,0.1); border-color: var(--accent); } .note-type-choice input { position: absolute; top: 12px; right: 12px; } .note-type-choice-title { color: var(--text); font-size: 14px; font-weight: 700; } .note-type-choice-desc { color: var(--text-dim); font-size: 12px; line-height: 1.55; } .note-canvas-preview { position: relative; min-height: 132px; margin-top: 2px; padding: 12px; background-color: #fff; border: 1px solid var(--line); border-radius: 8px; color: #445; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.025); } .note-canvas-preview.template-grid { background-image: linear-gradient(#e4eaf1 1px, transparent 1px), linear-gradient(90deg, #e4eaf1 1px, transparent 1px); background-size: 20px 20px; } .note-canvas-preview.template-lined { background-image: linear-gradient(#dce5ef 1px, transparent 1px); background-size: 100% 24px; } .note-canvas-preview.template-dots { background-image: radial-gradient(#cbd5df 1px, transparent 1px); background-size: 18px 18px; } .note-canvas-preview.template-pdf { background: linear-gradient(145deg, #fff 0 68%, #f1f3f6 68% 100%); } .note-edit-form label { color: var(--text-dim); font-size: 12px; min-width: 0; } /* 必须排除 .canvas-note-root 与 .ql-toolbar 内部:画布工具栏和富文本工具栏都是 .note-edit-form 的后代,不加 :not() 的话工具栏里的下拉会被当成表单控件,吃到 margin-top 与 width:100%,表现为工具栏凭空高出 5px、各分组高度对不齐。 */ .note-edit-form textarea:not(.canvas-note-root textarea):not(.ql-toolbar textarea), .note-edit-form select:not(.canvas-note-root select):not(.ql-toolbar select) { width: 100%; margin-top: 5px; padding: 8px 10px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 8px; color: var(--text); font-family: inherit; font-size: 13px; outline: none; resize: vertical; } /* 关联书籍 / 笔记本:书名可以很长,下拉框跟着长到占满整行,与右侧「标题」输入框 宽度悬殊。限宽后仍需 min-width:0,否则 select 的 min-content 以最长选项为准, 照样把整行顶宽。 */ .note-edit-form select:not(.canvas-note-root select):not(.ql-toolbar select) { max-width: 320px; min-width: 0; text-overflow: ellipsis; } .note-edit-form textarea:not(.canvas-note-root textarea):focus, .note-edit-form select:not(.canvas-note-root select):focus { border-color: var(--accent); } .modal-box:has(.quill-note-editor), .modal-box:has(.canvas-note-root) { display: flex; width: 760px; max-height: 92vh; flex-direction: column; } .modal-box:has(.quill-note-editor) .modal-body, .modal-box:has(.canvas-note-root) .modal-body { min-height: 0; } .modal-box:has(.quill-note-editor) .modal-body { overflow-y: auto; } .canvas-note-modal .modal-box { height: 94vh; width: min(1180px, 96vw); max-width: 96vw; max-height: 94vh; padding: 16px; } .canvas-note-modal .modal-body { display: flex; min-height: 0; margin-bottom: 12px; flex: 1; overflow: hidden; } .canvas-note-modal .modal-title, .canvas-note-modal .modal-actions { flex: 0 0 auto; } .canvas-note-modal .canvas-note-form { display: grid; width: 100%; min-height: 0; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: auto minmax(0, 1fr) auto auto; gap: 8px 10px; } .canvas-note-modal .canvas-note-form > label { min-width: 0; } .canvas-note-modal .canvas-note-content { display: flex; min-height: 0; grid-column: 1 / -1; flex-direction: column; } .canvas-note-modal .canvas-note-content-label { color: var(--text-dim); font-size: 12px; } .canvas-note-modal .canvas-note-content > div, .canvas-note-modal .canvas-note-content .mixed-note-editor, .canvas-note-modal .canvas-note-content .mixed-note-canvas { min-height: 0; flex: 1; } .canvas-note-modal .canvas-note-content > div { display: flex; margin-top: 5px; flex-direction: column; } .canvas-note-modal .note-form-error { grid-column: 1 / -1; } @media (max-width: 760px) { .canvas-note-modal .canvas-note-form { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 520px) { .canvas-note-modal .modal-box { height: 98vh; max-height: 98vh; } .canvas-note-modal .canvas-note-form { grid-template-columns: minmax(0, 1fr); } } .rich-note-editor { margin-top: 5px; overflow: hidden; background: var(--input-bg); border: 1px solid var(--line); border-radius: 9px; } .rich-note-editor:focus-within { border-color: var(--accent); } .rich-note-toolbar { display: flex; align-items: center; gap: 4px; padding: 6px; background: var(--bg-soft); border-bottom: 1px solid var(--line); flex-wrap: wrap; } .rich-note-style, .rich-note-tool { height: 28px; background: var(--bg-card); border: 1px solid var(--line); border-radius: 6px; color: var(--text); font: inherit; } .rich-note-style { padding: 0 7px; } .rich-note-tool { min-width: 29px; padding: 0 7px; cursor: pointer; } .rich-note-tool:hover { border-color: var(--accent); color: var(--accent-bright); } .rich-note-tool-bold { font-weight: 700; } .rich-note-tool-italic { font-style: italic; } .rich-note-tool-underline { text-decoration: underline; } .rich-note-tool-strikeThrough { text-decoration: line-through; } .rich-note-surface { min-height: 220px; max-height: 48vh; padding: 12px 14px; overflow-y: auto; color: var(--text); font-size: 13px; line-height: 1.7; outline: none; } .rich-note-surface:empty::before { color: var(--text-muted); content: attr(data-placeholder); pointer-events: none; } .rich-note-surface .rich-note-image { cursor: default; } .rich-note-image-remove { position: absolute; top: 6px; right: 6px; width: 26px; height: 26px; padding: 0; background: rgba(20,20,20,0.78); border: 1px solid rgba(255,255,255,0.35); border-radius: 50%; color: #fff; cursor: pointer; font-size: 18px; line-height: 22px; } .rich-note-image-remove:hover { background: var(--danger); } .note-edit-check { display: flex; align-items: center; gap: 7px; } .note-edit-check input { accent-color: var(--accent); } .note-form-error { min-height: 16px; color: #f66; font-size: 12px; } /* 设置 */ .settings-page { width: 100%; max-width: 900px; } .settings-title { font-size: 20px; margin-bottom: 20px; } .settings-group { background: var(--bg-soft); border: 1px solid var(--line); border-radius: 12px; padding: 6px 18px; margin-bottom: 16px; } .settings-item { display: flex; align-items: center; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--line); } .settings-item:last-child { border-bottom: none; } .settings-item-block { flex-direction: column; align-items: stretch; } .settings-item-info { flex: 1; min-width: 0; } .settings-item-label { font-size: 14px; font-weight: 600; } .settings-item-desc { font-size: 12px; color: var(--text-dim); margin-top: 4px; } .settings-input { width: 240px; min-width: 0; padding: 6px 10px; background: var(--bg-card); border: 1px solid var(--line); color: var(--text); border-radius: 6px; } .ai-form { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; width: 100%; } .ai-row { display: flex; align-items: center; gap: 10px; } .ai-form > label.ai-row > span { width: 76px; color: var(--text-dim); font-size: 13px; flex: none; } .ai-row .settings-input { flex: 1; width: auto; } .ai-vision-row input { width: 17px; height: 17px; accent-color: var(--accent); } .ai-vision-row small { color: var(--text-dim); font-size: 12px; } .ai-actions { justify-content: flex-end; } .ai-hint { flex: 1; min-width: 0; color: var(--text-dim); font-size: 12px; line-height: 1.5; } .settings-input:focus { outline: none; border-color: var(--accent); } .source-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 24px; padding: 10px 0 14px; } .source-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; font-size: 13px; cursor: pointer; } .source-row input { accent-color: var(--accent); } .settings-path { margin-top: 6px; padding: 6px 10px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 6px; font-family: Consolas, monospace; font-size: 11px; color: var(--text-dim); word-break: break-all; } .switch input { width: 38px; height: 20px; accent-color: var(--accent); cursor: pointer; } @media (max-width: 720px) { .titlebar-left { margin-right: 8px; } .brand-sub { display: none; } .tab { padding: 0 10px; } .notes-page { grid-template-columns: 1fr; gap: 12px; } .library-page { grid-template-columns: 1fr; gap: 12px; } .library-sidebar { position: static; max-height: none; overflow-y: visible; scrollbar-gutter: auto; } .library-search { width: 100%; flex-wrap: wrap; } .library-search input { min-width: 180px; flex: 1; width: auto; } .notes-sidebar { position: static; } #notesCollectionList { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } .notes-toolbar { align-items: stretch; flex-direction: column; } .notes-search { flex-wrap: wrap; } #notesSearchInput { flex: 1 1 220px; width: auto; } .notes-toolbar > .source-select { align-self: flex-start; } .notes-type-tabs { max-width: 100%; overflow-x: auto; } .note-type-choice-grid { grid-template-columns: 1fr; } .note-card-footer { align-items: flex-start; flex-direction: column; } .note-actions { align-self: flex-end; } .source-list { grid-template-columns: 1fr; } .settings-item:not(.settings-item-block) { align-items: stretch; flex-wrap: wrap; } .settings-item:not(.settings-item-block) .settings-item-info { flex-basis: 100%; } .settings-input { flex: 1; width: auto; } .ai-actions { align-items: flex-end; flex-wrap: wrap; } .ai-hint { flex-basis: 100%; } } /* 弹窗 */ .modal { position: fixed; inset: 0; z-index: 50; background: var(--modal-overlay); display: flex; align-items: center; justify-content: center; } .modal-box { width: 420px; max-width: 90vw; background: var(--bg-card); border: 1px solid var(--line); border-radius: 14px; padding: 20px; } .modal-title { font-size: 16px; font-weight: 700; margin-bottom: 12px; } .modal-body { font-size: 13px; color: var(--text-dim); line-height: 1.6; margin-bottom: 18px; } .modal-body input[type="text"], .modal-input { width: 100%; height: 32px; margin-top: 8px; background: var(--input-bg); border: 1px solid var(--line); border-radius: 8px; padding: 0 12px; color: var(--text); font-size: 13px; outline: none; } .modal-body input[type="text"]:focus, .modal-input:focus { border-color: var(--accent); } .modal-actions { display: flex; justify-content: flex-end; gap: 10px; } .modal-actions > .tb-btn { width: 72px; height: 32px; padding: 0; } /* 滚动条 */ ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 6px; } ::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-hover); }