Files
Arcrun/landing/app/mira/mira.css
T
Leo 933ae6cb13 feat(mira): 7B.3g wiki UI 樹狀渲染 + 跨 wiki 連結
對應 polaris/mira/.agents/specs/mira-app/design.md §5.2 + §3.5.12。

`/mira/wiki/[pageName]`:
- 抓 wiki-page 後平行撈所有 wiki-paragraph / triplet / wiki-page,client-side 用 parent_id filter
  (KBDB 沒 parent_id server filter,且 tag filter 還有 KI-3 bug)
- 按 facet 分區渲染:facet 標題 + paragraph markdown + 該段的 triplets
- facet 預設展開(看一篇要看內容)/ triplets 預設折疊(leo Logseq outliner 習慣)
- **triplet A/B 拆字串 「A >> 關係 >> B」**,若 A 或 B 對得上既有 wiki entity → render 成 <Link>
  跨 wiki 跳轉,是 Wikipedia-like 體驗的關鍵
- fallback:非 wiki-page block(schema/index/log 等)直接 render content

`/mira/wiki`:列表用 wiki-page 的 content (= entity 名稱) 當標題,不是 page_name slug。

mira.css 加 `.mira-wiki-detail` 不破版 + h2 底線,避免長 cypher 字串撐爆右邊界。

TS check pass。
2026-05-14 13:35:54 +08:00

778 lines
18 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.
/* Mira — 社群貼文式 KM 河道
* 視覺參考:Facebook / X / LinkedIn
* Scope 在 .mira-app 容器內,避免汙染 landing 的 Tailwind 樣式
*/
.mira-app {
/* Surfaces */
--mira-bg-0: #0e0e0d;
--mira-bg-1: #1a1a18;
--mira-bg-2: #252320;
--mira-bg-3: #302d28;
--mira-line: #2e2c27;
--mira-line-soft: #1f1d1a;
/* Text — 高對比 */
--mira-text-1: #f0eee8;
--mira-text-2: #c9c4b8;
--mira-text-3: #9c968a;
--mira-text-4: #6c685e;
--mira-accent: oklch(0.78 0.13 75);
--mira-accent-soft: oklch(0.78 0.13 75 / 0.16);
--mira-accent-line: oklch(0.78 0.13 75 / 0.4);
--mira-conflict: oklch(0.72 0.14 30);
--mira-conflict-soft: oklch(0.72 0.14 30 / 0.13);
--mira-src-logseq: oklch(0.75 0.08 250);
--mira-src-mobile: oklch(0.78 0.07 160);
--mira-src-tg: oklch(0.78 0.08 220);
--mira-src-rss: oklch(0.78 0.08 30);
--mira-src-ai: oklch(0.82 0.10 95);
--mira-radius-sm: 6px;
--mira-radius: 10px;
--mira-radius-lg: 14px;
--mira-font-zh: "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", system-ui, sans-serif;
--mira-font-en: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
--mira-font-mono: "JetBrains Mono", "SF Mono", Menlo, monospace;
background: var(--mira-bg-0);
color: var(--mira-text-1);
font-family: var(--mira-font-zh);
/* 不啟用 palt:保留中文標點全寬,避免標點看起來只有半寬 */
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
letter-spacing: 0.01em;
line-height: 1.65;
min-height: calc(100vh - 73px);
}
.mira-app .mira-num,
.mira-app .mira-en {
font-family: var(--mira-font-en);
letter-spacing: 0;
}
.mira-app .mira-content {
max-width: 920px;
margin: 0 auto;
padding: 24px 16px 80px;
}
@media (max-width: 640px) {
.mira-app .mira-content {
padding: 12px 0 60px;
}
}
/* ── card 卡片 ── */
.mira-app .mira-card {
background: var(--mira-bg-1);
border: 1px solid var(--mira-line);
border-radius: var(--mira-radius);
margin-bottom: 12px;
/* 不要 overflow: hidden — 會 clip ⋮ menu dropdown */
position: relative;
}
@media (max-width: 640px) {
.mira-app .mira-card {
border-radius: 0;
border-left: none;
border-right: none;
margin-bottom: 8px;
}
}
/* ── composer 寫貼文 ── */
.mira-app .mira-composer-card {
padding: 14px 16px;
}
.mira-app .mira-composer-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.mira-app .mira-composer-textarea {
flex: 1;
min-width: 0;
background: transparent;
border: none;
outline: none;
resize: none;
font-family: inherit;
font-size: 16px;
line-height: 1.65;
color: var(--mira-text-1);
padding: 8px 0;
}
.mira-app .mira-composer-textarea::placeholder {
color: var(--mira-text-3);
}
.mira-app .mira-composer-actions {
display: flex;
align-items: center;
gap: 10px;
padding-top: 10px;
margin-top: 8px;
border-top: 1px solid var(--mira-line-soft);
margin-left: 52px;
flex-wrap: wrap;
}
/* ── avatar ── */
.mira-app .mira-avatar {
border-radius: 50%;
flex-shrink: 0;
background: var(--mira-bg-2);
object-fit: cover;
}
.mira-app .mira-avatar-fallback {
display: grid;
place-items: center;
background: linear-gradient(135deg, var(--mira-bg-2), var(--mira-bg-3));
color: var(--mira-text-1);
font-weight: 600;
font-family: var(--mira-font-en);
}
/* ── post 貼文 ── */
.mira-app .mira-post {
display: flex;
flex-direction: column;
}
.mira-app .mira-post-header {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px 10px;
}
.mira-app .mira-post-author {
flex: 1;
min-width: 0;
}
.mira-app .mira-post-name {
font-size: 14.5px;
font-weight: 600;
color: var(--mira-text-1);
line-height: 1.3;
}
.mira-app .mira-post-time {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: var(--mira-text-3);
font-family: var(--mira-font-en);
margin-top: 2px;
}
/* ── post body 內文 ── */
.mira-app .mira-post-body {
padding: 0 16px 12px;
}
.mira-app .mira-post-content {
font-size: 15px;
line-height: 1.7;
color: var(--mira-text-1);
word-break: break-word;
white-space: normal;
}
.mira-app .mira-post-content-full {
/* 展開模式:顯示每個 sub-block 為獨立行,可編輯 */
font-size: 14.5px;
}
/* react-markdown render 樣式 */
.mira-app .mira-md > *:first-child { margin-top: 0; }
.mira-app .mira-md > *:last-child { margin-bottom: 0; }
.mira-app .mira-md p {
margin: 0 0 8px;
line-height: 1.7;
}
.mira-app .mira-md h1,
.mira-app .mira-md h2,
.mira-app .mira-md h3,
.mira-app .mira-md h4,
.mira-app .mira-md h5,
.mira-app .mira-md h6 {
margin: 14px 0 6px;
font-weight: 700;
color: var(--mira-text-1);
line-height: 1.3;
}
.mira-app .mira-md h1 { font-size: 1.5em; }
.mira-app .mira-md h2 { font-size: 1.3em; }
.mira-app .mira-md h3 { font-size: 1.15em; font-weight: 600; }
.mira-app .mira-md h4,
.mira-app .mira-md h5,
.mira-app .mira-md h6 { font-size: 1em; font-weight: 600; }
.mira-app .mira-md ul,
.mira-app .mira-md ol {
margin: 4px 0 8px;
padding-left: 22px;
}
.mira-app .mira-md ul {
list-style: disc;
}
.mira-app .mira-md ul ul {
list-style: circle;
}
.mira-app .mira-md ul ul ul {
list-style: square;
}
.mira-app .mira-md ol {
list-style: decimal;
}
.mira-app .mira-md ul ul,
.mira-app .mira-md ul ol,
.mira-app .mira-md ol ul,
.mira-app .mira-md ol ol {
margin: 4px 0;
}
.mira-app .mira-md li {
margin: 2px 0;
line-height: 1.7;
}
/* GFM task list 的 li 不顯示 bulletcheckbox 取代)*/
.mira-app .mira-md li:has(> input[type="checkbox"]) {
list-style: none;
margin-left: -22px;
}
.mira-app .mira-md li > p {
margin: 0;
}
.mira-app .mira-md blockquote {
margin: 8px 0;
padding: 4px 12px;
border-left: 3px solid var(--mira-line);
color: var(--mira-text-2);
background: var(--mira-bg-2);
border-radius: 0 4px 4px 0;
}
.mira-app .mira-md blockquote p:last-child { margin-bottom: 0; }
.mira-app .mira-md hr {
border: none;
border-top: 1px solid var(--mira-line);
margin: 16px 0;
}
.mira-app .mira-md code {
font-family: var(--mira-font-mono);
font-size: 0.9em;
background: var(--mira-bg-2);
padding: 1px 5px;
border-radius: 4px;
border: 1px solid var(--mira-line-soft);
}
.mira-app .mira-md pre {
margin: 8px 0;
padding: 12px;
background: var(--mira-bg-2);
border: 1px solid var(--mira-line-soft);
border-radius: 6px;
overflow-x: auto;
}
.mira-app .mira-md pre code {
background: transparent;
border: none;
padding: 0;
font-size: 0.85em;
line-height: 1.6;
}
.mira-app .mira-md table {
border-collapse: collapse;
margin: 8px 0;
width: 100%;
font-size: 0.95em;
}
.mira-app .mira-md th,
.mira-app .mira-md td {
border: 1px solid var(--mira-line);
padding: 6px 10px;
text-align: left;
}
.mira-app .mira-md th {
background: var(--mira-bg-2);
color: var(--mira-text-1);
font-weight: 600;
}
.mira-app .mira-md tr:nth-child(even) {
background: rgba(255, 255, 255, 0.02);
}
.mira-app .mira-md strong { color: var(--mira-text-1); font-weight: 700; }
.mira-app .mira-md em { font-style: italic; }
.mira-app .mira-md del { color: var(--mira-text-3); }
/* GFM task list */
.mira-app .mira-md input[type="checkbox"] {
margin-right: 6px;
vertical-align: middle;
}
/* ── show more ── */
.mira-app .mira-show-more {
background: transparent;
border: none;
color: var(--mira-accent);
font-size: 14px;
cursor: pointer;
padding: 4px 0;
margin-top: 4px;
font-family: inherit;
}
.mira-app .mira-show-more:hover {
text-decoration: underline;
}
/* ── footer 互動列 ── */
.mira-app .mira-post-footer {
display: flex;
align-items: center;
border-top: 1px solid var(--mira-line-soft);
padding: 4px 8px;
margin: 0 8px;
}
.mira-app .mira-action-btn {
background: transparent;
border: none;
color: var(--mira-text-2);
font-size: 13.5px;
font-family: inherit;
padding: 8px 14px;
cursor: pointer;
border-radius: 6px;
display: flex;
align-items: center;
gap: 6px;
transition: background 0.12s, color 0.12s;
}
.mira-app .mira-action-btn:hover,
.mira-app .mira-action-btn:active {
background: var(--mira-bg-2);
color: var(--mira-text-1);
}
.mira-app .mira-action-count {
font-size: 12px;
color: var(--mira-text-3);
font-family: var(--mira-font-en);
}
/* ── replies 對整篇的留言 ── */
.mira-app .mira-post-replies {
background: var(--mira-bg-0);
padding: 8px 16px;
border-top: 1px solid var(--mira-line-soft);
display: flex;
flex-direction: column;
gap: 6px;
}
.mira-app .mira-show-replies {
background: transparent;
border: none;
color: var(--mira-text-2);
font-size: 13px;
cursor: pointer;
padding: 6px 4px;
text-align: left;
font-family: inherit;
font-weight: 500;
}
.mira-app .mira-show-replies:hover {
text-decoration: underline;
}
.mira-app .mira-reply-composer {
display: flex;
gap: 10px;
padding: 10px 16px;
border-top: 1px solid var(--mira-line-soft);
background: var(--mira-bg-0);
align-items: flex-start;
}
/* ── reply line ── */
.mira-app .mira-reply-line {
margin-bottom: 6px;
padding: 8px 10px;
background: var(--mira-bg-1);
border-radius: 16px;
display: flex;
align-items: flex-start;
gap: 8px;
position: relative;
}
.mira-app .mira-reply-line.is-ai {
background: var(--mira-accent-soft);
}
/* reply line 內的 ⋮ 永遠顯示(取代 hover only*/
.mira-app .mira-reply-line .mira-menu-wrap {
opacity: 1;
}
.mira-app .mira-reply-icon {
font-size: 13px;
color: var(--mira-text-2);
flex-shrink: 0;
margin-top: 2px;
}
.mira-app .mira-reply-line.is-ai .mira-reply-icon {
color: var(--mira-accent);
}
.mira-app .mira-reply-content {
font-size: 13.5px;
line-height: 1.6;
color: var(--mira-text-1);
word-break: break-word;
white-space: normal;
}
.mira-app .mira-reply-nested {
margin-left: 20px;
margin-top: 4px;
padding-left: 8px;
border-left: 2px solid var(--mira-line-soft);
}
/* ── source tag ── */
.mira-app .src-tag {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 1px 7px;
border-radius: 999px;
font-size: 11px;
font-family: var(--mira-font-en);
letter-spacing: 0.04em;
background: var(--mira-bg-2);
color: var(--mira-text-2);
border: 1px solid var(--mira-line);
}
.mira-app .src-dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: var(--mira-text-3);
}
.mira-app .src-tag.logseq .src-dot { background: var(--mira-src-logseq); }
.mira-app .src-tag.mobile .src-dot { background: var(--mira-src-mobile); }
.mira-app .src-tag.tg .src-dot { background: var(--mira-src-tg); }
.mira-app .src-tag.rss .src-dot { background: var(--mira-src-rss); }
.mira-app .src-tag.ai .src-dot { background: var(--mira-src-ai); }
/* ── wiki link ── */
.mira-app .wiki-link {
color: var(--mira-accent);
cursor: pointer;
text-decoration: none;
border-bottom: 1px dashed var(--mira-accent-line);
padding-bottom: 1px;
}
.mira-app .wiki-link:hover {
background: var(--mira-accent-soft);
}
/* ── empty state ── */
.mira-app .empty-state {
text-align: center;
padding: 80px 20px;
color: var(--mira-text-2);
font-size: 13px;
}
/* ── icon button ── */
.mira-app .mira-icon-btn {
width: 32px;
height: 32px;
display: grid;
place-items: center;
border-radius: 50%;
cursor: pointer;
color: var(--mira-text-2);
background: transparent;
border: none;
font-size: 14px;
line-height: 1;
padding: 0;
transition: background 0.12s, color 0.12s;
flex-shrink: 0;
}
.mira-app .mira-icon-btn:hover,
.mira-app .mira-icon-btn:active {
background: var(--mira-bg-2);
color: var(--mira-text-1);
}
.mira-app .mira-icon-btn-vertical {
font-size: 20px;
font-weight: 700;
letter-spacing: 0;
}
/* ── ⋮ menu (dropdown) ── */
.mira-app .mira-menu-wrap {
position: relative;
}
.mira-app .mira-menu {
position: absolute;
right: 0;
top: calc(100% + 4px);
min-width: 160px;
background: var(--mira-bg-1);
border: 1px solid var(--mira-line);
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
padding: 4px;
z-index: 10;
display: flex;
flex-direction: column;
gap: 1px;
}
.mira-app .mira-menu-item {
background: transparent;
border: none;
text-align: left;
padding: 10px 14px;
border-radius: 5px;
color: var(--mira-text-1);
font-size: 14px;
cursor: pointer;
font-family: inherit;
transition: background 0.12s;
}
.mira-app .mira-menu-item:hover,
.mira-app .mira-menu-item:active {
background: var(--mira-bg-2);
}
.mira-app .mira-menu-item.danger {
color: var(--mira-conflict);
}
.mira-app .mira-menu-item.danger:hover {
background: var(--mira-conflict-soft);
}
/* ── block-lineFullContent 模式)── */
.mira-app .mira-block-line {
position: relative;
}
.mira-app .mira-block-line .mira-menu-wrap {
opacity: 0;
transition: opacity 0.12s;
}
.mira-app .mira-block-line:hover .mira-menu-wrap {
opacity: 1;
}
@media (hover: none) {
/* 觸控裝置一律顯示 ⋮ */
.mira-app .mira-block-line .mira-menu-wrap {
opacity: 1;
}
}
.mira-app .mira-menu-wrap:has(.mira-menu) { opacity: 1 !important; }
/* ── edit textarea ── */
.mira-app .mira-edit-textarea {
width: 100%;
background: var(--mira-bg-0);
border: 1px solid var(--mira-accent-line);
border-radius: 8px;
padding: 10px 12px;
font-family: inherit;
font-size: 14px;
line-height: 1.7;
color: var(--mira-text-1);
resize: vertical;
outline: none;
}
.mira-app .mira-edit-textarea:focus {
border-color: var(--mira-accent);
}
.mira-app .mira-edit-textarea::placeholder {
color: var(--mira-text-3);
}
.mira-app .mira-edit-actions {
display: flex;
align-items: center;
gap: 8px;
margin-top: 6px;
flex-wrap: wrap;
}
/* ── markdown toolbar ── */
.mira-app .mira-md-toolbar {
display: flex;
align-items: center;
gap: 4px;
padding: 6px 8px;
background: var(--mira-bg-2);
border: 1px solid var(--mira-line);
border-bottom: none;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
flex-wrap: wrap;
}
/* compact 模式:給 PostComposer 的 actions 列 inline 用 */
.mira-app .mira-md-toolbar.compact {
padding: 0;
background: transparent;
border: none;
gap: 2px;
}
.mira-app .mira-md-btn {
background: transparent;
border: none;
width: 28px;
height: 28px;
display: grid;
place-items: center;
border-radius: 5px;
color: var(--mira-text-2);
cursor: pointer;
font-size: 13px;
font-family: inherit;
transition: background 0.12s, color 0.12s;
padding: 0;
line-height: 1;
}
.mira-app .mira-md-btn:hover,
.mira-app .mira-md-btn:active {
background: var(--mira-bg-3);
color: var(--mira-text-1);
}
.mira-app .mira-md-btn em {
font-style: italic;
font-family: serif;
}
.mira-app .mira-md-hint {
margin-left: auto;
font-size: 11px;
color: var(--mira-text-3);
font-family: var(--mira-font-en);
}
/* toolbar 之後的 textarea 接續成一塊 */
.mira-app .mira-md-toolbar + .mira-edit-textarea {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-top: none;
}
/* ── kbd 提示 ── */
.mira-app .mira-kbd {
font-size: 11px;
color: var(--mira-text-3);
font-family: var(--mira-font-en);
}
/* ── messages ── */
.mira-app .mira-msg-error {
font-size: 12px;
color: var(--mira-conflict);
}
.mira-app .mira-error {
padding: 16px;
color: var(--mira-conflict);
font-size: 14px;
}
/* ── buttons ── */
.mira-app .mira-btn-primary {
background: var(--mira-accent);
border: none;
color: var(--mira-bg-0);
font-size: 13px;
padding: 8px 18px;
border-radius: 999px;
cursor: pointer;
font-weight: 600;
font-family: inherit;
transition: opacity 0.12s, background 0.12s;
}
.mira-app .mira-btn-primary:hover {
opacity: 0.9;
}
.mira-app .mira-btn-primary:disabled,
.mira-app .mira-btn-primary.disabled {
background: var(--mira-bg-3);
color: var(--mira-text-3);
cursor: not-allowed;
opacity: 1;
}
.mira-app .mira-btn-ghost {
background: transparent;
border: 1px solid var(--mira-line);
color: var(--mira-text-2);
font-size: 12px;
padding: 6px 14px;
border-radius: 999px;
cursor: pointer;
font-family: inherit;
}
.mira-app .mira-btn-ghost:hover {
background: var(--mira-bg-2);
color: var(--mira-text-1);
}
/* ── Mira 思考中(AI reply pending)── */
.mira-app .mira-thinking {
opacity: 0.7;
}
.mira-app .mira-thinking-dots::after {
content: '⋯';
display: inline-block;
animation: mira-think-dots 1.4s infinite;
}
@keyframes mira-think-dots {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
/* ── skeleton loader ── */
.mira-app .mira-skel {
height: 60px;
background: linear-gradient(
90deg,
var(--mira-bg-1) 0%,
var(--mira-bg-2) 50%,
var(--mira-bg-1) 100%
);
background-size: 200% 100%;
animation: mira-skel-shimmer 1.4s ease-in-out infinite;
border-radius: 6px;
}
@keyframes mira-skel-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* ── rel time ── */
.mira-app .mira-rel-time {
cursor: default;
}
/* ── Wiki detail (7B.3g 樹狀渲染) ── */
/* .mira-md 已在 §190+ 定義整套 markdown 樣式(河道+wiki 共用),這裡只加 wiki 細節頁的「不破版」保護 */
.mira-app .mira-wiki-detail {
overflow-wrap: break-word;
word-break: break-word;
}
/* 防止長 cypher binding 字串 / URL 撐爆右邊界 */
.mira-app .mira-wiki-detail .mira-md li,
.mira-app .mira-wiki-detail .mira-md p {
overflow-wrap: break-word;
word-break: break-word;
}
/* wiki h2/h3 加底線分隔,更像文章 */
.mira-app .mira-wiki-detail .mira-md h2 {
border-bottom: 1px solid var(--mira-line-soft);
padding-bottom: 4px;
}